diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml new file mode 100644 index 0000000000..2ab7d91ddf --- /dev/null +++ b/.github/workflows/pull-request.yml @@ -0,0 +1,28 @@ +# Run whenever a PR is generated or updated. + +name: Pull Request Checks + +on: + pull_request: + +jobs: + + code-spell: + name: Check spelling + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + submodules: false + - name: Get submodules + run: | + SMING_ARCH=Host make -C Sming submodules + echo "[codespell]" > .codespellrc + echo "skip = $(tr "\n" , < Tools/spelling/skip.txt)" >> .codespellrc + - name: Run codespell + uses: codespell-project/actions-codespell@master + with: + skip: "" # Use resource script entry + ignore_words_file: "Tools/spelling/ignore.txt" + check_filenames: true + only_warn: 1 diff --git a/.gitignore b/.gitignore index a30086cd31..4b6b1485ca 100644 --- a/.gitignore +++ b/.gitignore @@ -7,19 +7,28 @@ docs/build docs/source/_inc *.pyc -# dev tools, editors, etc. +# Eclipse +.project +.cproject language.settings.xml .settings -nbproject -.*.swp +.metadata + +# MS Visual Studio Code .vscode *.code-workspace -GTAGS -GRTAGS -GPATH # Microsoft Visual SourceSafe files vssver2.scc -.metadata +# Other dev tools, editors, etc. +nbproject +.*.swp +GTAGS +GRTAGS +GPATH + +# Tag files created by build system .submodule +*.built +*.completed diff --git a/.gitmodules b/.gitmodules index f0fd7431a8..f617104431 100644 --- a/.gitmodules +++ b/.gitmodules @@ -91,16 +91,12 @@ path = Sming/Arch/Esp8266/Components/lwip2/lwip2 url = https://github.com/mikee47/esp82xx-nonos-linklayer.git ignore = dirty -[submodule "Esp8266.new-pwm"] - path = Sming/Arch/Esp8266/Components/driver/new-pwm - url = https://github.com/StefanBruens/ESP8266_new_pwm.git - ignore = dirty [submodule "Esp8266.umm_malloc"] path = Sming/Arch/Esp8266/Components/heap/umm_malloc url = https://github.com/rhempel/umm_malloc.git ignore = dirty [submodule "Esp8266.Sdk"] - path = Sming/Arch/Esp8266/Components/esp8266/ESP8266_NONOS_SDK + path = Sming/Arch/Esp8266/Components/esp8266/sdk url = https://github.com/espressif/ESP8266_NONOS_SDK.git ignore = dirty @@ -112,6 +108,20 @@ ### NONE ### +# +# `Rp2040` Components +# + +[submodule "Rp2040.picotool"] + path = Sming/Arch/Rp2040/Components/picotool/picotool + url = https://github.com/mikee47/picotool + ignore = dirty + +[submodule "Rp2040.Sdk"] + path = Sming/Arch/Rp2040/Components/rp2040/pico-sdk + url = https://github.com/raspberrypi/pico-sdk + ignore = dirty + # # `Host` Components # @@ -143,6 +153,10 @@ path = Sming/Libraries/Adafruit_BME280_Library url = https://github.com/adafruit/Adafruit_BME280_Library.git ignore = dirty +[submodule "Libraries.Adafruit_BusIO"] + path = Sming/Libraries/Adafruit_BusIO + url = https://github.com/adafruit/Adafruit_BusIO + ignore = dirty [submodule "Libraries.Adafruit_Sensor"] path = Sming/Libraries/Adafruit_Sensor url = https://github.com/adafruit/Adafruit_Sensor @@ -211,6 +225,10 @@ path = Sming/Libraries/HueEmulator url = https://github.com/mikee47/HueEmulator ignore = dirty +[submodule "Libraries.jerryscript"] + path = Sming/Libraries/jerryscript + url = https://github.com/slaff/Sming-jerryscript.git + ignore = dirty [submodule "Libraries.IR"] path = Sming/Libraries/IR url = https://github.com/markszabo/IRremoteESP8266.git @@ -231,6 +249,10 @@ path = Sming/Libraries/MDNS url = https://github.com/mikee47/Sming-MDNS ignore = dirty +[submodule "Libraries.MHZ19"] + path = Sming/Libraries/MHZ19 + url = https://github.com/mikee47/Sming-MHZ19 + ignore = dirty [submodule "Libraries.modbusino"] path = Sming/Libraries/modbusino/modbusino url = https://github.com/kmihaylov/modbusino.git @@ -255,6 +277,10 @@ path = Sming/Libraries/RapidXML url = https://github.com/mikee47/Sming-RapidXML ignore = dirty +[submodule "Libraries.rbpf"] + path = Sming/Libraries/rbpf + url = https://github.com/slaff/Sming-rbpf.git + ignore = dirty [submodule "Libraries.RingBufCPP"] path = Sming/Libraries/RingBufCPP url = https://github.com/wizard97/Embedded_RingBuf_CPP.git @@ -268,7 +294,7 @@ url = https://github.com/mikee47/SignalGenerator ignore = dirty [submodule "Libraries.simpleRPC"] - path = Sming/Libraries/simpleRPC/simpleRPC + path = Sming/Components/simpleRPC/simpleRPC url = https://github.com/jfjlaros/simpleRPC.git ignore = dirty [submodule "Libraries.SmingTest"] @@ -279,7 +305,7 @@ path = Sming/Libraries/SolarCalculator url = https://github.com/mikee47/SolarCalculator ignore = dirty -[submodule "spiffs"] +[submodule "Libraries.spiffs"] path = Sming/Libraries/Spiffs/spiffs url = https://github.com/pellepl/spiffs.git ignore = dirty diff --git a/README.md b/README.md index 8fd27ca177..83ab9aee4e 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # Sming -Sming is an asynchronous C/C++ framework with superb performance and multiple network features. -Sming is [open source](LICENSE) and is tailored towards embedded devices. -It supports multiple architectures as ESP8266 for example. -[![ESP8266 C++ development framework](https://github.com/SmingHub/Sming/wiki/images/small/combine.png)](https://github.com/SmingHub/Sming/wiki/examples) +Sming is an asynchronous embedded C/C++ framework with superb performance and multiple network features. +Sming is [open source](LICENSE), modular and supports [multiple architectures](https://sming.readthedocs.io/en/latest/features.html) including ESP8266 and ESP32. + +[![Examples](https://github.com/SmingHub/Sming/wiki/images/small/combine.png)](https://github.com/SmingHub/Sming/wiki/examples) [![Gitter (chat)](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/SmingHub/Sming?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![Backers](https://opencollective.com/Sming/backers/badge.svg)](#financial-contributions) @@ -18,106 +18,26 @@ If you like **Sming**, give it a star, or fork it and [contribute](#contribute)! [![GitHub stars](https://img.shields.io/github/stars/SmingHub/Sming.svg?style=social&label=Star)](https://github.com/SmingHub/Sming/stargazers) [![GitHub forks](https://img.shields.io/github/forks/SmingHub/Sming.svg?style=social&label=Fork)](https://github.com/SmingHub/Sming/network) +## Getting Started + +Sming supports multiple architectures and has a [plethora of features](https://sming.readthedocs.io/en/latest/index.html#summary). +Choose the architecture of your choice to [install the needed development software](https://sming.readthedocs.io/en/latest/getting-started). + +You can also try Sming without installing anything locally. We have an [interactive tutorial](https://www.katacoda.com/slaff/scenarios/sming-host-emulator) that can be run directly from your browser. + +## Documentation -Table of Contents -================= - - - * [Sming](#sming) - * [Table of Contents](#table-of-contents) - * [Summary](#summary) - * [Compatibility](#compatibility) - * [GCC compiler >= 8](#gcc-compiler--8) - * [Architecture: ESP8266](#architecture-esp8266) - * [Architecture: Host](#architecture-host) - * [Architecture: ESP32 (Experimental)](#architecture-esp32-experimental) - * [Releases](#releases) - * [Stable](#stable) - * [Long Term Support (LTS)](#long-term-support-lts) - * [Development](#development) - * [Getting Started](#getting-started) - * [Documentation](#documentation) - * [Examples](#examples) - * [Basic Blink](#basic-blink) - * [Simple GPIO Input/Output](#simple-gpio-inputoutput) - * [Start Serial Communication](#start-serial-communication) - * [Connect to WiFi](#connect-to-wifi) - * [Read DHT22 sensor](#read-dht22-sensor) - * [HTTP Client](#http-client) - * [OTA Application Update](#ota-application-update) - * [HTTP Server](#http-server) - * [Email Client](#email-client) - * [Live Debugging](#live-debugging) - * [Contribute](#contribute) - * [Financial contributions](#financial-contributions) - * [Backers and sponsors](#backers-and-sponsors) - - -Please note Version 4 documentation is at [sming.readthedocs.io](https://sming.readthedocs.io/). - -## Summary - -* Superb performance and memory usage (Sming compiles to native firmware!). -* Fast and user friendly development. -* Simple yet powerful hardware API wrappers. -* Compatible with standard [Arduino Libraries](https://sming.readthedocs.io/en/latest/libraries.html) - use any popular hardware in few lines of code. -* Built-in file system: [spiffs](https://github.com/pellepl/spiffs). -* Built-in powerful wireless modules. -* Powerful asynchronous (async) network stack. - * Async TCP and UDP stack based on [LWIP](http://savannah.nongnu.org/projects/lwip/). - * With clients supporting: HTTP, MQTT, WebSockets and SMTP. - * And servers for: DNS, FTP, HTTP(+ WebSockets), Telnet. - * With [SSL support](https://sming.readthedocs.io/en/latest/_inc/Sming/Components/ssl/index.html) for all network clients and servers. Based on [axTLS](http://axtls.sourceforge.net/) and [BearSSL](https://www.bearssl.org/). - * Over-The-Air(OTA) firmware upgrades via HTTP(S) and MQTT(S). -* ESP8266 specific features. - * Integrated boot loader [rboot](https://sming.readthedocs.io/en/latest/_inc/Sming/Components/rboot/index.html) with support for 1MB ROMs, OTA firmware updating and ROM switching. - * [Crash handlers](https://sming.readthedocs.io/en/latest/information/debugging.html) for analyzing/handling system restarts due to fatal errors or WDT resets. - * [PWM support](https://sming.readthedocs.io/en/latest/_inc/Sming/Arch/Esp8266/Components/driver/index.html) based on [Stefan Bruens PWM](https://github.com/StefanBruens/ESP8266_new_pwm.git). - * Optional [custom heap allocation](https://sming.readthedocs.io/en/latest/_inc/Sming/Arch/Esp8266/Components/heap/index.html) based on [Umm Malloc](https://github.com/rhempel/umm_malloc.git). - * Based on Espressif NONOS SDK. Officially suppored NON SDK version is >= 3.0.1. - * Support for a [thin No-Wifi-SDK](https://sming.readthedocs.io/en/latest/_inc/Sming/Arch/Esp8266/Components/esp_no_wifi/index.html). Helpful when a project does not require WiFi (or networking) and reduces code size and memory usage signficantly. -* Linux/Windows features - * Sming has a [host emulator](https://sming.readthedocs.io/en/latest/arch/host/index.html) that allows libraries and sample applications to be compiled on a Linux/Windows host system and be tested before uploading them to an actual microcontroller. - -## Compatibility - - -### GCC compiler >= 8 - -Your GCC compiler should be version 8 or newer! See the different architectures for details. -Newer compilers - -- contain bugfixes -- produce smaller and better code -- have features which facilitate code quality, ease of use, etc. - -### Architecture: ESP8266 - -OS/SDK | Linux | Mac OS X | Windows | FreeBSD-current | --------|-------|----------|---------|-----------------| -UDK (v1.5)    | n/a   | n/a      |   [![Build status](https://ci.appveyor.com/api/projects/status/5aj0oi0wyk4uij00/branch/develop?svg=true)](https://ci.appveyor.com/project/slaff/sming-sb483/branch/develop)      |     n/a         | -esp-open-sdk (v1.5.x **, v2.0.0 **, v3.0.x) | :sunny:  | :sunny: | n/a | :sunny: | - -- OS = Operating System. -- SDK = Software Development Kit. -- n/a = The selected SDK is not available on that OS. -- ** = not supported officially. Samples and library should compile and run but we recommend using version >= 3.0.3. - -### Architecture: Host - -Linux and Windows OSes with gcc compilers are supported. Clang is NOT supported. - - -### Architecture: ESP32 (Experimental) - -Supported SDK: ESP-IDF v4.3. See https://sming.readthedocs.io/en/latest/_inc/Sming/Arch/Esp32/README.html. +The purpose of Sming is to simplify the creation of embedded applications. The documentation will help you get started in no time. +- [**Documentation for version 4.5.0**](https://sming.readthedocs.io/en/stable) - current stable version. +- [Documentation for version 4.2.x](https://sming.readthedocs.io/en/4.2.2) - Long Term Support (LTS) version. +- [Documentation for latest](https://sming.readthedocs.io/en/latest) - development version. ## Releases ### Stable -- [Sming V4.4.1](https://github.com/SmingHub/Sming/releases/tag/4.4.1) - great new features, performance and stability improvements. +- [Sming V4.5.0](https://github.com/SmingHub/Sming/releases/tag/4.5.0) - great new features, performance and stability improvements. ### Long Term Support (LTS) @@ -134,16 +54,6 @@ git clone https://github.com/SmingHub/Sming.git ``` -## Getting Started - -Sming supports multiple architectures. Choose the architecture of your choice to [install the needed development software](https://sming.readthedocs.io/en/latest/getting-started) and toolchain(s). - -You can also try Sming without installing anything locally. We have an [interactive tutorial](https://www.katacoda.com/slaff/scenarios/sming-host-emulator) that can be run directly from your browser. - -## Documentation -In addition to our [online documentation](https://sming.readthedocs.io/), -you can also generate a complete documentation locally by following these [instructions](https://sming.readthedocs.io/en/latest/_inc/docs/README.html). - ## Examples The examples are a great way to learn the API and brush up your C/C++ knowledge. @@ -175,7 +85,7 @@ make # -- compiles the application make flash # -- tries to upload the application to your ESP8266 device. ``` -More information at **[Wiki Examples](https://github.com/SmingHub/Sming/wiki/examples)** page. +More information at **[Sample Projects](https://sming.readthedocs.io/en/latest/samples.html)** page. ### Simple GPIO Input/Output ```c++ diff --git a/Sming/Arch/Esp32/Components/driver/uart.cpp b/Sming/Arch/Esp32/Components/driver/uart.cpp index 34752c9d76..78a14e48c2 100644 --- a/Sming/Arch/Esp32/Components/driver/uart.cpp +++ b/Sming/Arch/Esp32/Components/driver/uart.cpp @@ -2,23 +2,23 @@ uart.cpp - esp32 UART HAL */ -#include - -#include -#include -#include -#include -#include - -// These conflict with enumerated types defined in IDF - values are same though +// #define typeof(x) std::remove_volatile::type +#define typeof(x) decltype(x) +// These conflict with enumerated types defined in IDF +#define UART_PARITY_NONE IDF_UART_PARITY_NONE +#define UART_PARITY_EVEN IDF_UART_PARITY_EVEN +#define UART_PARITY_ODD IDF_UART_PARITY_ODD +#include #undef UART_PARITY_NONE #undef UART_PARITY_EVEN #undef UART_PARITY_ODD -// #define typeof(x) std::remove_volatile::type -#define typeof(x) decltype(x) -#include +#include +#include #include +#include +#include +#include namespace { @@ -50,17 +50,17 @@ struct smg_uart_pins_t { uint8_t rx; }; -#ifdef SUBARCH_ESP32 +#ifdef SOC_ESP32 #define UART0_PIN_DEFAULT UART_NUM_0_TXD_DIRECT_GPIO_NUM, UART_NUM_0_RXD_DIRECT_GPIO_NUM #define UART1_PIN_DEFAULT 18, 19 // Defaults conflict with flash #define UART2_PIN_DEFAULT UART_NUM_2_TXD_DIRECT_GPIO_NUM, UART_NUM_2_RXD_DIRECT_GPIO_NUM -#elif defined(SUBARCH_ESP32C3) +#elif defined(SOC_ESP32C3) #define UART0_PIN_DEFAULT 21, 20 #define UART1_PIN_DEFAULT UART_NUM_1_TXD_DIRECT_GPIO_NUM, UART_NUM_1_RXD_DIRECT_GPIO_NUM -#elif defined(SUBARCH_ESP32S2) +#elif defined(SOC_ESP32S2) #define UART0_PIN_DEFAULT 43, 44 #define UART1_PIN_DEFAULT UART_NUM_1_TXD_DIRECT_GPIO_NUM, UART_NUM_1_RXD_DIRECT_GPIO_NUM -#elif defined(SUBARCH_ESP32S3) +#elif defined(SOC_ESP32S3) #define UART0_PIN_DEFAULT 43, 44 #define UART1_PIN_DEFAULT UART_NUM_1_TXD_DIRECT_GPIO_NUM, UART_NUM_1_RXD_DIRECT_GPIO_NUM #define UART2_PIN_DEFAULT UART_NUM_2_TXD_DIRECT_GPIO_NUM, UART_NUM_2_RXD_DIRECT_GPIO_NUM @@ -132,11 +132,6 @@ void notify(smg_uart_t* uart, smg_uart_notify_code_t code) } } -__forceinline bool uart_isr_enabled(uint8_t nr) -{ - return bitRead(isrMask, nr); -} - /** @brief Determine if the given uart is a real uart or a virtual one */ __forceinline bool is_physical(int uart_nr) @@ -241,7 +236,7 @@ void IRAM_ATTR uart_isr(smg_uart_instance_t* inst) if(usis.rxfifo_ovf) { uart_ll_disable_intr_mask(dev, UART_INTR_RXFIFO_OVF); } else if(read == 0) { - uart_ll_ena_intr_mask(dev, UART_INTR_RXFIFO_FULL | UART_INTR_RXFIFO_TOUT); + uart_ll_disable_intr_mask(dev, UART_INTR_RXFIFO_FULL | UART_INTR_RXFIFO_TOUT); } } @@ -838,7 +833,6 @@ void smg_uart_debug_putc(char c) void smg_uart_set_debug(int uart_nr) { s_uart_debug_nr = uart_nr; - system_set_os_print(uart_nr >= 0); ets_install_putc1(smg_uart_debug_putc); ets_install_putc2(nullptr); } diff --git a/Sming/Arch/Esp32/Components/esp32/README.rst b/Sming/Arch/Esp32/Components/esp32/README.rst index 94c906a6ee..d1419ec950 100644 --- a/Sming/Arch/Esp32/Components/esp32/README.rst +++ b/Sming/Arch/Esp32/Components/esp32/README.rst @@ -21,13 +21,6 @@ Followed by:: Configuration variables ----------------------- -Option variables: - -.. envvar:: ESP_VARIANT - - Build for for esp32 or esp32s2 device - - The following variables may need to be changed if tools are installed in a different location, or if multiple versions are installed. By default, the most current version will be used. @@ -58,14 +51,14 @@ Background An empty ESP IDF project is built which generates a set of libraries and headers which the framework can then be built against. -The project is located in ``project/{ESP_VARIANT}`. +The project is located in ``project/{SMING_SOC}``. The code for this project is copied from ``sdk/project``. The default configuration settings are obtained from ``sdk/config`` and written -to ``project/{ESP_VARIANT}/sdkconfig.defaults``. +to ``project/{SMING_SOC}/sdkconfig.defaults``. -When ``sdk-menuconfig`` is run, the ``project/{ESP_VARIANT}/sdkconfig`` is modified. +When ``sdk-menuconfig`` is run, the ``project/{SMING_SOC}/sdkconfig`` is modified. This can be reset using ``make sdk-config-clean``. If custom settings are required for a project then place these in a separate file diff --git a/Sming/Arch/Esp32/Components/esp32/component.mk b/Sming/Arch/Esp32/Components/esp32/component.mk index 002f489da1..b60596d355 100644 --- a/Sming/Arch/Esp32/Components/esp32/component.mk +++ b/Sming/Arch/Esp32/Components/esp32/component.mk @@ -1,7 +1,5 @@ SDK_COMPONENTS_PATH := $(IDF_PATH)/components -# See build.mk for default ESP_VARIANT - determines toolchain - COMPONENT_DEPENDS := libc COMPONENT_SRCDIRS := src @@ -24,15 +22,19 @@ SDK_LIBDIRS := \ $(ESP_VARIANT)/ld \ esp_rom/$(ESP_VARIANT)/ld +ESP32_COMPONENT_PATH := $(COMPONENT_PATH) +SDK_DEFAULT_PATH := $(ESP32_COMPONENT_PATH)/sdk + LIBDIRS += \ $(SDK_COMPONENT_LIBDIR) \ $(SDK_BUILD_BASE)/esp-idf/mbedtls/mbedtls/library \ $(SDK_BUILD_BASE)/esp-idf/$(ESP_VARIANT) \ $(SDK_BUILD_BASE)/esp-idf/$(ESP_VARIANT)/ld \ - $(COMPONENT_PATH)/ld \ + $(ESP32_COMPONENT_PATH)/ld \ $(addprefix $(SDK_COMPONENTS_PATH)/,$(SDK_LIBDIRS)) SDK_INCDIRS := \ + app_update/include \ bootloader_support/include \ bootloader_support/include_bootloader \ driver/$(ESP_VARIANT)/include \ @@ -151,11 +153,6 @@ ifeq ($(ESP_VARIANT),esp32) SDK_ESP_WIFI_LIBS += rtc endif -SDK_NEWLIB_LIBS := \ - c \ - m \ - stdc++ - ifdef IDF_TARGET_ARCH_RISCV SDK_TARGET_ARCH_LIBS := hal else @@ -163,9 +160,7 @@ SDK_TARGET_ARCH_LIBS := hal xt_hal endif EXTRA_LIBS := \ - gcc \ $(SDK_COMPONENTS) \ - $(SDK_NEWLIB_LIBS) \ $(SDK_TARGET_ARCH_LIBS) ifneq ($(DISABLE_WIFI),1) @@ -196,23 +191,18 @@ LDFLAGS_esp32s3 := \ $(call LinkerScript,rom.newlib-data) \ $(call LinkerScript,rom.spiflash) +SDK_WRAP_SYMBOLS := +SDK_UNDEF_SYMBOLS := + +$(foreach c,$(wildcard $(SDK_DEFAULT_PATH)/*.mk),$(eval include $c)) + EXTRA_LDFLAGS := \ - -u esp_app_desc \ - -u __cxa_guard_dummy -u __cxx_fatal_exception \ -T $(ESP_VARIANT)_out.ld \ - -u ld_include_panic_highint_hdl \ $(call LinkerScript,project) \ $(call LinkerScript,peripherals) \ $(call LinkerScript,rom) \ $(call LinkerScript,rom.api) \ $(call LinkerScript,rom.libgcc) \ - -u newlib_include_locks_impl \ - -u newlib_include_heap_impl \ - -u newlib_include_syscalls_impl \ - -u pthread_include_pthread_impl \ - -u pthread_include_pthread_cond_impl \ - -u pthread_include_pthread_local_storage_impl \ - -Wl,--undefined=uxTopUsedPriority \ $(call Wrap,\ esp_event_loop_create_default \ esp_event_handler_register \ @@ -221,10 +211,12 @@ EXTRA_LDFLAGS := \ esp_event_handler_instance_unregister \ esp_event_post \ esp_event_isr_post) \ - $(LDFLAGS_$(ESP_VARIANT)) + $(LDFLAGS_$(ESP_VARIANT)) \ + $(call Undef,$(SDK_UNDEF_SYMBOLS)) \ + $(call Wrap,$(SDK_WRAP_SYMBOLS)) + -SDK_DEFAULT_PATH := $(COMPONENT_PATH)/sdk -SDK_PROJECT_PATH := $(COMPONENT_PATH)/project/$(ESP_VARIANT)/$(BUILD_TYPE) +SDK_PROJECT_PATH := $(ESP32_COMPONENT_PATH)/project/$(ESP_VARIANT)/$(BUILD_TYPE) SDK_CONFIG_DEFAULTS := $(SDK_PROJECT_PATH)/sdkconfig.defaults SDKCONFIG_MAKEFILE := $(SDK_PROJECT_PATH)/sdkconfig @@ -248,12 +240,20 @@ export SDK_BUILD_BASE export SDK_COMPONENT_LIBDIR export SDK_COMPONENTS -CUSTOM_TARGETS += checksdk +ifndef MAKE_CLEAN +.PHONY: checkdirs +checkdirs: | checksdk .PHONY: checksdk checksdk: $(SDK_PROJECT_PATH) $(SDKCONFIG_H) $(SDKCONFIG_MAKEFILE) $(Q) $(NINJA) -C $(SDK_BUILD_BASE) bootloader app - $(Q) $(MAKE) --no-print-directory -C $(SDK_DEFAULT_PATH) -f misc.mk copylibs + $(Q) $(MAKE) --no-print-directory -C $(ESP32_COMPONENT_PATH) -f misc.mk copylibs + +.PHONY: reconfigure-sdk +reconfigure-sdk: + $(Q) $(SDK_BUILD) reconfigure + +$(COMPONENT_NAME)-build: reconfigure-sdk $(SDKCONFIG_H) $(SDKCONFIG_MAKEFILE) $(SDK_COMPONENT_LIBS): $(SDK_PROJECT_PATH) $(SDK_CONFIG_DEFAULTS) | $(SDK_BUILD_BASE) $(SDK_COMPONENT_LIBDIR) $(Q) $(SDK_BUILD) reconfigure @@ -263,6 +263,7 @@ $(SDK_PROJECT_PATH): $(Q) cp -r $(SDK_DEFAULT_PATH)/project/* $@ $(SDK_COMPONENT_LIBS): checksdk +endif SDK_CONFIG_FILES := \ common \ @@ -309,7 +310,3 @@ sdk-help: ##Get SDK build options .PHONY: sdk sdk: ##Pass options to IDF builder, e.g. `make sdk -- --help` or `make sdk menuconfig` $(Q) $(SDK_BUILD) $(filter-out sdk,$(MAKECMDGOALS)) - -.PHONY: checkdirs -checkdirs: | checksdk - diff --git a/Sming/Arch/Esp32/Components/esp32/include/espinc/lwip_includes.h b/Sming/Arch/Esp32/Components/esp32/include/espinc/lwip_includes.h deleted file mode 100644 index 013cae1a8e..0000000000 --- a/Sming/Arch/Esp32/Components/esp32/include/espinc/lwip_includes.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * lwip_includes.h - * - * Created on: 23 ����. 2015 �. - * Author: Anakonda - */ - -#pragma once - -#include "lwip/debug.h" -#include "lwip/dns.h" -#include "lwip/init.h" -#include "lwip/stats.h" -#include "lwip/tcp.h" -#include "lwip/udp.h" -#include "lwipopts.h" diff --git a/Sming/Arch/Esp32/Components/esp32/sdk/misc.mk b/Sming/Arch/Esp32/Components/esp32/misc.mk similarity index 100% rename from Sming/Arch/Esp32/Components/esp32/sdk/misc.mk rename to Sming/Arch/Esp32/Components/esp32/misc.mk diff --git a/Sming/Arch/Esp32/Components/esp32/sdk/app_update.mk b/Sming/Arch/Esp32/Components/esp32/sdk/app_update.mk new file mode 100644 index 0000000000..c70fd37ebe --- /dev/null +++ b/Sming/Arch/Esp32/Components/esp32/sdk/app_update.mk @@ -0,0 +1,7 @@ +# +# app_update +# + +# esp_app_desc structure is added as an undefined symbol because otherwise the +# linker will ignore this structure as it has no other files depending on it. +SDK_UNDEF_SYMBOLS += esp_app_desc diff --git a/Sming/Arch/Esp32/Components/esp32/sdk/config/README.rst b/Sming/Arch/Esp32/Components/esp32/sdk/config/README.rst index 404ff46990..55857c7aa4 100644 --- a/Sming/Arch/Esp32/Components/esp32/sdk/config/README.rst +++ b/Sming/Arch/Esp32/Components/esp32/sdk/config/README.rst @@ -8,8 +8,8 @@ The following files are assembled, in order: common {BUILD_TYPE} - {ESP_VARIANT}.common - {ESP_VARIANT}.{BUILD_TYPE} + {SMING_SOC}.common + {SMING_SOC}.{BUILD_TYPE} {PROJECT_DIR}/{SDK_CUSTOM_CONFIG} Where: diff --git a/Sming/Arch/Esp32/Components/esp32/sdk/config/debug b/Sming/Arch/Esp32/Components/esp32/sdk/config/debug deleted file mode 100644 index 55e48a89ac..0000000000 --- a/Sming/Arch/Esp32/Components/esp32/sdk/config/debug +++ /dev/null @@ -1,17 +0,0 @@ -# -# DEBUG -# - -# The bootloader logs all type of messages -CONFIG_BOOTLOADER_LOG_LEVEL=3 - -# ESP-IDF logs all type of messages -CONFIG_LOG_DEFAULT_LEVEL=3 - -# Sets watchpoint index 1 (the second of two) at the end of any task stack. This is the most accurate way to debug task stack overflows. -CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y - -# Used by TaskStat class to track task usage -CONFIG_FREERTOS_USE_TRACE_FACILITY=y -CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y -CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID=y diff --git a/Sming/Arch/Esp32/Components/esp32/sdk/config/release b/Sming/Arch/Esp32/Components/esp32/sdk/config/release deleted file mode 100644 index 2e3743a7c1..0000000000 --- a/Sming/Arch/Esp32/Components/esp32/sdk/config/release +++ /dev/null @@ -1,10 +0,0 @@ -# -# RELEASE -# - -# The bootloader logs only errors -CONFIG_BOOTLOADER_LOG_LEVEL=1 - -# ESP-IDF logs only errors -CONFIG_LOG_DEFAULT_LEVEL=1 - diff --git a/Sming/Arch/Esp32/Components/esp32/sdk/cxx.mk b/Sming/Arch/Esp32/Components/esp32/sdk/cxx.mk new file mode 100644 index 0000000000..cd150b4cb6 --- /dev/null +++ b/Sming/Arch/Esp32/Components/esp32/sdk/cxx.mk @@ -0,0 +1,57 @@ +# +# cxx +# + +ifndef CONFIG_COMPILER_CXX_EXCEPTIONS +# If exceptions are disabled, ensure our fatal exception +# hooks are preferentially linked over libstdc++ which +# has full exception support +SDK_WRAP_SYMBOLS += \ + _Unwind_SetEnableExceptionFdeSorting \ + __register_frame_info_bases \ + __register_frame_info \ + __register_frame \ + __register_frame_info_table_bases \ + __register_frame_info_table \ + __register_frame_table \ + __deregister_frame_info_bases \ + __deregister_frame_info \ + _Unwind_Find_FDE \ + _Unwind_GetGR \ + _Unwind_GetCFA \ + _Unwind_GetIP \ + _Unwind_GetIPInfo \ + _Unwind_GetRegionStart \ + _Unwind_GetDataRelBase \ + _Unwind_GetTextRelBase \ + _Unwind_SetIP \ + _Unwind_SetGR \ + _Unwind_GetLanguageSpecificData \ + _Unwind_FindEnclosingFunction \ + _Unwind_Resume \ + _Unwind_RaiseException \ + _Unwind_DeleteException \ + _Unwind_ForcedUnwind \ + _Unwind_Resume_or_Rethrow \ + _Unwind_Backtrace \ + __cxa_call_unexpected \ + __gxx_personality_v0 + +SDK_UNDEF_SYMBOLS += __cxx_fatal_exception +endif + +SDK_UNDEF_SYMBOLS += __cxa_guard_dummy + +# Force libpthread to appear later than libstdc++ in link line since libstdc++ depends on libpthread. +# Furthermore, force libcxx to appear later than libgcc because some libgcc unwind code is wrapped, if C++ +# exceptions are disabled. libcxx (this component) provides the unwind code wrappers. +# This is to prevent linking of libgcc's unwind code which considerably increases the binary size. + +# idf_component_get_property(pthread pthread COMPONENT_LIB) +# idf_component_get_property(cxx cxx COMPONENT_LIB) +# add_library(stdcpp_pthread INTERFACE) +# target_link_libraries(stdcpp_pthread INTERFACE stdc++ $) +# target_link_libraries(${COMPONENT_LIB} PUBLIC stdcpp_pthread) +# add_library(libgcc_cxx INTERFACE) +# target_link_libraries(libgcc_cxx INTERFACE gcc $) +# target_link_libraries(${COMPONENT_LIB} PUBLIC libgcc_cxx) diff --git a/Sming/Arch/Esp32/Components/esp32/sdk/esp32.mk b/Sming/Arch/Esp32/Components/esp32/sdk/esp32.mk new file mode 100644 index 0000000000..84ac656dd0 --- /dev/null +++ b/Sming/Arch/Esp32/Components/esp32/sdk/esp32.mk @@ -0,0 +1,5 @@ +# +# esp32 +# + +SDK_UNDEF_SYMBOLS += call_user_start_cpu0 diff --git a/Sming/Arch/Esp32/Components/esp32/sdk/esp_rom.mk b/Sming/Arch/Esp32/Components/esp32/sdk/esp_rom.mk new file mode 100644 index 0000000000..ed4f2b64c5 --- /dev/null +++ b/Sming/Arch/Esp32/Components/esp32/sdk/esp_rom.mk @@ -0,0 +1,6 @@ +# +# esp_rom +# +ifdef CONFIG_IDF_TARGET_ARCH_XTENSA +SDK_WRAP_SYMBOLS += longjmp +endif diff --git a/Sming/Arch/Esp32/Components/esp32/sdk/esp_system.mk b/Sming/Arch/Esp32/Components/esp32/sdk/esp_system.mk new file mode 100644 index 0000000000..1d7f1f8726 --- /dev/null +++ b/Sming/Arch/Esp32/Components/esp32/sdk/esp_system.mk @@ -0,0 +1,18 @@ +# +# esp_system +# + +# After system initialization, `start_app` (and its other cores variant) is called. +# This is provided by the user or from another component. Since we can't establish +# dependency on what we don't know, force linker to not drop the symbol regardless +# of link line order. +SDK_UNDEF_SYMBOLS += start_app + +ifndef CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE +SDK_UNDEF_SYMBOLS += start_app_other_cores +endif + +# ld_include_panic_highint_hdl is added as an undefined symbol because otherwise the +# linker will ignore panic_highint_hdl.S as it has no other files depending on any +# symbols in it. +SDK_UNDEF_SYMBOLS += ld_include_panic_highint_hdl diff --git a/Sming/Arch/Esp32/Components/esp32/sdk/freertos.mk b/Sming/Arch/Esp32/Components/esp32/sdk/freertos.mk new file mode 100644 index 0000000000..8d658211a5 --- /dev/null +++ b/Sming/Arch/Esp32/Components/esp32/sdk/freertos.mk @@ -0,0 +1,7 @@ +# +# freertos +# + +ifdef CONFIG_FREERTOS_DEBUG_OCDAWARE +EXTRA_LDFLAGS += -Wl,--undefined=uxTopUsedPriority +endif diff --git a/Sming/Arch/Esp32/Components/esp32/sdk/heap.mk b/Sming/Arch/Esp32/Components/esp32/sdk/heap.mk new file mode 100644 index 0000000000..b16d826602 --- /dev/null +++ b/Sming/Arch/Esp32/Components/esp32/sdk/heap.mk @@ -0,0 +1,16 @@ +# +# heap +# + +ifdef CONFIG_HEAP_TRACING +SDK_WRAP_SYMBOLS += \ + calloc \ + malloc \ + free \ + realloc \ + heap_caps_malloc \ + heap_caps_free \ + heap_caps_realloc \ + heap_caps_malloc_default \ + heap_caps_realloc_default +endif diff --git a/Sming/Arch/Esp32/Components/esp32/sdk/newlib.mk b/Sming/Arch/Esp32/Components/esp32/sdk/newlib.mk new file mode 100644 index 0000000000..75613e5733 --- /dev/null +++ b/Sming/Arch/Esp32/Components/esp32/sdk/newlib.mk @@ -0,0 +1,13 @@ +# +# newlib +# + +# Forces the linker to include heap, syscall, pthread and retargetable locks from this component, +# instead of the implementations provided by newlib. +SDK_UNDEF_SYMBOLS += \ + newlib_include_heap_impl \ + newlib_include_syscalls_impl \ + newlib_include_pthread_impl + +# Must link before standard C library +LIBS := newlib $(LIBS) diff --git a/Sming/Arch/Esp32/Components/esp32/sdk/pthread.mk b/Sming/Arch/Esp32/Components/esp32/sdk/pthread.mk new file mode 100644 index 0000000000..c24e62cb1e --- /dev/null +++ b/Sming/Arch/Esp32/Components/esp32/sdk/pthread.mk @@ -0,0 +1,11 @@ +# +# pthread +# +SDK_UNDEF_SYMBOLS += \ + pthread_include_pthread_impl \ + pthread_include_pthread_cond_impl \ + pthread_include_pthread_local_storage_impl + +ifdef CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP +SDK_WRAP_SYMBOLS += vPortCleanUpTCB +endif diff --git a/Sming/Arch/Esp32/Components/esp32/src/include/esp_libc.h b/Sming/Arch/Esp32/Components/esp32/src/include/esp_libc.h deleted file mode 100644 index 4f4728c247..0000000000 --- a/Sming/Arch/Esp32/Components/esp32/src/include/esp_libc.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -inline void system_set_os_print(bool onoff) -{ - // -} - -#define ets_memcpy(dest, src, n) memcpy(dest, src, n) - -#ifdef __cplusplus -} -#endif diff --git a/Sming/Arch/Esp32/Components/esp32/src/include/esp_system.h b/Sming/Arch/Esp32/Components/esp32/src/include/esp_system.h index eb4336a5b9..9d0704944f 100644 --- a/Sming/Arch/Esp32/Components/esp32/src/include/esp_system.h +++ b/Sming/Arch/Esp32/Components/esp32/src/include/esp_system.h @@ -12,6 +12,7 @@ extern "C" { #include +uint32_t system_get_time(void); void system_restart(void); void system_soft_wdt_stop(void); diff --git a/Sming/Arch/Esp32/Components/esp32/src/include/esp_systemapi.h b/Sming/Arch/Esp32/Components/esp32/src/include/esp_systemapi.h index 89482e7071..6077b68105 100644 --- a/Sming/Arch/Esp32/Components/esp32/src/include/esp_systemapi.h +++ b/Sming/Arch/Esp32/Components/esp32/src/include/esp_systemapi.h @@ -10,10 +10,7 @@ #pragma once -// ==== taken from ESP8266/ets_sys.h -#define ETS_GPIO_INUM 4 - -// ==== +#include // Default types #include @@ -21,7 +18,6 @@ #include #include -#include "esp_libc.h" #include "esp_sleep.h" #include "esp_clk.h" #include "esp_tasks.h" @@ -38,10 +34,6 @@ #include #include -#define __ESP32_EX__ // System definition ESP8266 SOC - -#define LOCAL static - #define SYSTEM_ERROR(fmt, ...) debug_e("ERROR: " fmt "\r\n", ##__VA_ARGS__) /** @brief Disable interrupts diff --git a/Sming/Arch/Esp32/Components/esp32/src/startup.cpp b/Sming/Arch/Esp32/Components/esp32/src/startup.cpp index a754cfa261..8c8bf99b7b 100644 --- a/Sming/Arch/Esp32/Components/esp32/src/startup.cpp +++ b/Sming/Arch/Esp32/Components/esp32/src/startup.cpp @@ -36,7 +36,7 @@ namespace esp_event_handler_t wifiEventHandler; /* - * Initalise NVS which IDF WiFi uses to store configuration parameters. + * Initialise NVS which IDF WiFi uses to store configuration parameters. */ void esp_init_nvs() { @@ -110,7 +110,7 @@ extern void sming_create_task(TaskFunction_t); extern "C" void app_main(void) { -#if defined(SUBARCH_ESP32) && !CONFIG_FREERTOS_UNICORE +#if defined(SOC_ESP32) && !CONFIG_FREERTOS_UNICORE constexpr unsigned core_id{1}; #else constexpr unsigned core_id{0}; diff --git a/Sming/Arch/Esp32/Components/esp32/src/system.cpp b/Sming/Arch/Esp32/Components/esp32/src/system.cpp index fd0ce1fdee..8633b37252 100644 --- a/Sming/Arch/Esp32/Components/esp32/src/system.cpp +++ b/Sming/Arch/Esp32/Components/esp32/src/system.cpp @@ -3,11 +3,11 @@ #include #include -extern "C" uint32_t system_get_time(void) +extern "C" int64_t esp_system_get_time(); + +uint32_t system_get_time(void) { - struct timeval tv; - gettimeofday(&tv, nullptr); - return tv.tv_sec * 1000000U + tv.tv_usec; + return esp_system_get_time(); } struct rst_info* system_get_rst_info(void) diff --git a/Sming/Arch/Esp32/Components/gdbstub/gdb_syscall.cpp b/Sming/Arch/Esp32/Components/gdbstub/gdb_syscall.cpp index 91367581e6..52c57f1c0d 100644 --- a/Sming/Arch/Esp32/Components/gdbstub/gdb_syscall.cpp +++ b/Sming/Arch/Esp32/Components/gdbstub/gdb_syscall.cpp @@ -1,4 +1,5 @@ #include +#include int gdb_syscall(const GdbSyscallInfo& info) { diff --git a/Sming/Arch/Esp32/Components/libc/component.mk b/Sming/Arch/Esp32/Components/libc/component.mk index 3980983c81..065d909a37 100644 --- a/Sming/Arch/Esp32/Components/libc/component.mk +++ b/Sming/Arch/Esp32/Components/libc/component.mk @@ -3,4 +3,21 @@ COMPONENT_INCDIRS := src/include COMPONENT_DOXYGEN_INPUT := src/include/sys -EXTRA_LDFLAGS := $(call Wrap,_write_r _read_r) +LIBC_WRAPSYMS := \ + _write_r \ + _read_r \ + putchar \ + puts \ + vprintf \ + printf \ + vsnprintf \ + vsprintf \ + sprintf + +EXTRA_LDFLAGS := $(call Wrap,$(LIBC_WRAPSYMS)) + +EXTRA_LIBS := \ + c \ + m \ + gcc \ + stdc++ diff --git a/Sming/Arch/Esp32/Components/libc/src/replacements.c b/Sming/Arch/Esp32/Components/libc/src/replacements.c index 04d972852b..768f09ee11 100644 --- a/Sming/Arch/Esp32/Components/libc/src/replacements.c +++ b/Sming/Arch/Esp32/Components/libc/src/replacements.c @@ -6,14 +6,17 @@ #include #include -ssize_t __wrap__write_r(struct _reent* r, int fd, const void* data, size_t size) +#define BUFMAX 16384 +#define WRAP(x) __wrap_##x + +ssize_t WRAP(_write_r)(struct _reent* r, int fd, const void* data, size_t size) { (void)r; (void)fd; // Ignore, direct everything return m_nputs(data, size); } -ssize_t __wrap__read_r(struct _reent* r, int fd, void* dst, size_t size) +ssize_t WRAP(_read_r)(struct _reent* r, int fd, void* dst, size_t size) { (void)r; (void)fd; @@ -22,3 +25,57 @@ ssize_t __wrap__read_r(struct _reent* r, int fd, void* dst, size_t size) errno = ENOSYS; return -1; } + +size_t WRAP(putc)(char c) +{ + return m_putc(c); +} + +size_t WRAP(puts)(const char* str) +{ + return m_puts(str); +} + +int WRAP(vprintf)(const char* format, va_list arg) +{ + return m_vprintf(format, arg); +} + +int WRAP(printf)(char const* fmt, ...) +{ + va_list args; + va_start(args, fmt); + int n = m_vprintf(fmt, args); + va_end(args); + return n; +} + +int WRAP(vsnprintf)(char* buf, size_t maxLen, const char* fmt, va_list args) +{ + return m_vsnprintf(buf, maxLen, fmt, args); +} + +int WRAP(snprintf)(char* buf, int length, const char* fmt, ...) +{ + va_list args; + + va_start(args, fmt); + int n = m_vsnprintf(buf, length, fmt, args); + va_end(args); + + return n; +} + +int WRAP(vsprintf)(char* buf, const char* fmt, va_list args) +{ + return m_vsnprintf(buf, BUFMAX, fmt, args); +} + +int WRAP(sprintf)(char* buf, const char* fmt, ...) +{ + va_list args; + va_start(args, fmt); + int n = m_vsnprintf(buf, BUFMAX, fmt, args); + va_end(args); + return n; +} diff --git a/Sming/Arch/Esp32/Components/sming-arch/component.mk b/Sming/Arch/Esp32/Components/sming-arch/component.mk index 24c3b98a72..189237cbae 100644 --- a/Sming/Arch/Esp32/Components/sming-arch/component.mk +++ b/Sming/Arch/Esp32/Components/sming-arch/component.mk @@ -3,14 +3,12 @@ IDF_TARGET ?= esp32 COMPONENT_SRCDIRS := \ $(ARCH_CORE) $(call ListAllSubDirs,$(ARCH_CORE)) \ - $(ARCH_SYS) \ $(ARCH_BASE)/Platform \ $(ARCH_BASE)/Services/Profiling COMPONENT_INCDIRS := \ $(ARCH_BASE) \ $(ARCH_CORE) \ - $(ARCH_SYS)/include \ $(ARCH_COMPONENTS) COMPONENT_DEPENDS := \ @@ -18,13 +16,12 @@ COMPONENT_DEPENDS := \ spi_flash \ driver \ heap \ - fatfs \ esp32 \ gdbstub \ esptool # ELF and BIN files -DEBUG_VARS += TARGET_BIN +DEBUG_VARS += TARGET_BIN TARGET_OUT TARGET_OUT = $(BUILD_BASE)/$(APP_NAME).out TARGET_BIN = $(FW_BASE)/$(APP_NAME).bin TARGET_OUT_0 = $(TARGET_OUT) diff --git a/Sming/Arch/Esp32/Components/spi_flash/flashmem.cpp b/Sming/Arch/Esp32/Components/spi_flash/flashmem.cpp index 76f01d16c0..7bb869775f 100644 --- a/Sming/Arch/Esp32/Components/spi_flash/flashmem.cpp +++ b/Sming/Arch/Esp32/Components/spi_flash/flashmem.cpp @@ -14,6 +14,7 @@ #include #include #include +#include uint32_t flashmem_write(const void* from, uint32_t toaddr, uint32_t size) { @@ -39,7 +40,7 @@ uint32_t flashmem_read(void* to, uint32_t fromaddr, uint32_t size) bool flashmem_erase_sector(uint32_t sector_id) { - debug_e("flashmem_erase_sector(0x%08x)", sector_id); + debug_d("flashmem_erase_sector(0x%08x)", sector_id); return spi_flash_erase_sector(sector_id) == SPI_FLASH_RESULT_OK; } diff --git a/Sming/Arch/Esp32/Components/spi_flash/include/esp_spi_flash.h b/Sming/Arch/Esp32/Components/spi_flash/include/esp_spi_flash.h index f4b34017ef..3e4a03dff7 100644 --- a/Sming/Arch/Esp32/Components/spi_flash/include/esp_spi_flash.h +++ b/Sming/Arch/Esp32/Components/spi_flash/include/esp_spi_flash.h @@ -19,8 +19,6 @@ extern "C" { #endif -#include - /** * @defgroup flash Flash Memory Support * @defgroup spi_flash SPI Flash API @@ -151,10 +149,13 @@ uint32_t flashmem_find_sector(uint32_t address, uint32_t* pstart, uint32_t* pend */ uint32_t flashmem_get_sector_of_address(uint32_t addr); -/** @} */ - +/* + * @brief Get unique 32-bit flash identification code + */ uint32_t spi_flash_get_id(void); +/** @} */ + #ifdef __cplusplus } #endif diff --git a/Sming/Arch/Esp32/Components/spi_flash/include/flashmem.h b/Sming/Arch/Esp32/Components/spi_flash/include/flashmem.h deleted file mode 100644 index f1d8fa7a80..0000000000 --- a/Sming/Arch/Esp32/Components/spi_flash/include/flashmem.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -#pragma GCC warning "Please update to #include " -#include "esp_spi_flash.h" diff --git a/Sming/Arch/Esp32/Components/spi_flash/include/iram_precache.h b/Sming/Arch/Esp32/Components/spi_flash/include/iram_precache.h index ecebfa0ca2..e48a605ba0 100644 --- a/Sming/Arch/Esp32/Components/spi_flash/include/iram_precache.h +++ b/Sming/Arch/Esp32/Components/spi_flash/include/iram_precache.h @@ -2,8 +2,6 @@ * Dummy stub. ESP32 has tons of IRAM. */ -#include - #pragma once /** @@ -16,22 +14,4 @@ #define IRAM_PRECACHE_START(tag) #define IRAM_PRECACHE_END(tag) -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Pre-load flash data into the flash instruction cache - * @param addr First location to cache, specify NULL to use current location. - * @param bytes Number of bytes to cache - * @note All pages containing the requested region will be read to pull them into cache RAM. - */ -inline void iram_precache(void* addr, uint32_t bytes) -{ -} - /** @} */ - -#ifdef __cplusplus -} -#endif diff --git a/Sming/Arch/Esp32/Core/Digital.cpp b/Sming/Arch/Esp32/Core/Digital.cpp index 6469e6707c..1fbc854d9a 100644 --- a/Sming/Arch/Esp32/Core/Digital.cpp +++ b/Sming/Arch/Esp32/Core/Digital.cpp @@ -9,8 +9,8 @@ ****/ #include -#include -#define gpio_drive_cap_t uint32_t +#include +#include #include #include #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED @@ -58,7 +58,8 @@ void pinMode(uint16_t pin, uint8_t mode) } #endif - gpio_set_level(gpio, 0); + gpio_ll_set_level(&GPIO, gpio, 0); + gpio_ll_input_enable(&GPIO, gpio); gpio_ll_pulldown_dis(&GPIO, gpio); @@ -127,7 +128,7 @@ void noPullup(uint16_t pin) } \ } -unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout) +unsigned long pulseIn(uint16_t pin, uint8_t state, unsigned long timeout) { const uint32_t max_timeout_us = clockCyclesToMicroseconds(UINT_MAX); if(timeout > max_timeout_us) { diff --git a/Sming/Arch/Esp32/Core/Interrupts.cpp b/Sming/Arch/Esp32/Core/Interrupts.cpp index b34d20d09d..3deac44c4d 100644 --- a/Sming/Arch/Esp32/Core/Interrupts.cpp +++ b/Sming/Arch/Esp32/Core/Interrupts.cpp @@ -8,13 +8,12 @@ * ****/ -#include #include #include #include #include #include -#include +#include #define gpio_drive_cap_t uint32_t #include diff --git a/Sming/Arch/Esp32/Core/SPI.cpp b/Sming/Arch/Esp32/Core/SPI.cpp index c79317fc82..f6d8316b03 100644 --- a/Sming/Arch/Esp32/Core/SPI.cpp +++ b/Sming/Arch/Esp32/Core/SPI.cpp @@ -57,8 +57,10 @@ __forceinline void spi_wait(SpiDevice& dev) /** * @brief Initiate an SPI user transaction */ -__forceinline void spi_send(SpiDevice& dev) +__forceinline void spi_send(SpiDevice& dev, unsigned num_bits) { + spi_ll_set_mosi_bitlen(&dev, num_bits); + spi_ll_set_miso_bitlen(&dev, num_bits); dev.cmd.usr = true; } @@ -97,7 +99,7 @@ void spi_byte_order(SpiDevice& dev, uint8_t byte_order) #endif // No HAL definition for this -#if SUBARCH_ESP32 || SUBARCH_ESP32S2 +#if SOC_ESP32 || SOC_ESP32S2 dev.user.rd_byte_order = (byte_order == MSBFIRST); dev.user.wr_byte_order = (byte_order == MSBFIRST); #else @@ -272,6 +274,10 @@ bool SPIClass::begin() spi_ll_enable_miso(&dev, true); spi_ll_set_half_duplex(&dev, false); + spi_ll_set_dummy(&dev, 0); + spi_ll_set_command_bitlen(&dev, 0); + spi_ll_set_addr_bitlen(&dev, 0); + // Not using any auto. chip selects spi_ll_master_select_cs(&dev, -1); @@ -345,11 +351,8 @@ uint32_t SPIClass::transfer32(uint32_t data, uint8_t bits) spi_wait(dev); - spi_ll_set_mosi_bitlen(&dev, bits); - spi_ll_set_miso_bitlen(&dev, bits); - // copy data to W0 -#if SUBARCH_ESP32 || SUBARCH_ESP32S2 +#if SOC_ESP32 || SOC_ESP32S2 if(dev.user.wr_byte_order) { dev.data_buf[0] = data << (32 - bits); } else @@ -358,11 +361,11 @@ uint32_t SPIClass::transfer32(uint32_t data, uint8_t bits) dev.data_buf[0] = data; } - spi_send(dev); + spi_send(dev, bits); spi_wait(dev); auto res = dev.data_buf[0]; -#if SUBARCH_ESP32 || SUBARCH_ESP32S2 +#if SOC_ESP32 || SOC_ESP32S2 if(dev.user.rd_byte_order) { res >>= (32 - bits); } @@ -378,11 +381,11 @@ uint8_t SPIClass::read8() dev.data_buf[0] = 0x00; - spi_send(dev); + spi_send(dev, 8); spi_wait(dev); auto res = dev.data_buf[0]; -#if SUBARCH_ESP32 || SUBARCH_ESP32S2 +#if SOC_ESP32 || SOC_ESP32S2 if(dev.user.rd_byte_order) { res >>= 24; } @@ -414,11 +417,6 @@ void SPIClass::transfer(uint8_t* buffer, size_t numberBytes) spi_wait(dev); - // setup bit length - auto num_bits = bufLength * 8; - spi_ll_set_mosi_bitlen(&dev, num_bits); - spi_ll_set_miso_bitlen(&dev, num_bits); - // copy the registers starting from last index position if(IS_ALIGNED(buffer)) { memcpy((void*)dev.data_buf, &buffer[bufIndx], ALIGNUP4(bufLength)); @@ -428,7 +426,7 @@ void SPIClass::transfer(uint8_t* buffer, size_t numberBytes) memcpy((void*)dev.data_buf, wordBuffer, ALIGNUP4(bufLength)); } - spi_send(dev); + spi_send(dev, bufLength * 8); spi_wait(dev); // copy the registers starting from last index position diff --git a/Sming/Arch/Esp32/Core/SPI.h b/Sming/Arch/Esp32/Core/SPI.h index ee83fd9ceb..1ef1f3cd22 100644 --- a/Sming/Arch/Esp32/Core/SPI.h +++ b/Sming/Arch/Esp32/Core/SPI.h @@ -50,7 +50,7 @@ enum class SpiBus { VSPI = 3, // Normally attached to pins 5, 18, 19 and 23, but can be matrixed to any pins #endif MAX = SOC_SPI_PERIPH_NUM, -#ifdef SUBARCH_ESP32C3 +#ifdef SOC_ESP32C3 DEFAULT = SPI1, #else DEFAULT = VSPI, diff --git a/Sming/Arch/Esp32/Core/peripheral.h b/Sming/Arch/Esp32/Core/peripheral.h index 817e0abd1a..be157e6e34 100644 --- a/Sming/Arch/Esp32/Core/peripheral.h +++ b/Sming/Arch/Esp32/Core/peripheral.h @@ -162,7 +162,7 @@ extern const uint8_t esp8266_gpioToFn[16]; #define TCIS 8 //Interrupt Status #define TCTE 7 //Timer Enable #define TCAR 6 //AutoReload (restart timer when condition is reached) -#define TCPD 2 //Prescale Devider (2bit) 0:1(12.5ns/tick), 1:16(0.2us/tick), 2/3:256(3.2us/tick) +#define TCPD 2 //Prescale Divider (2bit) 0:1(12.5ns/tick), 1:16(0.2us/tick), 2/3:256(3.2us/tick) #define TCIT 0 //Interrupt Type 0:edge, 1:level //RTC Registers @@ -270,7 +270,7 @@ extern const uint8_t esp8266_gpioToFn[16]; #define UCRXI 19 //Invert RX #define UCTXRST 18 //Reset TX FIFO #define UCRXRST 17 //Reset RX FIFO -#define UCTXHFE 15 //TX Harware Flow Enable +#define UCTXHFE 15 //TX Hardware Flow Enable #define UCLBE 14 //LoopBack Enable #define UCBRK 8 //Send Break on the TX line #define UCSWDTR 7 //Set this bit to assert DTR @@ -282,11 +282,11 @@ extern const uint8_t esp8266_gpioToFn[16]; //UART CONF1 Registers Bits #define UCTOE 31 //RX TimeOut Enable -#define UCTOT 24 //RX TimeOut Treshold (7bit) -#define UCRXHFE 23 //RX Harware Flow Enable -#define UCRXHFT 16 //RX Harware Flow Treshold (7bit) -#define UCFET 8 //TX FIFO Empty Treshold (7bit) -#define UCFFT 0 //RX FIFO Full Treshold (7bit) +#define UCTOT 24 //RX TimeOut Threshold (7bit) +#define UCRXHFE 23 //RX Hardware Flow Enable +#define UCRXHFT 16 //RX Hardware Flow Threshold (7bit) +#define UCFET 8 //TX FIFO Empty Threshold (7bit) +#define UCFFT 0 //RX FIFO Full Threshold (7bit) //SPI_READY #define SPIRDY ESP8266_DREG(0x0C) @@ -367,7 +367,7 @@ extern const uint8_t esp8266_gpioToFn[16]; #define SPI1E3 ESP8266_REG(0x1FC) #define SPI1W(p) ESP8266_REG(0x140 + ((p & 0xF) * 4)) -//SPI0, SPI1 & I2S Interupt Register +//SPI0, SPI1 & I2S Interrupt Register #define SPIIR ESP8266_DREG(0x20) #define SPII0 4 //SPI0 Interrupt #define SPII1 7 //SPI1 Interrupt diff --git a/Sming/Arch/Esp32/Core/pins_arduino.h b/Sming/Arch/Esp32/Core/pins_arduino.h index 7caf39ac15..04af3f5be1 100644 --- a/Sming/Arch/Esp32/Core/pins_arduino.h +++ b/Sming/Arch/Esp32/Core/pins_arduino.h @@ -22,55 +22,7 @@ #define digitalPinToInterrupt(p) (((p) < 40) ? (p) : -1) #define digitalPinHasPWM(p) (p < 34) -static const uint8_t TX = 1; -static const uint8_t RX = 3; - -static const uint8_t SDA = 21; -static const uint8_t SCL = 22; - -static const uint8_t SS = 5; -static const uint8_t MOSI = 23; -static const uint8_t MISO = 19; -static const uint8_t SCK = 18; - -static const uint8_t A0 = 36; -static const uint8_t A3 = 39; -static const uint8_t A4 = 32; -static const uint8_t A5 = 33; -static const uint8_t A6 = 34; -static const uint8_t A7 = 35; -static const uint8_t A10 = 4; -static const uint8_t A11 = 0; -static const uint8_t A12 = 2; -static const uint8_t A13 = 15; -static const uint8_t A14 = 13; -static const uint8_t A15 = 12; -static const uint8_t A16 = 14; -static const uint8_t A17 = 27; -static const uint8_t A18 = 25; -static const uint8_t A19 = 26; - -static const uint8_t T0 = 4; -static const uint8_t T1 = 0; -static const uint8_t T2 = 2; -static const uint8_t T3 = 15; -static const uint8_t T4 = 13; -static const uint8_t T5 = 12; -static const uint8_t T6 = 14; -static const uint8_t T7 = 27; -static const uint8_t T8 = 33; -static const uint8_t T9 = 32; - -static const uint8_t DAC1 = 25; -static const uint8_t DAC2 = 26; - -#define NOT_A_PIN 0 -#define NOT_A_PORT 0 -#define NOT_ON_TIMER 0 - -#define PA 1 -#define PB 2 -#define PC 3 +constexpr uint8_t A0{36}; #define GPIO_REG_TYPE uint32_t diff --git a/Sming/Arch/Esp32/Core/twi_arch.h b/Sming/Arch/Esp32/Core/twi_arch.h index 08ccdf3378..1ed2b43e42 100644 --- a/Sming/Arch/Esp32/Core/twi_arch.h +++ b/Sming/Arch/Esp32/Core/twi_arch.h @@ -19,3 +19,6 @@ #define SCL_LOW() gpio_ll_output_enable(&GPIO, gpio_num_t(twi_scl)) #define SCL_HIGH() gpio_ll_output_disable(&GPIO, gpio_num_t(twi_scl)) #define SCL_READ() (gpio_ll_get_level(&GPIO, gpio_num_t(twi_scl)) != 0) + +#define DEFAULT_SDA_PIN 21 +#define DEFAULT_SCL_PIN 22 diff --git a/Sming/Arch/Esp32/Platform/Clocks.h b/Sming/Arch/Esp32/Platform/Clocks.h index 34484ac99b..fcf72ef9e8 100644 --- a/Sming/Arch/Esp32/Platform/Clocks.h +++ b/Sming/Arch/Esp32/Platform/Clocks.h @@ -38,7 +38,7 @@ using PolledTimerClock = OsTimerClock; using CpuCycleClockSlow = CpuCycleClock; using CpuCycleClockNormal = CpuCycleClock; -#ifdef SUBARCH_ESP32C3 +#ifdef SOC_ESP32C3 using CpuCycleClockFast = CpuCycleClockNormal; #else using CpuCycleClockFast = CpuCycleClock; diff --git a/Sming/Arch/Esp32/README.rst b/Sming/Arch/Esp32/README.rst index 3092ea6496..4afaa24ac8 100644 --- a/Sming/Arch/Esp32/README.rst +++ b/Sming/Arch/Esp32/README.rst @@ -76,8 +76,8 @@ If you want to revert to using the default SDK settings then issue the following You can also configure per-project custom settings via :envvar:`SDK_CUSTOM_CONFIG`. -Processor variants ------------------- +SoC variants +------------ Sming leverages the `ESP IDF HAL `__ to support multiple processor variants. @@ -92,7 +92,7 @@ This is still at an early stage of development however basic applications should You can change variants like this: ``` -make SMING_ARCH=Esp32 ESP_VARIANT=esp32c3 +make SMING_SOC=esp32c3 ``` Each variant uses a different build directory, e.g. ``out/Esp32/esp32c3/...`` to avoid conflicts. diff --git a/Sming/Arch/Esp32/System/include/user_config.h b/Sming/Arch/Esp32/System/include/user_config.h deleted file mode 100644 index 590d433248..0000000000 --- a/Sming/Arch/Esp32/System/include/user_config.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef __USER_CONFIG_H__ -#define __USER_CONFIG_H__ - -// UART config -#define SERIAL_BAUD_RATE COM_SPEED_SERIAL - -#include - -#include - -// Extended string conversion for compatibility -#include - -// Network base API -#include - -#endif diff --git a/Sming/Arch/Esp32/Tools/ci/build.run.cmd b/Sming/Arch/Esp32/Tools/ci/build.run.cmd index ad6fc47873..78de751535 100644 --- a/Sming/Arch/Esp32/Tools/ci/build.run.cmd +++ b/Sming/Arch/Esp32/Tools/ci/build.run.cmd @@ -1,18 +1,10 @@ REM Esp32 build.run.cmd -%MAKE_PARALLEL% Basic_Blink Basic_WiFi HttpServer_ConfigNetwork DEBUG_VERBOSE_LEVEL=3 STRICT=1 || goto :error +%MAKE_PARALLEL% Basic_Blink Basic_Ethernet Basic_WiFi HttpServer_ConfigNetwork DEBUG_VERBOSE_LEVEL=3 STRICT=1 || goto :error %MAKE_PARALLEL% Basic_Ssl ENABLE_SSL=Bearssl DEBUG_VERBOSE_LEVEL=3 STRICT=1 || goto :error -ESP32_PROJECTS="Basic_Blink Basic_Ethernet" - -REM esp32s2 -%MAKE_PARALLEL% ESP_VARIANT=esp32s2 %ESP32_PROJECTS% || goto :error - -REM esp32c3 -%MAKE_PARALLEL% ESP_VARIANT=esp32c3 %ESP32_PROJECTS% || goto :error - -REM esp32s3 -%MAKE_PARALLEL% ESP_VARIANT=esp32s3 %ESP32_PROJECTS% || goto :error +REM make sure that the Ota Library sample compiles for ESP32 +%MAKE_PARALLEL% -C %SMING_HOME%\Libraries\OtaUpgradeMqtt\samples\Upgrade goto :EOF diff --git a/Sming/Arch/Esp32/Tools/ci/build.run.sh b/Sming/Arch/Esp32/Tools/ci/build.run.sh index 2bd9758347..0d27ac8073 100644 --- a/Sming/Arch/Esp32/Tools/ci/build.run.sh +++ b/Sming/Arch/Esp32/Tools/ci/build.run.sh @@ -1,15 +1,9 @@ +#!/bin/bash +# # Esp32 build.run.sh $MAKE_PARALLEL Basic_Blink Basic_WiFi HttpServer_ConfigNetwork DEBUG_VERBOSE_LEVEL=3 STRICT=1 $MAKE_PARALLEL Basic_Ssl ENABLE_SSL=Bearssl DEBUG_VERBOSE_LEVEL=3 STRICT=1 +$MAKE_PARALLEL samples -ESP32_PROJECTS="Basic_Blink Basic_Ethernet" - -# esp32s2 -$MAKE_PARALLEL ESP_VARIANT=esp32s2 $ESP32_PROJECTS - -# esp32c3 -$MAKE_PARALLEL ESP_VARIANT=esp32c3 $ESP32_PROJECTS - -# esp32s3 -$MAKE_PARALLEL ESP_VARIANT=esp32s3 $ESP32_PROJECTS +$MAKE_PARALLEL component-samples STRICT=1 diff --git a/Sming/Arch/Esp32/Tools/ci/build.setup.sh b/Sming/Arch/Esp32/Tools/ci/build.setup.sh index 4aaa83f008..ae000d1ac3 100755 --- a/Sming/Arch/Esp32/Tools/ci/build.setup.sh +++ b/Sming/Arch/Esp32/Tools/ci/build.setup.sh @@ -1 +1,3 @@ +#!/bin/bash +# # Esp32 build.setup.sh diff --git a/Sming/Arch/Esp32/Tools/decode-stacktrace.py b/Sming/Arch/Esp32/Tools/decode-stacktrace.py index 925958e2db..22dcf517f9 100644 --- a/Sming/Arch/Esp32/Tools/decode-stacktrace.py +++ b/Sming/Arch/Esp32/Tools/decode-stacktrace.py @@ -49,4 +49,3 @@ def extractAddresses(data): pipe.stdin.write(line.encode('ascii')) pipe.stdin.flush() - diff --git a/Sming/Arch/Esp32/Tools/ci/install.cmd b/Sming/Arch/Esp32/Tools/install.cmd similarity index 72% rename from Sming/Arch/Esp32/Tools/ci/install.cmd rename to Sming/Arch/Esp32/Tools/install.cmd index dd93195491..ae5388a47e 100644 --- a/Sming/Arch/Esp32/Tools/ci/install.cmd +++ b/Sming/Arch/Esp32/Tools/install.cmd @@ -9,5 +9,6 @@ if "%IDF_BRANCH%"=="" set IDF_BRANCH="sming/release/v4.3" git clone -b %IDF_BRANCH% %IDF_REPO% %IDF_PATH% REM Install IDF tools and packages -python %IDF_PATH%\tools\idf_tools.py install +python "%IDF_PATH%\tools\idf_tools.py" --non-interactive install +python -m pip install %SMINGTOOLS%/gevent-1.5.0-cp39-cp39-win_amd64.whl python -m pip install -r %IDF_PATH%\requirements.txt diff --git a/Sming/Arch/Esp32/Tools/install.sh b/Sming/Arch/Esp32/Tools/install.sh index d087b4bfa0..ccf85289f8 100644 --- a/Sming/Arch/Esp32/Tools/install.sh +++ b/Sming/Arch/Esp32/Tools/install.sh @@ -1,3 +1,5 @@ +#!/bin/bash +# # Esp32 install.sh if [ -n "$IDF_PATH" ] && [ -n "$IDF_TOOLS_PATH" ]; then @@ -49,7 +51,7 @@ rm -f "$IDF_PATH" ln -s "$IDF_CLONE_PATH" "$IDF_PATH" # Install IDF tools and packages -python3 "$IDF_PATH/tools/idf_tools.py" install +python3 "$IDF_PATH/tools/idf_tools.py" --non-interactive install python3 -m pip install -r "$IDF_PATH/requirements.txt" if [ -z "$KEEP_DOWNLOADS" ]; then diff --git a/Sming/Arch/Esp32/app.mk b/Sming/Arch/Esp32/app.mk index db6ca31cbf..05846d47a8 100644 --- a/Sming/Arch/Esp32/app.mk +++ b/Sming/Arch/Esp32/app.mk @@ -16,24 +16,13 @@ application: $(TARGET_BIN) $(TARGET_OUT): $(COMPONENTS_AR) $(info $(notdir $(PROJECT_DIR)): Linking $@) $(Q) $(LD) $(addprefix -L,$(LIBDIRS)) $(LDFLAGS) -Wl,--start-group $(COMPONENTS_AR) $(addprefix -l,$(LIBS)) -Wl,--end-group -o $@ + $(Q) $(MEMANALYZER) $@ > $(FW_MEMINFO) + $(Q) cat $(FW_MEMINFO) - $(Q) $(MEMANALYZER) $@ > $(FW_MEMINFO_NEW) - - $(Q) if [ -f "$(FW_MEMINFO_NEW)" -a -f "$(FW_MEMINFO_OLD)" ]; then \ - $(AWK) -F "|" ' \ - FILENAME == "$(FW_MEMINFO_OLD)" { \ - arr[$$1]=$$5 \ - } \ - FILENAME == "$(FW_MEMINFO_NEW)" { \ - if (arr[$$1] != $$5) { \ - printf "%s%s%+d%s", substr($$0, 1, length($$0) - 1)," (",$$5 - arr[$$1],")\n" \ - } else { \ - print $$0 \ - } \ - }' $(FW_MEMINFO_OLD) $(FW_MEMINFO_NEW); \ - elif [ -f "$(FW_MEMINFO_NEW)" ]; then \ - cat $(FW_MEMINFO_NEW); \ - fi +CHIP_REV_MIN := $(CONFIG_$(call ToUpper,$(ESP_VARIANT))_REV_MIN) +ifeq ($(CHIP_REV_MIN),) +CHIP_REV_MIN := 0 +endif CHIP_REV_MIN := $(CONFIG_$(call ToUpper,$(ESP_VARIANT))_REV_MIN) ifeq ($(CHIP_REV_MIN),) diff --git a/Sming/Arch/Esp32/build.mk b/Sming/Arch/Esp32/build.mk index 3356671ea9..aeb1bc7a8b 100644 --- a/Sming/Arch/Esp32/build.mk +++ b/Sming/Arch/Esp32/build.mk @@ -22,10 +22,8 @@ endif export IDF_TOOLS_PATH := $(call FixPath,$(IDF_TOOLS_PATH)) -ifndef ESP_VARIANT -override ESP_VARIANT := esp32 -endif - +# ESP_VARIANT used internally for ESP32 only +ESP_VARIANT := $(SMING_SOC) export ESP_VARIANT ifeq ($(ESP_VARIANT),esp32c3) @@ -96,7 +94,7 @@ DEBUG_VARS += ESP32_IDFEXE_PATH ifndef ESP32_IDFEXE_PATH ESP32_IDFEXE_PATH := $(call FindTool,tools/idf-exe) endif -IDF_PATH_LIST += ESP32_IDFEXE_PATH +IDF_PATH_LIST += $(ESP32_IDFEXE_PATH) endif DEBUG_VARS += NINJA @@ -113,6 +111,7 @@ CC := $(TOOLSPEC)-gcc CXX := $(TOOLSPEC)-g++ AR := $(TOOLSPEC)-ar LD := $(TOOLSPEC)-gcc +NM := $(TOOLSPEC)-nm OBJCOPY := $(TOOLSPEC)-objcopy OBJDUMP := $(TOOLSPEC)-objdump GDB := $(TOOLSPEC)-gdb @@ -131,174 +130,39 @@ endif IDF_VER := $(shell echo "$(IDF_VER_T)" | cut -c 1-31) # [ Sming specific flags ] -DEBUG_VARS += IDF_PATH IDF_VER - -# Set default LDFLAGS -EXTRA_LDFLAGS ?= -LDFLAGS ?= -nostdlib \ - -u call_user_start_cpu0 \ - $(EXTRA_LDFLAGS) \ - -Wl,--gc-sections \ - -Wl,-static \ - -Wl,--start-group \ - $(COMPONENT_LDFLAGS) \ - -lgcc \ - -lstdc++ \ - -lgcov \ - -Wl,--end-group \ - -Wl,-EL - -SMING_C_STD := gnu99 - -# Set default CPPFLAGS, CFLAGS, CXXFLAGS -# These are exported so that components can use them when compiling. -# If you need your component to add CFLAGS/etc for it's own source compilation only, set CFLAGS += in your component's Makefile. -# If you need your component to add CFLAGS/etc globally for all source -# files, set CFLAGS += in your component's Makefile.projbuild -# If you need to set CFLAGS/CPPFLAGS/CXXFLAGS at project level, set them in application Makefile -# before including project.mk. Default flags will be added before the ones provided in application Makefile. +DEBUG_VARS += IDF_PATH IDF_VER -# This variable stores the common C/C++ flags -# CPPFLAGS used by C preprocessor -# If any flags are defined in application Makefile, add them at the end. +# Common C/C++ flags CPPFLAGS += \ -DESP_PLATFORM \ - -D IDF_VER=\"$(IDF_VER)\" \ + -DIDF_VER=\"$(IDF_VER)\" \ -MMD \ -MP \ - $(EXTRA_CPPFLAGS) - -# Sming specific CPPFLAGS -CPPFLAGS += \ + $(EXTRA_CPPFLAGS) \ -DARCH_ESP32 \ + -D__ESP32_EX__ \ -D__ets__ \ - -DICACHE_FLASH \ - -DUSE_OPTIMIZE_PRINTF \ - -DESP32 + -D_GNU_SOURCE \ + -DCONFIG_NONE_OS \ + -Dasm=__asm__ PROJECT_VER ?= export IDF_VER export PROJECT_NAME export PROJECT_VER -# Warnings-related flags relevant both for C and C++ -COMMON_WARNING_FLAGS := -Wall -Werror=all \ - -Wno-error=unused-function \ - -Wno-error=unused-but-set-variable \ - -Wno-error=unused-variable \ - -Wno-error=deprecated-declarations \ - -Wno-error=extra \ - -Wno-unused-parameter -Wno-error=sign-compare \ - -Wno-error=ignored-qualifiers \ - -Wno-error=missing-field-initializers \ - -Wno-error=implicit-fallthrough - -# Sming warning.... -COMMON_WARNING_FLAGS += -Wno-error=undef - -ifdef CONFIG_COMPILER_DISABLE_GCC8_WARNINGS -COMMON_WARNING_FLAGS += -Wno-parentheses \ - -Wno-sizeof-pointer-memaccess \ - -Wno-clobbered \ - -Wno-format-overflow \ - -Wno-stringop-truncation \ - -Wno-misleading-indentation \ - -Wno-cast-function-type \ - -Wno-implicit-fallthrough \ - -Wno-unused-const-variable \ - -Wno-switch-unreachable \ - -Wno-format-truncation \ - -Wno-memset-elt-size \ - -Wno-int-in-bool-context -endif - -ifdef CONFIG_COMPILER_WARN_WRITE_STRINGS -COMMON_WARNING_FLAGS += -Wwrite-strings -endif #CONFIG_COMPILER_WARN_WRITE_STRINGS - # Flags which control code generation and dependency generation, both for C and C++ -COMMON_FLAGS := \ - -Wno-frame-address \ - -ffunction-sections -fdata-sections \ - -fstrict-volatile-bitfields \ - -nostdlib +CPPFLAGS += -Wno-frame-address -ifdef IDF_TARGET_ARCH_RISCV -COMMON_FLAGS += -DIDF_TARGET_ARCH_RISCV=1 -else -COMMON_FLAGS += \ +ifndef IDF_TARGET_ARCH_RISCV +CPPFLAGS += \ -mlongcalls \ -mtext-section-literals endif -ifndef IS_BOOTLOADER_BUILD -# stack protection (only one option can be selected in menuconfig) -ifdef CONFIG_COMPILER_STACK_CHECK_MODE_NORM -COMMON_FLAGS += -fstack-protector -endif -ifdef CONFIG_COMPILER_STACK_CHECK_MODE_STRONG -COMMON_FLAGS += -fstack-protector-strong -endif -ifdef CONFIG_COMPILER_STACK_CHECK_MODE_ALL -COMMON_FLAGS += -fstack-protector-all -endif -endif - -# Optimization flags are set based on menuconfig choice -ifdef CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE -OPTIMIZATION_FLAGS = -Os -freorder-blocks -else -OPTIMIZATION_FLAGS = -Og -endif - -ifdef CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE -CPPFLAGS += -DNDEBUG -endif - -# IDF uses some GNU extension from libc -CPPFLAGS += -D_GNU_SOURCE - -CPPFLAGS += -DCONFIG_NONE_OS - -# Enable generation of debugging symbols -# (we generate even in Release mode, as this has no impact on final binary size.) -DEBUG_FLAGS ?= -ggdb - -# List of flags to pass to C compiler -# If any flags are defined in application Makefile, add them at the end. -CFLAGS := $(strip \ - $(OPTIMIZATION_FLAGS) $(DEBUG_FLAGS) \ - $(COMMON_FLAGS) \ - $(COMMON_WARNING_FLAGS) -Wno-old-style-declaration \ - $(CPPFLAGS) \ - $(CFLAGS) \ - $(EXTRA_CFLAGS)) - -# List of flags to pass to C++ compiler -# If any flags are defined in application Makefile, add them at the end. -CXXFLAGS := $(strip \ - -std=gnu++11 \ - $(OPTIMIZATION_FLAGS) $(DEBUG_FLAGS) \ - $(COMMON_FLAGS) \ - $(COMMON_WARNING_FLAGS) \ - $(CPPFLAGS) \ - $(CXXFLAGS) \ - $(EXTRA_CXXFLAGS)) - -ifdef CONFIG_COMPILER_CXX_EXCEPTIONS -CXXFLAGS += -fexceptions -else -CXXFLAGS += -fno-exceptions +ifeq ($(SMING_RELEASE),1) +CPPFLAGS += -freorder-blocks endif -ifdef CONFIG_COMPILER_CXX_RTTI -CXXFLAGS += -frtti -else -CXXFLAGS += -fno-rtti -LDFLAGS += -fno-rtti -endif - -ARFLAGS := cru - # => Tools MEMANALYZER = $(PYTHON) $(ARCH_TOOLS)/memanalyzer.py $(OBJDUMP)$(TOOL_EXT) diff --git a/Sming/Arch/Esp32/esp32-soc.json b/Sming/Arch/Esp32/esp32-soc.json new file mode 100644 index 0000000000..a03565cef1 --- /dev/null +++ b/Sming/Arch/Esp32/esp32-soc.json @@ -0,0 +1,4 @@ +{ + "variant": "esp32", + "name": "ESP32" +} \ No newline at end of file diff --git a/Sming/Arch/Esp32/esp32c3-soc.json b/Sming/Arch/Esp32/esp32c3-soc.json new file mode 100644 index 0000000000..4e0ac3bf2e --- /dev/null +++ b/Sming/Arch/Esp32/esp32c3-soc.json @@ -0,0 +1,4 @@ +{ + "variant": "esp32c3", + "name": "ESP32-C3" +} \ No newline at end of file diff --git a/Sming/Arch/Esp32/esp32s2-soc.json b/Sming/Arch/Esp32/esp32s2-soc.json new file mode 100644 index 0000000000..7000a1c8f1 --- /dev/null +++ b/Sming/Arch/Esp32/esp32s2-soc.json @@ -0,0 +1,4 @@ +{ + "variant": "esp32s2", + "name": "ESP32-S2" +} \ No newline at end of file diff --git a/Sming/Arch/Esp32/esp32s3-soc.json b/Sming/Arch/Esp32/esp32s3-soc.json new file mode 100644 index 0000000000..65023576bb --- /dev/null +++ b/Sming/Arch/Esp32/esp32s3-soc.json @@ -0,0 +1,4 @@ +{ + "variant": "esp32s3", + "name": "ESP32-S3" +} \ No newline at end of file diff --git a/Sming/Arch/Esp32/standard.hw b/Sming/Arch/Esp32/standard.hw index 2083a769eb..f648416ce8 100644 --- a/Sming/Arch/Esp32/standard.hw +++ b/Sming/Arch/Esp32/standard.hw @@ -27,7 +27,7 @@ }, "factory": { "address": "0x010000", - "size": "0x180000", + "size": "0x0f0000", "type": "app", "subtype": "factory", "filename": "$(TARGET_BIN)" diff --git a/Sming/Arch/Esp8266/Components/driver/Kconfig b/Sming/Arch/Esp8266/Components/driver/Kconfig new file mode 100644 index 0000000000..566932a5af --- /dev/null +++ b/Sming/Arch/Esp8266/Components/driver/Kconfig @@ -0,0 +1,22 @@ +menu "Drivers" + config USE_US_TIMER + bool "Enable microsecond precision for software timers (Timer2)" + help + The following functions depend on Timer2: + - NOW() return value, the Timer2 tick count + - Software timers + - System time + + Software timers are driven by Timer2, which by default uses a /256 prescale + providing a resolution of 3.2us and a range of 1' 54". + + Enabling this setting increases the resolution to 200ns but reduces the maximum + software timer to 7" 9.5s. + + config ENABLE_CUSTOM_PWM + bool "Use the *New PWM* driver" + default y + help + New PWM is a drop-in replacement for the version provided in the Espressif SDK. + +endmenu diff --git a/Sming/Arch/Esp8266/Components/driver/component.mk b/Sming/Arch/Esp8266/Components/driver/component.mk index 57551f91b2..88d3aed302 100644 --- a/Sming/Arch/Esp8266/Components/driver/component.mk +++ b/Sming/Arch/Esp8266/Components/driver/component.mk @@ -19,7 +19,6 @@ endif COMPONENT_RELINK_VARS += ENABLE_CUSTOM_PWM ENABLE_CUSTOM_PWM ?= 1 ifeq ($(ENABLE_CUSTOM_PWM), 1) - COMPONENT_SUBMODULES += new-pwm COMPONENT_SRCDIRS += new-pwm COMPONENT_CFLAGS += -DSDK_PWM_PERIOD_COMPAT_MODE=1 else diff --git a/Sming/Arch/Esp8266/Components/driver/i2s.cpp b/Sming/Arch/Esp8266/Components/driver/i2s.cpp index 40fbb545ce..374463a332 100644 --- a/Sming/Arch/Esp8266/Components/driver/i2s.cpp +++ b/Sming/Arch/Esp8266/Components/driver/i2s.cpp @@ -47,7 +47,6 @@ #include #include #include -#include #include #include diff --git a/Sming/Arch/Esp8266/Components/driver/include/driver/os_timer.h b/Sming/Arch/Esp8266/Components/driver/include/driver/os_timer.h index 431075a973..7598a8821e 100644 --- a/Sming/Arch/Esp8266/Components/driver/include/driver/os_timer.h +++ b/Sming/Arch/Esp8266/Components/driver/include/driver/os_timer.h @@ -14,7 +14,13 @@ #pragma once -#include +#include + +// Disarmed +#define OS_TIMER_DEFAULT() \ + { \ + .timer_next = (os_timer_t*)-1, \ + } // Disarmed #define OS_TIMER_DEFAULT() \ diff --git a/Sming/Arch/Esp8266/Components/driver/new-pwm b/Sming/Arch/Esp8266/Components/driver/new-pwm deleted file mode 160000 index 19cb69e9ce..0000000000 --- a/Sming/Arch/Esp8266/Components/driver/new-pwm +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 19cb69e9ce5071686d0e2a28962fd06e11d03a61 diff --git a/Sming/Arch/Esp8266/Components/driver/new-pwm.patch b/Sming/Arch/Esp8266/Components/driver/new-pwm.patch deleted file mode 100644 index c3d5b2d084..0000000000 --- a/Sming/Arch/Esp8266/Components/driver/new-pwm.patch +++ /dev/null @@ -1,83 +0,0 @@ -diff --git a/pwm.c b/pwm.c -index 6df21ac..06dda6a 100644 ---- a/pwm.c -+++ b/pwm.c -@@ -16,6 +16,8 @@ - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -+#include -+ - /* Set the following three defines to your needs */ - - #ifndef SDK_PWM_PERIOD_COMPAT_MODE -@@ -31,10 +33,10 @@ - - #define PWM_MAX_TICKS 0x7fffff - #if SDK_PWM_PERIOD_COMPAT_MODE --#define PWM_PERIOD_TO_TICKS(x) (x * 0.2) --#define PWM_DUTY_TO_TICKS(x) (x * 5) --#define PWM_MAX_DUTY (PWM_MAX_TICKS * 0.2) --#define PWM_MAX_PERIOD (PWM_MAX_TICKS * 5) -+#define PWM_PERIOD_TO_TICKS(x) (x * 5) -+#define PWM_DUTY_TO_TICKS(x) (x * 0.2) -+#define PWM_MAX_DUTY (PWM_MAX_TICKS * 5) -+#define PWM_MAX_PERIOD (PWM_MAX_TICKS * 0.2) - #else - #define PWM_PERIOD_TO_TICKS(x) (x) - #define PWM_DUTY_TO_TICKS(x) (x) -@@ -45,6 +47,8 @@ - #include - #include - #include -+#include -+#include - #include - - // from SDK hw_timer.c -@@ -109,8 +113,8 @@ struct timer_regs { - }; - static struct timer_regs* timer = (struct timer_regs*)(0x60000600); - --static void ICACHE_RAM_ATTR --pwm_intr_handler(void) -+static void IRAM_ATTR -+pwm_intr_handler(void* param) - { - if ((pwm_state.current_set[pwm_state.current_phase].off_mask == 0) && - (pwm_state.current_set[pwm_state.current_phase].on_mask == 0)) { -@@ -120,7 +124,7 @@ pwm_intr_handler(void) - - do { - // force write to GPIO registers on each loop -- asm volatile ("" : : : "memory"); -+ __asm__ volatile ("" : : : "memory"); - - gpio->out_w1ts = (uint32_t)(pwm_state.current_set[pwm_state.current_phase].on_mask); - gpio->out_w1tc = (uint32_t)(pwm_state.current_set[pwm_state.current_phase].off_mask); -@@ -142,7 +146,7 @@ pwm_intr_handler(void) - do { - ticks -= 1; - // stop compiler from optimizing delay loop to noop -- asm volatile ("" : : : "memory"); -+ __asm__ volatile ("" : : : "memory"); - } while (ticks > 0); - } - -@@ -209,7 +213,6 @@ _pwm_phases_prep(struct pwm_phase* pwm) - { - uint8_t n, phases; - -- uint16_t off_mask = 0; - for (n = 0; n < pwm_channels + 2; n++) { - pwm[n].ticks = 0; - pwm[n].on_mask = 0; -@@ -390,7 +393,7 @@ pwm_start(void) - pwm_state.current_set = pwm_state.next_set = *pwm; - pwm_state.current_phase = phases - 1; - ETS_FRC1_INTR_ENABLE(); -- RTC_REG_WRITE(FRC1_LOAD_ADDRESS, 0); -+ WRITE_PERI_REG(FRC1_LOAD_ADDRESS, 0); - timer->frc1_ctrl = TIMER1_DIVIDE_BY_16 | TIMER1_ENABLE_TIMER; - return; - } diff --git a/Sming/Arch/Esp8266/Components/driver/new-pwm/LICENSE b/Sming/Arch/Esp8266/Components/driver/new-pwm/LICENSE new file mode 100644 index 0000000000..23cb790338 --- /dev/null +++ b/Sming/Arch/Esp8266/Components/driver/new-pwm/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {description} + Copyright (C) {year} {fullname} + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + {signature of Ty Coon}, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/Sming/Arch/Esp8266/Components/driver/new-pwm/README.md b/Sming/Arch/Esp8266/Components/driver/new-pwm/README.md new file mode 100644 index 0000000000..d9391a597e --- /dev/null +++ b/Sming/Arch/Esp8266/Components/driver/new-pwm/README.md @@ -0,0 +1,66 @@ +# ESP8266_new_pwm +This is a drop-in replacement for the ESP8266 SDK PWM + +If you like this project and want to support this and my other works, consider donating on Liberapay: + + Donate using Liberapay + +The software PWM provided in the ESP8266 SDK from Espressif has several drawbacks: + +1. Duty cycle limited to 90% (at 1kHz PWM period) +2. usable PWM period at most ~2KHz. +3. Incomplete documentation + +This replacement allows duty cycles from 0% to 100%, with a stepsize of 200ns. +This is 5000 steps for a 1kHz PWM, and 256 steps (8 bit of resolution) at 19kHz. + +If all channels are in steady state (either 0% of 100% in any combination), +the implementation goes to full idle, e.g. no interrupts. + +The code is a drop-in replacement for the SDK, it provides the same functions +as the SDK libpwm.a closed binary library. Just add pwm.c to your project. + +By default there is one small difference to the SDK. The code uses a unit of +200ns for both period and duty. E.g. for 10% duty cycle at 1kHz you need to +specify a period value of 5000 and a duty cycle value of 500, a duty cycle of +5000 or above switches the channel to full on. + +To have full compatibility with the SDK, you have to set the +SDK_PWM_PERIOD_COMPAT_MODE define to 1. If set, the code will use 1us for PWM +period and 40ns for the duty cycle. E.g. 10% duty cycle at 1kHz is set by a +period value of 1000 and a duty cycle value of 2500, full duty at 25000 and +above. + +Example usage: + + #define PWM_CHANNELS 5 + const uint32_t period = 5000; // * 200ns ^= 1 kHz + + // PWM setup + uint32 io_info[PWM_CHANNELS][3] = { + // MUX, FUNC, PIN + {PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12, 12}, + {PERIPHS_IO_MUX_MTDO_U, FUNC_GPIO15, 15}, + {PERIPHS_IO_MUX_MTCK_U, FUNC_GPIO13, 13}, + {PERIPHS_IO_MUX_MTMS_U, FUNC_GPIO14, 14}, + {PERIPHS_IO_MUX_GPIO5_U, FUNC_GPIO5 , 5}, + }; + + // initial duty: all off + uint32 pwm_duty_init[PWM_CHANNELS] = {0, 0, 0, 0, 0}; + + pwm_init(period, pwm_duty_init, PWM_CHANNELS, io_info); + pwm_start(); + + // do something like this whenever you want to change duty + pwm_set_duty(500, 1); // GPIO15: 10% + pwm_set_duty(5000, 1); // GPIO15: 100% + pwm_start(); // commit + +**CAVEATS** + +- **To set 100% duty, the duty must be *equal* to the period** + +- **The code uses the TIMER1 interrupt. If you use e.g. the + softtimer, there is a conflict. You can use NM1 for the PWM + instead.** diff --git a/Sming/Arch/Esp8266/Components/driver/new-pwm/pwm.c b/Sming/Arch/Esp8266/Components/driver/new-pwm/pwm.c new file mode 100644 index 0000000000..9fc9188e60 --- /dev/null +++ b/Sming/Arch/Esp8266/Components/driver/new-pwm/pwm.c @@ -0,0 +1,451 @@ +/* + * Copyright (C) 2016 Stefan Brüns + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Set the following three defines to your needs */ + +#ifndef SDK_PWM_PERIOD_COMPAT_MODE + #define SDK_PWM_PERIOD_COMPAT_MODE 0 +#endif +#ifndef PWM_MAX_CHANNELS + #define PWM_MAX_CHANNELS 8 +#endif +#define PWM_DEBUG 0 +#define PWM_USE_NMI 0 + +/* no user servicable parts beyond this point */ + +#define PWM_MAX_TICKS 0x7fffff +#if SDK_PWM_PERIOD_COMPAT_MODE +#define PWM_PERIOD_TO_TICKS(x) (x * 5) +#define PWM_DUTY_TO_TICKS(x) (x * 0.2) +#define PWM_MAX_DUTY (PWM_MAX_TICKS * 5) +#define PWM_MAX_PERIOD (PWM_MAX_TICKS * 0.2) +#else +#define PWM_PERIOD_TO_TICKS(x) (x) +#define PWM_DUTY_TO_TICKS(x) (x) +#define PWM_MAX_DUTY PWM_MAX_TICKS +#define PWM_MAX_PERIOD PWM_MAX_TICKS +#endif + +#include +#include +#include +#include +#include +#include +#include + +// from SDK hw_timer.c +#define TIMER1_DIVIDE_BY_16 0x0004 +#define TIMER1_ENABLE_TIMER 0x0080 + +struct pwm_phase { + uint32_t ticks; ///< delay until next phase, in 200ns units + uint16_t on_mask; ///< GPIO mask to switch on + uint16_t off_mask; ///< GPIO mask to switch off +}; + +/* Three sets of PWM phases, the active one, the one used + * starting with the next cycle, and the one updated + * by pwm_start. After the update pwm_next_set + * is set to the last updated set. pwm_current_set is set to + * pwm_next_set from the interrupt routine during the first + * pwm phase + */ +typedef struct pwm_phase (pwm_phase_array)[PWM_MAX_CHANNELS + 2]; +static pwm_phase_array pwm_phases[3]; +static struct { + struct pwm_phase* next_set; + struct pwm_phase* current_set; + uint8_t current_phase; +} pwm_state; + +static uint32_t pwm_period; +static uint32_t pwm_period_ticks; +static uint32_t pwm_duty[PWM_MAX_CHANNELS]; +static uint16_t gpio_mask[PWM_MAX_CHANNELS]; +static uint8_t pwm_channels; + +// 3-tuples of MUX_REGISTER, MUX_VALUE and GPIO number +typedef uint32_t (pin_info_type)[3]; + +struct gpio_regs { + uint32_t out; /* 0x60000300 */ + uint32_t out_w1ts; /* 0x60000304 */ + uint32_t out_w1tc; /* 0x60000308 */ + uint32_t enable; /* 0x6000030C */ + uint32_t enable_w1ts; /* 0x60000310 */ + uint32_t enable_w1tc; /* 0x60000314 */ + uint32_t in; /* 0x60000318 */ + uint32_t status; /* 0x6000031C */ + uint32_t status_w1ts; /* 0x60000320 */ + uint32_t status_w1tc; /* 0x60000324 */ +}; +static struct gpio_regs* gpio = (struct gpio_regs*)(0x60000300); + +struct timer_regs { + uint32_t frc1_load; /* 0x60000600 */ + uint32_t frc1_count; /* 0x60000604 */ + uint32_t frc1_ctrl; /* 0x60000608 */ + uint32_t frc1_int; /* 0x6000060C */ + uint8_t pad[16]; + uint32_t frc2_load; /* 0x60000620 */ + uint32_t frc2_count; /* 0x60000624 */ + uint32_t frc2_ctrl; /* 0x60000628 */ + uint32_t frc2_int; /* 0x6000062C */ + uint32_t frc2_alarm; /* 0x60000630 */ +}; +static struct timer_regs* timer = (struct timer_regs*)(0x60000600); + +static void IRAM_ATTR +pwm_intr_handler(void* param) +{ + if ((pwm_state.current_set[pwm_state.current_phase].off_mask == 0) && + (pwm_state.current_set[pwm_state.current_phase].on_mask == 0)) { + pwm_state.current_set = pwm_state.next_set; + pwm_state.current_phase = 0; + } + + do { + // force write to GPIO registers on each loop + __asm__ volatile ("" : : : "memory"); + + gpio->out_w1ts = (uint32_t)(pwm_state.current_set[pwm_state.current_phase].on_mask); + gpio->out_w1tc = (uint32_t)(pwm_state.current_set[pwm_state.current_phase].off_mask); + + uint32_t ticks = pwm_state.current_set[pwm_state.current_phase].ticks; + + pwm_state.current_phase++; + + if (ticks) { + if (ticks >= 16) { + // constant interrupt overhead + ticks -= 9; + timer->frc1_int &= ~FRC1_INT_CLR_MASK; + WRITE_PERI_REG(&timer->frc1_load, ticks); + return; + } + + ticks *= 4; + do { + ticks -= 1; + // stop compiler from optimizing delay loop to noop + __asm__ volatile ("" : : : "memory"); + } while (ticks > 0); + } + + } while (1); +} + +/** + * period: initial period (base unit 1us OR 200ns) + * duty: array of initial duty values, may be NULL, may be freed after pwm_init + * pwm_channel_num: number of channels to use + * pin_info_list: array of pin_info + */ +void ICACHE_FLASH_ATTR +pwm_init(uint32_t period, uint32_t *duty, uint32_t pwm_channel_num, + uint32_t (*pin_info_list)[3]) +{ + int i, j, n; + + pwm_channels = pwm_channel_num; + if (pwm_channels > PWM_MAX_CHANNELS) + pwm_channels = PWM_MAX_CHANNELS; + + for (i = 0; i < 3; i++) { + for (j = 0; j < (PWM_MAX_CHANNELS + 2); j++) { + pwm_phases[i][j].ticks = 0; + pwm_phases[i][j].on_mask = 0; + pwm_phases[i][j].off_mask = 0; + } + } + pwm_state.current_set = pwm_state.next_set = 0; + pwm_state.current_phase = 0; + + uint32_t all = 0; + // PIN info: MUX-Register, Mux-Setting, PIN-Nr + for (n = 0; n < pwm_channels; n++) { + pin_info_type* pin_info = &pin_info_list[n]; + PIN_FUNC_SELECT((*pin_info)[0], (*pin_info)[1]); + gpio_mask[n] = 1 << (*pin_info)[2]; + all |= 1 << (*pin_info)[2]; + if (duty) + pwm_set_duty(duty[n], n); + } + GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, all); + GPIO_REG_WRITE(GPIO_ENABLE_W1TS_ADDRESS, all); + + pwm_set_period(period); + +#if PWM_USE_NMI + ETS_FRC_TIMER1_NMI_INTR_ATTACH(pwm_intr_handler); +#else + ETS_FRC_TIMER1_INTR_ATTACH(pwm_intr_handler, NULL); +#endif + TM1_EDGE_INT_ENABLE(); + + timer->frc1_int &= ~FRC1_INT_CLR_MASK; + timer->frc1_ctrl = 0; + + pwm_start(); +} + +__attribute__ ((noinline)) +static uint8_t ICACHE_FLASH_ATTR +_pwm_phases_prep(struct pwm_phase* pwm) +{ + uint8_t n, phases; + + for (n = 0; n < pwm_channels + 2; n++) { + pwm[n].ticks = 0; + pwm[n].on_mask = 0; + pwm[n].off_mask = 0; + } + phases = 1; + for (n = 0; n < pwm_channels; n++) { + uint32_t ticks = PWM_DUTY_TO_TICKS(pwm_duty[n]); + if (ticks == 0) { + pwm[0].off_mask |= gpio_mask[n]; + } else if (ticks >= pwm_period_ticks) { + pwm[0].on_mask |= gpio_mask[n]; + } else { + if (ticks < (pwm_period_ticks/2)) { + pwm[phases].ticks = ticks; + pwm[0].on_mask |= gpio_mask[n]; + pwm[phases].off_mask = gpio_mask[n]; + } else { + pwm[phases].ticks = pwm_period_ticks - ticks; + pwm[phases].on_mask = gpio_mask[n]; + pwm[0].off_mask |= gpio_mask[n]; + } + phases++; + } + } + pwm[phases].ticks = pwm_period_ticks; + + // bubble sort, lowest to highest duty + n = 2; + while (n < phases) { + if (pwm[n].ticks < pwm[n - 1].ticks) { + struct pwm_phase t = pwm[n]; + pwm[n] = pwm[n - 1]; + pwm[n - 1] = t; + if (n > 2) + n--; + } else { + n++; + } + } + +#if PWM_DEBUG + int t = 0; + for (t = 0; t <= phases; t++) { + ets_printf("%d @%d: %04x %04x\n", t, pwm[t].ticks, pwm[t].on_mask, pwm[t].off_mask); + } +#endif + + // shift left to align right edge; + uint8_t l = 0, r = 1; + while (r <= phases) { + uint32_t diff = pwm[r].ticks - pwm[l].ticks; + if (diff && (diff <= 16)) { + uint16_t mask = pwm[r].on_mask | pwm[r].off_mask; + pwm[l].off_mask ^= pwm[r].off_mask; + pwm[l].on_mask ^= pwm[r].on_mask; + pwm[0].off_mask ^= pwm[r].on_mask; + pwm[0].on_mask ^= pwm[r].off_mask; + pwm[r].ticks = pwm_period_ticks - diff; + pwm[r].on_mask ^= mask; + pwm[r].off_mask ^= mask; + } else { + l = r; + } + r++; + } + +#if PWM_DEBUG + for (t = 0; t <= phases; t++) { + ets_printf("%d @%d: %04x %04x\n", t, pwm[t].ticks, pwm[t].on_mask, pwm[t].off_mask); + } +#endif + + // sort again + n = 2; + while (n <= phases) { + if (pwm[n].ticks < pwm[n - 1].ticks) { + struct pwm_phase t = pwm[n]; + pwm[n] = pwm[n - 1]; + pwm[n - 1] = t; + if (n > 2) + n--; + } else { + n++; + } + } + + // merge same duty + l = 0, r = 1; + while (r <= phases) { + if (pwm[r].ticks == pwm[l].ticks) { + pwm[l].off_mask |= pwm[r].off_mask; + pwm[l].on_mask |= pwm[r].on_mask; + pwm[r].on_mask = 0; + pwm[r].off_mask = 0; + } else { + l++; + if (l != r) { + struct pwm_phase t = pwm[l]; + pwm[l] = pwm[r]; + pwm[r] = t; + } + } + r++; + } + phases = l; + +#if PWM_DEBUG + for (t = 0; t <= phases; t++) { + ets_printf("%d @%d: %04x %04x\n", t, pwm[t].ticks, pwm[t].on_mask, pwm[t].off_mask); + } +#endif + + // transform absolute end time to phase durations + for (n = 0; n < phases; n++) { + pwm[n].ticks = + pwm[n + 1].ticks - pwm[n].ticks; + // subtract common overhead + pwm[n].ticks--; + } + pwm[phases].ticks = 0; + + // do a cyclic shift if last phase is short + if (pwm[phases - 1].ticks < 16) { + for (n = 0; n < phases - 1; n++) { + struct pwm_phase t = pwm[n]; + pwm[n] = pwm[n + 1]; + pwm[n + 1] = t; + } + } + +#if PWM_DEBUG + for (t = 0; t <= phases; t++) { + ets_printf("%d +%d: %04x %04x\n", t, pwm[t].ticks, pwm[t].on_mask, pwm[t].off_mask); + } + ets_printf("\n"); +#endif + + return phases; +} + +void ICACHE_FLASH_ATTR +pwm_start(void) +{ + pwm_phase_array* pwm = &pwm_phases[0]; + + if ((*pwm == pwm_state.next_set) || + (*pwm == pwm_state.current_set)) + pwm++; + if ((*pwm == pwm_state.next_set) || + (*pwm == pwm_state.current_set)) + pwm++; + + uint8_t phases = _pwm_phases_prep(*pwm); + + // all with 0% / 100% duty - stop timer + if (phases == 1) { + if (pwm_state.next_set) { +#if PWM_DEBUG + ets_printf("PWM stop\n"); +#endif + timer->frc1_ctrl = 0; + ETS_FRC1_INTR_DISABLE(); + } + pwm_state.next_set = NULL; + + GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, (*pwm)[0].on_mask); + GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, (*pwm)[0].off_mask); + + return; + } + + // start if not running + if (!pwm_state.next_set) { +#if PWM_DEBUG + ets_printf("PWM start\n"); +#endif + pwm_state.current_set = pwm_state.next_set = *pwm; + pwm_state.current_phase = phases - 1; + ETS_FRC1_INTR_ENABLE(); + WRITE_PERI_REG(FRC1_LOAD_ADDRESS, 0); + timer->frc1_ctrl = TIMER1_DIVIDE_BY_16 | TIMER1_ENABLE_TIMER; + return; + } + + pwm_state.next_set = *pwm; +} + +void ICACHE_FLASH_ATTR +pwm_set_duty(uint32_t duty, uint8_t channel) +{ + if (channel >= PWM_MAX_CHANNELS) + return; + + if (duty > PWM_MAX_DUTY) + duty = PWM_MAX_DUTY; + + pwm_duty[channel] = duty; +} + +uint32_t ICACHE_FLASH_ATTR +pwm_get_duty(uint8_t channel) +{ + if (channel >= PWM_MAX_CHANNELS) + return 0; + return pwm_duty[channel]; +} + +void ICACHE_FLASH_ATTR +pwm_set_period(uint32_t period) +{ + pwm_period = period; + + if (pwm_period > PWM_MAX_PERIOD) + pwm_period = PWM_MAX_PERIOD; + + pwm_period_ticks = PWM_PERIOD_TO_TICKS(period); +} + +uint32_t ICACHE_FLASH_ATTR +pwm_get_period(void) +{ + return pwm_period; +} + +uint32_t ICACHE_FLASH_ATTR +get_pwm_version(void) +{ + return 1; +} + +void ICACHE_FLASH_ATTR +set_pwm_debug_en(uint8_t print_en) +{ + (void) print_en; +} + diff --git a/Sming/Arch/Esp8266/Components/driver/uart.cpp b/Sming/Arch/Esp8266/Components/driver/uart.cpp index 5d3691c008..eb1277a444 100644 --- a/Sming/Arch/Esp8266/Components/driver/uart.cpp +++ b/Sming/Arch/Esp8266/Components/driver/uart.cpp @@ -48,6 +48,7 @@ #include #include #include +#include /* * Parameters relating to RX FIFO and buffer thresholds diff --git a/Sming/Arch/Esp8266/Components/esp-lwip/include/lwip/api.h b/Sming/Arch/Esp8266/Components/esp-lwip/include/lwip/api.h index 91b9e5d243..9d283ab753 100644 --- a/Sming/Arch/Esp8266/Components/esp-lwip/include/lwip/api.h +++ b/Sming/Arch/Esp8266/Components/esp-lwip/include/lwip/api.h @@ -145,7 +145,7 @@ struct netconn { } pcb; /** the last error this netconn had */ err_t last_err; - /** sem that is used to synchroneously execute functions in the core context */ + /** sem that is used to synchronously execute functions in the core context */ sys_sem_t op_completed; /** mbox where received packets are stored until they are fetched by the netconn application thread (can grow quite big) */ diff --git a/Sming/Arch/Esp8266/Components/esp-lwip/include/lwip/netdb.h b/Sming/Arch/Esp8266/Components/esp-lwip/include/lwip/netdb.h index 7587e2f2d1..a414cdb692 100644 --- a/Sming/Arch/Esp8266/Components/esp-lwip/include/lwip/netdb.h +++ b/Sming/Arch/Esp8266/Components/esp-lwip/include/lwip/netdb.h @@ -93,7 +93,7 @@ struct addrinfo { #endif /* LWIP_DNS_API_DECLARE_STRUCTS */ #if LWIP_DNS_API_DECLARE_H_ERRNO -/* application accessable error code set by the DNS API functions */ +/* application accessible error code set by the DNS API functions */ extern int h_errno; #endif /* LWIP_DNS_API_DECLARE_H_ERRNO*/ diff --git a/Sming/Arch/Esp8266/Components/esp-lwip/include/lwip/opt.h b/Sming/Arch/Esp8266/Components/esp-lwip/include/lwip/opt.h index 0d2b3fcc5f..8240363ae6 100644 --- a/Sming/Arch/Esp8266/Components/esp-lwip/include/lwip/opt.h +++ b/Sming/Arch/Esp8266/Components/esp-lwip/include/lwip/opt.h @@ -184,7 +184,7 @@ * MEMP_USE_CUSTOM_POOLS==1: whether to include a user file lwippools.h * that defines additional pools beyond the "standard" ones required * by lwIP. If you set this to 1, you must have lwippools.h in your - * inlude path somewhere. + * include path somewhere. */ #ifndef MEMP_USE_CUSTOM_POOLS #define MEMP_USE_CUSTOM_POOLS 0 @@ -736,7 +736,7 @@ #endif /** - * Only allow SNMP write actions that are 'safe' (e.g. disabeling netifs is not + * Only allow SNMP write actions that are 'safe' (e.g. disabling netifs is not * a safe action and disabled when SNMP_SAFE_REQUESTS = 1). * Unsafe requests are disabled by default! */ @@ -1059,7 +1059,7 @@ /** * PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is - * designed to accomodate single full size TCP frame in one pbuf, including + * designed to accommodate single full size TCP frame in one pbuf, including * TCP_MSS, IP header, and link header. */ #ifndef PBUF_POOL_BUFSIZE diff --git a/Sming/Arch/Esp8266/Components/esp-lwip/include/lwip/snmp_structs.h b/Sming/Arch/Esp8266/Components/esp-lwip/include/lwip/snmp_structs.h index 0d3b46a928..8b8f8bdf5c 100644 --- a/Sming/Arch/Esp8266/Components/esp-lwip/include/lwip/snmp_structs.h +++ b/Sming/Arch/Esp8266/Components/esp-lwip/include/lwip/snmp_structs.h @@ -154,7 +154,7 @@ struct mib_ram_array_node u8_t node_type; u16_t maxlength; - /* aditional struct members */ + /* additional struct members */ s32_t *objid; struct mib_node **nptr; }; @@ -202,7 +202,7 @@ struct mib_external_node /* additional struct members */ /** points to an external (in memory) record of some sort of addressing - information, passed to and interpreted by the funtions below */ + information, passed to and interpreted by the functions below */ void* addr_inf; /** tree levels under this node */ u8_t tree_levels; diff --git a/Sming/Arch/Esp8266/Components/esp-lwip/include/lwip/sys.h b/Sming/Arch/Esp8266/Components/esp-lwip/include/lwip/sys.h index 432d2de22e..9536aa82d5 100644 --- a/Sming/Arch/Esp8266/Components/esp-lwip/include/lwip/sys.h +++ b/Sming/Arch/Esp8266/Components/esp-lwip/include/lwip/sys.h @@ -148,7 +148,7 @@ void sys_sem_free(sys_sem_t *sem); /** Wait for a semaphore - forever/no timeout */ #define sys_sem_wait(sem) sys_arch_sem_wait(sem, 0) #ifndef sys_sem_valid -/** Check if a sempahore is valid/allocated: return 1 for valid, 0 for invalid */ +/** Check if a semaphore is valid/allocated: return 1 for valid, 0 for invalid */ int sys_sem_valid(sys_sem_t *sem); #endif #ifndef sys_sem_set_invalid @@ -185,7 +185,7 @@ err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg); or SYS_ARCH_TIMEOUT on timeout * The returned time has to be accurate to prevent timer jitter! */ u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout); -/* Allow port to override with a macro, e.g. special timout for sys_arch_mbox_fetch() */ +/* Allow port to override with a macro, e.g. special timeout for sys_arch_mbox_fetch() */ #ifndef sys_arch_mbox_tryfetch /** Wait for a new message to arrive in the mbox * @param mbox mbox to get a message from @@ -221,7 +221,7 @@ sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, #endif /* NO_SYS */ -/* sys_init() must be called before anthing else. */ +/* sys_init() must be called before anything else. */ void sys_init(void)ICACHE_FLASH_ATTR; #ifndef sys_jiffies diff --git a/Sming/Arch/Esp8266/Components/esp-lwip/include/lwip/tcp_impl.h b/Sming/Arch/Esp8266/Components/esp-lwip/include/lwip/tcp_impl.h index a756781afc..e9e3c7096d 100644 --- a/Sming/Arch/Esp8266/Components/esp-lwip/include/lwip/tcp_impl.h +++ b/Sming/Arch/Esp8266/Components/esp-lwip/include/lwip/tcp_impl.h @@ -187,7 +187,7 @@ PACK_STRUCT_END /** Flags used on input processing, not on pcb->flags */ #define TF_RESET (u8_t)0x08U /* Connection was reset. */ -#define TF_CLOSED (u8_t)0x10U /* Connection was sucessfully closed. */ +#define TF_CLOSED (u8_t)0x10U /* Connection was successfully closed. */ #define TF_GOT_FIN (u8_t)0x20U /* Connection was closed by the remote end. */ @@ -276,7 +276,7 @@ PACK_STRUCT_END /* This structure represents a TCP segment on the unsent, unacked and ooseq queues */ struct tcp_seg { - struct tcp_seg *next; /* used when putting segements on a queue */ + struct tcp_seg *next; /* used when putting segments on a queue */ struct pbuf *p; /* buffer containing data + TCP header */ void *dataptr; /* pointer to the TCP data in the pbuf */ u16_t len; /* the TCP length of this segment */ diff --git a/Sming/Arch/Esp8266/Components/esp-lwip/lwipopts.h b/Sming/Arch/Esp8266/Components/esp-lwip/lwipopts.h index 2047f04db3..3692ba6094 100644 --- a/Sming/Arch/Esp8266/Components/esp-lwip/lwipopts.h +++ b/Sming/Arch/Esp8266/Components/esp-lwip/lwipopts.h @@ -178,7 +178,7 @@ * MEMP_USE_CUSTOM_POOLS==1: whether to include a user file lwippools.h * that defines additional pools beyond the "standard" ones required * by lwIP. If you set this to 1, you must have lwippools.h in your - * inlude path somewhere. + * include path somewhere. */ #ifndef MEMP_USE_CUSTOM_POOLS #define MEMP_USE_CUSTOM_POOLS 0 @@ -727,7 +727,7 @@ #endif /** - * Only allow SNMP write actions that are 'safe' (e.g. disabeling netifs is not + * Only allow SNMP write actions that are 'safe' (e.g. disabling netifs is not * a safe action and disabled when SNMP_SAFE_REQUESTS = 1). * Unsafe requests are disabled by default! */ @@ -1064,7 +1064,7 @@ /** * PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is - * designed to accomodate single full size TCP frame in one pbuf, including + * designed to accommodate single full size TCP frame in one pbuf, including * TCP_MSS, IP header, and link header. */ #ifndef PBUF_POOL_BUFSIZE diff --git a/Sming/Arch/Esp8266/Components/esp-lwip/mem_manager.h b/Sming/Arch/Esp8266/Components/esp-lwip/mem_manager.h index c9c4ba684a..d3007fd043 100644 --- a/Sming/Arch/Esp8266/Components/esp-lwip/mem_manager.h +++ b/Sming/Arch/Esp8266/Components/esp-lwip/mem_manager.h @@ -11,8 +11,7 @@ #ifndef _SYSTEM_INCLUDE_MEM_MANAGER_H_ #define _SYSTEM_INCLUDE_MEM_MANAGER_H_ -//#include -#include +#include /*------------------------��������------------------------*/ diff --git a/Sming/Arch/Esp8266/Components/esp-open-lwip/component.mk b/Sming/Arch/Esp8266/Components/esp-open-lwip/component.mk index e9a77126cc..13ba166b61 100644 --- a/Sming/Arch/Esp8266/Components/esp-open-lwip/component.mk +++ b/Sming/Arch/Esp8266/Components/esp-open-lwip/component.mk @@ -73,8 +73,7 @@ COMPONENT_INCDIRS := esp-open-lwip/include # Fussy about include paths so override default INCDIR := \ $(COMPONENT_PATH)/esp-open-lwip/include \ - $(SDK_BASE)/include \ + $(ARCH_COMPONENTS)/esp8266/include \ $(SMING_HOME)/System/include \ - $(ARCH_SYS)/include \ $(ARCH_COMPONENTS)/libc/include \ $(SMING_HOME)/Wiring diff --git a/Sming/Arch/Esp8266/Components/esp-open-lwip/esp-open-lwip.patch b/Sming/Arch/Esp8266/Components/esp-open-lwip/esp-open-lwip.patch index b5dc45183b..95efde870b 100644 --- a/Sming/Arch/Esp8266/Components/esp-open-lwip/esp-open-lwip.patch +++ b/Sming/Arch/Esp8266/Components/esp-open-lwip/esp-open-lwip.patch @@ -1,29 +1,3 @@ -diff --git a/include/user_config.h b/include/user_config.h -index e69de29..d608ddf 100644 ---- a/include/user_config.h -+++ b/include/user_config.h -@@ -0,0 +1,21 @@ -+#ifndef _USER_CONFIG_LWIP_ -+#define _USER_CONFIG_LWIP_ -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include "c_types.h" -+typedef signed short sint16_t; -+ -+void ets_bzero(void *block, size_t size); -+bool ets_post(uint32_t prio, ETSSignal sig, ETSParam par); -+void ets_task(ETSTask task, uint32_t prio, ETSEvent * queue, uint8 qlen); -+ -+void system_pp_recycle_rx_pkt(void *eb); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /*_USER_CONFIG_LWIP_*/ diff --git a/Makefile.open b/Makefile.open index 1bc584f..e4af916 100644 --- a/Makefile.open @@ -76,32 +50,22 @@ index 1bc584f..e4af916 100644 $(LIB): $(OBJS) $(AR) rcs $@ $^ diff --git a/include/arch/cc.h b/include/arch/cc.h -index ff03b30..4a2b4d9 100644 +index ff03b30..5089589 100644 --- a/include/arch/cc.h +++ b/include/arch/cc.h -@@ -38,14 +38,31 @@ - #include "c_types.h" - #include "ets_sys.h" - #include "osapi.h" -+#include "mem.h" -+#include -+#include "FakePgmSpace.h" +@@ -34,18 +34,17 @@ + #ifndef __ARCH_CC_H__ + #define __ARCH_CC_H__ + +-//#include +-#include "c_types.h" +-#include "ets_sys.h" +-#include "osapi.h" ++#include ++#include + #define EFAULT 14 -+//Extra symbols to avoid implicit declaration warnings -+extern void *ets_memset(void *s, int c, size_t n); -+extern void *ets_memcpy(void *dest, const void *src, size_t n); -+ -+extern int ets_strlen(const char *s); -+extern int os_printf_plus(const char *format, ...) __attribute__ ((format (printf, 1, 2))); -+extern int ets_sprintf(char *str, const char *format, ...) __attribute__ ((format (printf, 2, 3))); -+//extern void ets_timer_arm_new(ETSTimer *ptimer, uint32_t milliseconds, bool repeat_flag, int isMstimer); -+extern void ets_timer_disarm(ETSTimer *a); -+extern void ets_timer_setfn(ETSTimer *t, ETSTimerFunc *pfunction, void *parg); -+extern uint32 r_rand(void); -+extern int ets_memcmp(const void *s1, const void *s2, size_t n); -+ +struct netif * eagle_lwip_getif(uint8 index); + //#define LWIP_PROVIDE_ERRNO @@ -114,7 +78,7 @@ index ff03b30..4a2b4d9 100644 #endif -@@ -56,6 +73,7 @@ typedef signed short s16_t; +@@ -56,6 +55,7 @@ typedef signed short s16_t; typedef unsigned long u32_t; typedef signed long s32_t; typedef unsigned long mem_ptr_t; @@ -122,7 +86,7 @@ index ff03b30..4a2b4d9 100644 #define S16_F "d" #define U16_F "d" -@@ -73,11 +91,12 @@ typedef unsigned long mem_ptr_t; +@@ -73,11 +73,9 @@ typedef unsigned long mem_ptr_t; #define PACK_STRUCT_BEGIN #define PACK_STRUCT_END @@ -131,11 +95,8 @@ index ff03b30..4a2b4d9 100644 #ifdef LWIP_DEBUG -#define LWIP_PLATFORM_DIAG(x) os_printf x -#define LWIP_PLATFORM_ASSERT(x) ETS_ASSERT(x) -+#include "debug_progmem.h" -+ +#define LWIP_PLATFORM_DIAG(x) debug_i x +#define LWIP_PLATFORM_ASSERT(x) m_printf("ASSERT: %s %s %d", (x), __FUNCTION__, __LINE__) -+ #else #define LWIP_PLATFORM_DIAG(x) #define LWIP_PLATFORM_ASSERT(x) @@ -345,56 +306,124 @@ index c90adcd..f0c9dea 100644 } #endif diff --git a/include/lwip/mem.h b/include/lwip/mem.h -index af6e360..71b2178 100644 +index af6e360..b21ba7f 100644 --- a/include/lwip/mem.h +++ b/include/lwip/mem.h -@@ -52,19 +52,19 @@ typedef size_t mem_size_t; +@@ -33,16 +33,12 @@ + #define __LWIP_MEM_H__ + + #include "lwip/opt.h" +-//#include "mem_manager.h" ++#include + + #ifdef __cplusplus + extern "C" { + #endif + +-#if MEM_LIBC_MALLOC +- +-#include /* for size_t */ +- + typedef size_t mem_size_t; + + /* aliases for C library malloc() */ +@@ -50,91 +46,17 @@ typedef size_t mem_size_t; + /* in case C library malloc() needs extra protection, + * allow these defines to be overridden. */ - #ifndef MEMLEAK_DEBUG - #ifndef mem_free +-#ifndef MEMLEAK_DEBUG +-#ifndef mem_free -#define mem_free vPortFree -+#define mem_free(s) vPortFree(s, "", __LINE__) - #endif - #ifndef mem_malloc +-#endif +-#ifndef mem_malloc -#define mem_malloc pvPortMalloc -+#define mem_malloc(s) pvPortMalloc(s, "", __LINE__, false) - #endif - #ifndef mem_calloc +-#endif +-#ifndef mem_calloc -#define mem_calloc pvPortCalloc -+#define mem_calloc(l, s) ({void* ptr = (void*)pvPortMalloc((l) * (s), "", __LINE__,true);if(ptr){os_memset(ptr,0x0,(l) * (s));} ptr;}) - #endif - #ifndef mem_realloc +-#endif +-#ifndef mem_realloc -#define mem_realloc pvPortRealloc -+#define mem_realloc(p, s) pvPortRealloc(p, s, "", __LINE__) - #endif - #ifndef mem_zalloc +-#endif +-#ifndef mem_zalloc -#define mem_zalloc pvPortZalloc -+#define mem_zalloc(s) pvPortZalloc(s, "", __LINE__) - #endif - #else - #ifndef mem_free -@@ -75,7 +75,7 @@ do{\ - }while(0) - #endif - #ifndef mem_malloc +-#endif +-#else +-#ifndef mem_free +-#define mem_free(s) \ +-do{\ +- const char *file = mem_debug_file;\ +- vPortFree(s, file, __LINE__);\ +-}while(0) +-#endif +-#ifndef mem_malloc -#define mem_malloc(s) ({const char *file = mem_debug_file; pvPortMalloc(s, file, __LINE__);}) -+#define mem_malloc(s) ({const char *file = mem_debug_file; pvPortMalloc(s, file, __LINE__, false);}) - #endif - #ifndef mem_calloc - #define mem_calloc(s) ({const char *file = mem_debug_file; pvPortCalloc(s, file, __LINE__);}) -@@ -90,7 +90,11 @@ do{\ - #endif - - #ifndef os_malloc +-#endif +-#ifndef mem_calloc +-#define mem_calloc(s) ({const char *file = mem_debug_file; pvPortCalloc(s, file, __LINE__);}) +-#endif +-#ifndef mem_realloc +-#define mem_realloc(p, s) ({const char *file = mem_debug_file; pvPortRealloc(p, s, file, __LINE__);}) +-#endif +-#ifndef mem_zalloc +-#define mem_zalloc(s) ({const char *file = mem_debug_file; pvPortZalloc(s, file, __LINE__);}) +-#endif +- +-#endif +- +-#ifndef os_malloc -#define os_malloc(s) mem_malloc((s)) -+#ifndef MEMLEAK_DEBUG -+#define os_malloc(s) pvPortMalloc(s, "", __LINE__,true) -+#else -+#define os_malloc(s) ({const char *file = mem_debug_file; pvPortMalloc(s, file, __LINE__, true);}) -+#endif +-#endif +-#ifndef os_realloc +-#define os_realloc(p, s) mem_realloc((p), (s)) +-#endif +-#ifndef os_zalloc +-#define os_zalloc(s) mem_zalloc((s)) +-#endif +-#ifndef os_free +-#define os_free(p) mem_free((p)) +-#endif ++#define mem_free(s) os_free(s) ++#define mem_malloc(s) os_malloc(s) ++#define mem_calloc(l, s) os_calloc(l, s) ++#define mem_realloc(p, s) os_realloc(p, s) ++#define mem_zalloc(s) os_zalloc(s) + + /* Since there is no C library allocation function to shrink memory without + moving it, define this to nothing. */ + #ifndef mem_trim + #define mem_trim(mem, size) (mem) #endif - #ifndef os_realloc - #define os_realloc(p, s) mem_realloc((p), (s)) +-#else /* MEM_LIBC_MALLOC */ +- +-/* MEM_SIZE would have to be aligned, but using 64000 here instead of +- * 65535 leaves some room for alignment... +- */ +-#if MEM_SIZE > 64000l +-typedef u32_t mem_size_t; +-#define MEM_SIZE_F U32_F +-#else +-typedef u16_t mem_size_t; +-#define MEM_SIZE_F U16_F +-#endif /* MEM_SIZE > 64000 */ +- +-#if MEM_USE_POOLS +-/** mem_init is not used when using pools instead of a heap */ +-#define mem_init() +-/** mem_trim is not used when using pools instead of a heap: +- we can't free part of a pool element and don't want to copy the rest */ +-#define mem_trim(mem, size) (mem) +-#else /* MEM_USE_POOLS */ +-/* lwIP alternative malloc */ +-void mem_init(void)ICACHE_FLASH_ATTR; +-void *mem_trim(void *mem, mem_size_t size)ICACHE_FLASH_ATTR; +-#endif /* MEM_USE_POOLS */ +-void *mem_malloc(mem_size_t size)ICACHE_FLASH_ATTR; +-void *mem_calloc(mem_size_t count, mem_size_t size)ICACHE_FLASH_ATTR; +-void mem_free(void *mem)ICACHE_FLASH_ATTR; +-#endif /* MEM_LIBC_MALLOC */ + + /** Calculate memory size for an aligned buffer - returns the next highest + * multiple of MEM_ALIGNMENT (e.g. LWIP_MEM_ALIGN_SIZE(3) and diff --git a/include/lwip/app/espconn.h b/include/lwip/app/espconn.h index ae9ed50..46420df 100644 --- a/include/lwip/app/espconn.h @@ -565,3 +594,14 @@ index 14e802e..61d36de 100644 void sntp_init(void); void sntp_stop(void); +diff --git a/espconn_dummy.c b/espconn_dummy.c +index bbb126a..4cd8840 100644 +--- a/espconn_dummy.c ++++ b/espconn_dummy.c +@@ -1,5 +1,3 @@ +-#include +- +-void ICACHE_FLASH_ATTR espconn_init(void) ++void espconn_init(void) + { + } diff --git a/Sming/Arch/Esp8266/Components/esp8266/README.rst b/Sming/Arch/Esp8266/Components/esp8266/README.rst index 21007d6872..37fa9c0e7b 100644 --- a/Sming/Arch/Esp8266/Components/esp8266/README.rst +++ b/Sming/Arch/Esp8266/Components/esp8266/README.rst @@ -4,47 +4,7 @@ Esp8266 Core Component .. highlight:: bash Contains startup code, crash handling and additional Esp8266-specific -support code. Sming may be built using a pre-installed SDK, or by using -the current version 3 SDK as a submodule. +support code. -.. attention:: - - At time of writing, SDK 3 does not appear to support use of devices with 256K or 512K memory, - such as the ESP-01. For now, please use the default SDK 1.5.4 or SDK 2.0.0. - -.. envvar:: SDK_BASE - - Points to the location of the Espressif Non-OS SDK. To use the Espressif version 3 SDK, you need - only set this variable to point at the Sming repository (:envvar:`SMING_HOME`). The actual location - will be subsituted by the build system and the SDK pulled in via GIT. - - So for Windows you need to do: - - .. code-block:: batch - - set SDK_BASE=%SMING_HOME% - - For Linux (bash): - - :: - - export SDK_BASE="$SMING_HOME" - - If you change this value then your application and Sming must both be recompiled: - - :: - - make components-clean clean - make - -.. envvar:: SDK_INTERNAL - - **READONLY** When compiled using the current (version 3+) Espressif SDK this value is set to 1. - -.. envvar:: SDK_LIBDIR - - **READONLY** Path to the directory containing SDK archive libraries - -.. envvar:: SDK_INCDIR - - **READONLY** Path to the directory containing SDK header files +Sming uses libraries from the ESP8266 NON-OS SDK version 3, imported as a submodule. +The header and linker files are provided by this Component. diff --git a/Sming/Arch/Esp8266/Components/esp8266/component.mk b/Sming/Arch/Esp8266/Components/esp8266/component.mk index 6470a76db2..a62bfe2fef 100644 --- a/Sming/Arch/Esp8266/Components/esp8266/component.mk +++ b/Sming/Arch/Esp8266/Components/esp8266/component.mk @@ -1,9 +1,6 @@ # base directory of the ESP8266 SDK package, absolute -COMPONENT_VARS := SDK_BASE - -SDK_BASE ?= $(COMPONENT_PATH)/ESP8266_NONOS_SDK - -SDK_BASE := $(call FixPath,$(SDK_BASE)) +COMPONENT_SUBMODULES := sdk +SDK_BASE := $(COMPONENT_PATH)/sdk DEBUG_VARS += FLASH_INIT_DATA FLASH_INIT_DATA_VCC FLASH_INIT_DATA = $(SDK_BASE)/bin/esp_init_data_default.bin @@ -16,21 +13,8 @@ ifeq ($(DISABLE_WIFI),1) COMPONENT_DEPENDS += esp-lwip endif -# => 'Internal' SDK - for SDK Version 3+ as submodule in Sming repository -# SDK_BASE just needs to point into our repo as it's overridden with the correct submodule path -# This provides backward-compatiblity, so $(SMING)/third-party/ESP8266_NONOS_SDK) still works -DEBUG_VARS += SDK_INTERNAL SDK_BASE -ifneq (,$(findstring $(SMING_HOME),$(SDK_BASE))) -GLOBAL_CFLAGS += -DSDK_INTERNAL=1 -SDK_INTERNAL := 1 -COMPONENT_SUBMODULES := ESP8266_NONOS_SDK -SDK_BASE := $(COMPONENT_PATH)/ESP8266_NONOS_SDK - $(FLASH_INIT_DATA): $(SDK_BASE)/.submodule $(Q) cp -f $(@D)/esp_init_data_default_v08.bin $@ -else -SDK_INTERNAL := 0 -endif PHY_TOOL := $(COMPONENT_PATH)/Tools/patch-phy-bin.py @@ -38,18 +22,14 @@ $(FLASH_INIT_DATA_VCC): $(FLASH_INIT_DATA) $(Q) cp $< $@ $(Q) $(PYTHON) $(PHY_TOOL) $@ -DEBUG_VARS += SDK_LIBDIR SDK_INCDIR SDK_LIBDIR := $(SDK_BASE)/lib -SDK_INCDIR := $(SDK_BASE)/include -COMPONENT_INCDIRS := include $(SDK_INCDIR) +COMPONENT_INCDIRS := include . -export SDK_INTERNAL export SDK_LIBDIR -export SDK_INCDIR COMPONENT_DOXYGEN_INPUT := \ - $(SDK_INCDIR)/gpio.h \ - $(SDK_INCDIR)/pwm.h + include/gpio.h \ + include/pwm.h # Crash handler hooks this so debugger can be invoked EXTRA_LDFLAGS := $(call Wrap,system_restart_local) @@ -61,7 +41,7 @@ EXTRA_LIBS := \ crypto \ hal -LIBDIRS += $(COMPONENT_PATH)/ld $(SDK_BASE)/ld $(SDK_LIBDIR) +LIBDIRS += $(COMPONENT_PATH)/ld $(SDK_LIBDIR) # SDK-provided crypto library # Some routines are available in ROM so strip them out diff --git a/Sming/Arch/Esp8266/Components/esp8266/crash_handler.c b/Sming/Arch/Esp8266/Components/esp8266/crash_handler.c index ce0fa8af6f..324a314ded 100644 --- a/Sming/Arch/Esp8266/Components/esp8266/crash_handler.c +++ b/Sming/Arch/Esp8266/Components/esp8266/crash_handler.c @@ -20,7 +20,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include #include "gdb/gdb_hooks.h" extern void __real_system_restart_local(); diff --git a/Sming/Arch/Esp8266/Components/esp8266/esp_cplusplus.cpp b/Sming/Arch/Esp8266/Components/esp8266/esp_cplusplus.cpp index 965f7fd879..f3991d5c86 100644 --- a/Sming/Arch/Esp8266/Components/esp8266/esp_cplusplus.cpp +++ b/Sming/Arch/Esp8266/Components/esp8266/esp_cplusplus.cpp @@ -9,8 +9,7 @@ ****/ #include -#include "include/esp_cplusplus.h" -#include +#include extern void (*__init_array_start)(); extern void (*__init_array_end)(); diff --git a/Sming/Arch/Esp8266/Components/esp8266/include/airkiss.h b/Sming/Arch/Esp8266/Components/esp8266/include/airkiss.h new file mode 100644 index 0000000000..752d5a3c53 --- /dev/null +++ b/Sming/Arch/Esp8266/Components/esp8266/include/airkiss.h @@ -0,0 +1,111 @@ +/* + * airkiss.h + * + * Created on: 2015-1-26 + * Author: peterfan + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void* (*airkiss_memset_fn)(void* ptr, int value, unsigned int num); +typedef void* (*airkiss_memcpy_fn)(void* dst, const void* src, unsigned int num); +typedef int (*airkiss_memcmp_fn)(const void* ptr1, const void* ptr2, unsigned int num); +typedef int (*airkiss_printf_fn)(const char* format, ...); + +typedef struct { + airkiss_memset_fn memset; + airkiss_memcpy_fn memcpy; + airkiss_memcmp_fn memcmp; + airkiss_printf_fn printf; + +} airkiss_config_t; + +/** + * @brief Get airkiss lib version. + * + * @attention The length of version is unknown + * + * @param null. + * + * @return const char* + */ + +const char* airkiss_version(void); + +typedef enum { + /* the length of the data buffer is lack*/ + AIRKISS_LAN_ERR_OVERFLOW = -5, + + /* Do not support the type of instruction */ + AIRKISS_LAN_ERR_CMD = -4, + + /* Error reading data package */ + AIRKISS_LAN_ERR_PAKE = -3, + + /* Error function passing parameters */ + AIRKISS_LAN_ERR_PARA = -2, + + /* Packet data error */ + AIRKISS_LAN_ERR_PKG = -1, + + /* Message format is correct */ + AIRKISS_LAN_CONTINUE = 0, + + /* Find equipment request packet is received */ + AIRKISS_LAN_SSDP_REQ = 1, + + /* Packet packaging complete */ + AIRKISS_LAN_PAKE_READY = 2 + +} airkiss_lan_ret_t; + +typedef enum { + AIRKISS_LAN_SSDP_REQ_CMD = 0x1, + AIRKISS_LAN_SSDP_RESP_CMD = 0x1001, + AIRKISS_LAN_SSDP_NOTIFY_CMD = 0x1002 +} airkiss_lan_cmdid_t; + +/** + * @brief Receive UDP packet and input this API for analyzing. + * + * @attention null. + * + * @param const void* body : The start of the UDP message body data pointer. + * @param unsigned short length : the effective length of data. + * @param const airkiss_config_t* config : input struct airkiss_config_t + * + * @return >=0 : succeed (reference airkiss_lan_ret_t) + * @return <0 : error code (reference airkiss_lan_ret_t) + */ + +int airkiss_lan_recv(const void* body, unsigned short length, const airkiss_config_t* config); + +/** + * @brief Packaging the UDP packet to send. + * + * @attention null. + * + * @param airkiss_lan_cmdid_t ak_lan_cmdid : The packet type. + * @param void* appid : Vendor's Wechat public number id. + * @param void* deviceid : device model id. + * @param void* _datain : the data to be sent. + * @param unsigned short inlength : the length of data to be sent. + * @param void* _dataout : Data buffer addr. + * @param unsigned short* outlength : the size of data buffer. + * @param const airkiss_config_t* config : input struct airkiss_config_t + * + * @return >=0 : succeed (reference airkiss_lan_ret_t) + * @return <0 : error code (reference airkiss_lan_ret_t) + */ + +int airkiss_lan_pack(airkiss_lan_cmdid_t ak_lan_cmdid, void* appid, void* deviceid, void* _datain, + unsigned short inlength, void* _dataout, unsigned short* outlength, + const airkiss_config_t* config); + +#ifdef __cplusplus +} +#endif diff --git a/Sming/Arch/Esp8266/Components/esp8266/include/eagle_soc.h b/Sming/Arch/Esp8266/Components/esp8266/include/eagle_soc.h new file mode 100644 index 0000000000..5c68511c0c --- /dev/null +++ b/Sming/Arch/Esp8266/Components/esp8266/include/eagle_soc.h @@ -0,0 +1,4 @@ +#pragma once + +#include "espinc/eagle_soc.h" +#include "espinc/timer_register.h" diff --git a/Sming/Arch/Esp8266/Components/esp8266/include/esp_cplusplus.h b/Sming/Arch/Esp8266/Components/esp8266/include/esp_cplusplus.h deleted file mode 100644 index d5695c066d..0000000000 --- a/Sming/Arch/Esp8266/Components/esp8266/include/esp_cplusplus.h +++ /dev/null @@ -1,13 +0,0 @@ -/**** - * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. - * Created 2015 by Skurydin Alexey - * http://github.com/SmingHub/Sming - * All files of the Sming Core are provided under the LGPL v3 license. - * - * esp_cplusplus.h - * - ****/ - -#pragma once - -void cpp_core_initialize(); diff --git a/Sming/Arch/Esp8266/Components/esp8266/include/esp_crypto.h b/Sming/Arch/Esp8266/Components/esp8266/include/esp_crypto.h index e6d10bb49a..bd5f7550f6 100644 --- a/Sming/Arch/Esp8266/Components/esp8266/include/esp_crypto.h +++ b/Sming/Arch/Esp8266/Components/esp8266/include/esp_crypto.h @@ -7,7 +7,7 @@ * esp_crypto.h - ROM / SDK crypto functions * * There are a bunch of routines available in the ESP8266 ROM and SDK which could save space, - * and also potentially improving performance since ROM routines dont't require cache RAM. + * and also potentially improving performance since ROM routines don't require cache RAM. * * This header file provides prototypes so they can be used without conflicting with other libraries. * diff --git a/Sming/Arch/Esp8266/Components/esp8266/include/esp_missing.h b/Sming/Arch/Esp8266/Components/esp8266/include/esp_missing.h deleted file mode 100644 index 13fe605ae0..0000000000 --- a/Sming/Arch/Esp8266/Components/esp8266/include/esp_missing.h +++ /dev/null @@ -1,75 +0,0 @@ -/**** - * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. - * Created 2015 by Skurydin Alexey - * http://github.com/SmingHub/Sming - * All files of the Sming Core are provided under the LGPL v3 license. - * - * esp_missing.h - * - * Definitions missing from some SDKs prior to 3.0. - * Included from esp_systemapi.h - * - ****/ - -#pragma once - -/* Omitted from early SDK versions, in c_types.h in later versions (note: we don't use the SDK c_types.h) */ -typedef enum { - OK = 0, - FAIL, - PENDING, - BUSY, - CANCEL, -} STATUS; - -#ifndef ETS_SLC_INUM - -#define ETS_SLC_INUM 1 - -#define ETS_SLC_INTR_ATTACH(func, arg) ets_isr_attach(ETS_SLC_INUM, (func), (void*)(arg)) - -#define ETS_SLC_INTR_ENABLE() ETS_INTR_ENABLE(ETS_SLC_INUM) - -#define ETS_SLC_INTR_DISABLE() ETS_INTR_DISABLE(ETS_SLC_INUM) - -#endif // ETS_SLC_INUM - -#ifndef SDK_INTERNAL -extern void ets_timer_arm_new(ETSTimer* ptimer, uint32_t milliseconds, bool repeat_flag, int isMstimer); -extern void ets_timer_disarm(ETSTimer* a); -extern void ets_timer_setfn(ETSTimer* t, ETSTimerFunc* pfunction, void* parg); - -extern void ets_delay_us(uint32_t us); - -extern void ets_isr_mask(unsigned intr); -extern void ets_isr_unmask(unsigned intr); - -typedef void (*ets_isr_t)(void*); - -extern void ets_isr_attach(int i, ets_isr_t func, void* arg); - -extern int ets_memcmp(const void* s1, const void* s2, size_t n); -extern void* ets_memcpy(void* dest, const void* src, size_t n); -extern void* ets_memset(void* s, int c, size_t n); - -extern void ets_install_putc1(void (*p)(char c)); -extern int ets_sprintf(char* str, const char* format, ...) __attribute__((format(printf, 2, 3))); -extern int ets_str2macaddr(void*, void*); -extern int ets_strcmp(const char* s1, const char* s2); -extern char* ets_strcpy(char* dest, const char* src); -const char* ets_strrchr(const char* str, int character); -extern int ets_strlen(const char* s); -extern int ets_strncmp(const char* s1, const char* s2, unsigned int len); -extern char* ets_strncpy(char* dest, const char* src, size_t n); -extern char* ets_strstr(const char* haystack, const char* needle); -extern int os_printf_plus(const char* format, ...) __attribute__((format(printf, 1, 2))); -extern int os_snprintf(char* str, size_t size, const char* format, ...) __attribute__((format(printf, 3, 4))); -extern int ets_vsnprintf(char* s, size_t n, const char* format, va_list arg) __attribute__((format(printf, 3, 0))); - -extern void ets_intr_lock(); -extern void ets_intr_unlock(); - -// Missing from SDK 1.5.x -extern void NmiTimSetFunc(void (*func)(void)); - -#endif /* SDK_INTERNAL */ diff --git a/Sming/Arch/Esp8266/Components/esp8266/include/esp_system.h b/Sming/Arch/Esp8266/Components/esp8266/include/esp_system.h new file mode 100644 index 0000000000..c7179a39b3 --- /dev/null +++ b/Sming/Arch/Esp8266/Components/esp8266/include/esp_system.h @@ -0,0 +1,229 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2016 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, + * it is 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. + * + */ + +/* + * Contains definitions from `user_interface.h` which do not relate to WiFi/networking. + */ + +#pragma once + +#include "os_type.h" +#include "osapi.h" +#include "ets_sys.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MAC2STR +#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] +#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" +#endif + +enum rst_reason { + REASON_DEFAULT_RST = 0, + REASON_WDT_RST = 1, + REASON_EXCEPTION_RST = 2, + REASON_SOFT_WDT_RST = 3, + REASON_SOFT_RESTART = 4, + REASON_DEEP_SLEEP_AWAKE = 5, + REASON_EXT_SYS_RST = 6, +}; + +struct rst_info { + uint32_t reason; + uint32_t exccause; + uint32_t epc1; + uint32_t epc2; + uint32_t epc3; + uint32_t excvaddr; + uint32_t depc; +}; + +struct rst_info* system_get_rst_info(void); + +#define UPGRADE_FW_BIN1 0x00 +#define UPGRADE_FW_BIN2 0x01 + +void system_restore(void); +void system_restart(void); + +bool system_deep_sleep_set_option(uint8_t option); +bool system_deep_sleep(uint64_t time_in_us); +bool system_deep_sleep_instant(uint64_t time_in_us); + +uint8_t system_upgrade_userbin_check(void); +void system_upgrade_reboot(void); +uint8_t system_upgrade_flag_check(); +void system_upgrade_flag_set(uint8_t flag); + +void system_timer_reinit(void); +uint32_t system_get_time(void); + +/* user task's prio must be 0/1/2 !!!*/ +enum { + USER_TASK_PRIO_0 = 0, + USER_TASK_PRIO_1, + USER_TASK_PRIO_2, + USER_TASK_PRIO_MAX, +}; + +bool system_os_task(os_task_t task, uint8_t prio, os_event_t* queue, uint8_t qlen); +bool system_os_post(uint8_t prio, os_signal_t sig, os_param_t par); + +void system_print_meminfo(void); +uint32_t system_get_free_heap_size(void); + +void system_set_os_print(uint8_t onoff); +uint8_t system_get_os_print(); + +uint64_t system_mktime(uint32_t year, uint32_t mon, uint32_t day, uint32_t hour, uint32_t min, uint32_t sec); + +uint32_t system_get_chip_id(void); + +typedef void (*init_done_cb_t)(void); + +void system_init_done_cb(init_done_cb_t cb); + +uint32_t system_rtc_clock_cali_proc(void); +uint32_t system_get_rtc_time(void); + +bool system_rtc_mem_read(uint8_t src_addr, void* des_addr, uint16_t load_size); +bool system_rtc_mem_write(uint8_t des_addr, const void* src_addr, uint16_t save_size); + +void system_uart_swap(void); +void system_uart_de_swap(void); + +uint16_t system_adc_read(void); +void system_adc_read_fast(uint16_t* adc_addr, uint16_t adc_num, uint8_t adc_clk_div); +uint16_t system_get_vdd33(void); + +const char* system_get_sdk_version(void); + +#define SYS_BOOT_ENHANCE_MODE 0 +#define SYS_BOOT_NORMAL_MODE 1 + +#define SYS_BOOT_NORMAL_BIN 0 +#define SYS_BOOT_TEST_BIN 1 + +uint8_t system_get_boot_version(void); +uint32_t system_get_userbin_addr(void); +uint8_t system_get_boot_mode(void); +bool system_restart_enhance(uint8_t bin_type, uint32_t bin_addr); + +#define SYS_CPU_80MHZ 80 +#define SYS_CPU_160MHZ 160 + +bool system_update_cpu_freq(uint8_t freq); +uint8_t system_get_cpu_freq(void); + +enum flash_size_map { + FLASH_SIZE_4M_MAP_256_256 = 0, /**< Flash size : 4Mbits. Map : 256KBytes + 256KBytes */ + FLASH_SIZE_2M, /**< Flash size : 2Mbits. Map : 256KBytes */ + FLASH_SIZE_8M_MAP_512_512, /**< Flash size : 8Mbits. Map : 512KBytes + 512KBytes */ + FLASH_SIZE_16M_MAP_512_512, /**< Flash size : 16Mbits. Map : 512KBytes + 512KBytes */ + FLASH_SIZE_32M_MAP_512_512, /**< Flash size : 32Mbits. Map : 512KBytes + 512KBytes */ + FLASH_SIZE_16M_MAP_1024_1024, /**< Flash size : 16Mbits. Map : 1024KBytes + 1024KBytes */ + FLASH_SIZE_32M_MAP_1024_1024, /**< Flash size : 32Mbits. Map : 1024KBytes + 1024KBytes */ + FLASH_SIZE_32M_MAP_2048_2048, /**< attention: don't support now ,just compatible for nodemcu; + Flash size : 32Mbits. Map : 2048KBytes + 2048KBytes */ + FLASH_SIZE_64M_MAP_1024_1024, /**< Flash size : 64Mbits. Map : 1024KBytes + 1024KBytes */ + FLASH_SIZE_128M_MAP_1024_1024, /**< Flash size : 128Mbits. Map : 1024KBytes + 1024KBytes */ +}; + +enum flash_size_map system_get_flash_size_map(void); + +void system_phy_set_max_tpw(uint8_t max_tpw); +void system_phy_set_tpw_via_vdd33(uint16_t vdd33); +void system_phy_set_rfoption(uint8_t option); +void system_phy_set_powerup_option(uint8_t option); + +bool system_param_save_with_protect(uint16_t start_sec, void* param, uint16_t len); +bool system_param_load(uint16_t start_sec, uint16_t offset, void* param, uint16_t len); + +void system_soft_wdt_stop(void); +void system_soft_wdt_restart(void); +void system_soft_wdt_feed(void); + +void system_show_malloc(void); + +typedef enum { + SYSTEM_PARTITION_INVALID = 0, + SYSTEM_PARTITION_BOOTLOADER, /* user can't modify this partition address, but can modify size */ + SYSTEM_PARTITION_OTA_1, /* user can't modify this partition address, but can modify size */ + SYSTEM_PARTITION_OTA_2, /* user can't modify this partition address, but can modify size */ + SYSTEM_PARTITION_RF_CAL, /* user must define this partition */ + SYSTEM_PARTITION_PHY_DATA, /* user must define this partition */ + SYSTEM_PARTITION_SYSTEM_PARAMETER, /* user must define this partition */ + SYSTEM_PARTITION_AT_PARAMETER, + SYSTEM_PARTITION_SSL_CLIENT_CERT_PRIVKEY, + SYSTEM_PARTITION_SSL_CLIENT_CA, + SYSTEM_PARTITION_SSL_SERVER_CERT_PRIVKEY, + SYSTEM_PARTITION_SSL_SERVER_CA, + SYSTEM_PARTITION_WPA2_ENTERPRISE_CERT_PRIVKEY, + SYSTEM_PARTITION_WPA2_ENTERPRISE_CA, + + SYSTEM_PARTITION_CUSTOMER_BEGIN = 100, /* user can define partition after here */ + SYSTEM_PARTITION_MAX +} partition_type_t; + +typedef struct { + partition_type_t type; /* the partition type */ + uint32_t addr; /* the partition address */ + uint32_t size; /* the partition size */ +} partition_item_t; + +/** + * @brief register partition table information, user MUST call it in user_pre_init() + * + * @param partition_table: the partition table + * @param partition_num: the partition number in partition table + * @param map: the flash map + * + * @return true : succeed + * @return false : fail + */ +bool system_partition_table_regist(const partition_item_t* partition_table, uint32_t partition_num, uint32_t map); + +/** + * @brief get ota partition size + * + * @return the size of ota partition + */ +uint32_t system_partition_get_ota_partition_size(void); + +/** + * @brief get partition information + * + * @param type: the partition type + * @param partition_item: the point to store partition information + * + * @return true : succeed + * @return false : fail + */ +bool system_partition_get_item(partition_type_t type, partition_item_t* partition_item); + +#ifdef __cplusplus +} +#endif diff --git a/Sming/Arch/Esp8266/Components/esp8266/include/esp_systemapi.h b/Sming/Arch/Esp8266/Components/esp8266/include/esp_systemapi.h index b3b727ba6f..ba8a143453 100644 --- a/Sming/Arch/Esp8266/Components/esp8266/include/esp_systemapi.h +++ b/Sming/Arch/Esp8266/Components/esp8266/include/esp_systemapi.h @@ -12,56 +12,25 @@ #pragma once -#ifdef __cplusplus -extern "C" { -#endif - -// ESP SDK config -#define LWIP_OPEN_SRC - // Default types -#define __CORRECT_ISO_CPP_STDLIB_H_PROTO #include #include #include - -// Remove buggy espconn -#define _NO_ESPCON_ - -// And c_types -#define _C_TYPES_H_ - #include -#include "esp_attr.h" +#include #include #include #include -#include -#include -#include -#include -#include "esp_missing.h" -#include -#ifdef ENABLE_ESPCONN -#include -#endif - -#include "m_printf.h" -#include "debug_progmem.h" -#include "stringutil.h" -#include "xtensa/xtruntime.h" - -#define __ESP8266_EX__ // System definition ESP8266 SOC - -#define LOCAL static +#include "gpio.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "sdk/mem.h" +#include +#include +#include #define SYSTEM_ERROR(fmt, ...) debug_e("ERROR: " fmt "\r\n", ##__VA_ARGS__) -extern void ets_wdt_enable(void); -extern void ets_wdt_disable(void); -extern void wdt_feed(void); - - /** @brief Disable interrupts * @retval Current interrupt level * @note Hardware timer is unaffected if operating in non-maskable mode @@ -75,7 +44,3 @@ extern void wdt_feed(void); /** @brief Restore interrupts to level saved from previous noInterrupts() call */ #define restoreInterrupts(level) XTOS_RESTORE_INTLEVEL(level) - -#ifdef __cplusplus -} -#endif diff --git a/Sming/Arch/Esp8266/Components/esp8266/include/esp_wifi.h b/Sming/Arch/Esp8266/Components/esp8266/include/esp_wifi.h new file mode 100644 index 0000000000..093eeb9c07 --- /dev/null +++ b/Sming/Arch/Esp8266/Components/esp8266/include/esp_wifi.h @@ -0,0 +1,618 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2016 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, + * it is 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. + * + */ + +/* + * The bulk of the SDK `user_interface.h` file + */ + +#pragma once + +#include "os_type.h" +#include "lwip/ip_addr.h" +#include "../sdk/include/queue.h" +#include "gpio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define NULL_MODE 0x00 +#define STATION_MODE 0x01 +#define SOFTAP_MODE 0x02 +#define STATIONAP_MODE 0x03 + +typedef enum _auth_mode { + AUTH_OPEN = 0, + AUTH_WEP, + AUTH_WPA_PSK, + AUTH_WPA2_PSK, + AUTH_WPA_WPA2_PSK, + AUTH_MAX, +} AUTH_MODE; + +typedef enum _cipher_type { + CIPHER_NONE = 0, + CIPHER_WEP40, + CIPHER_WEP104, + CIPHER_TKIP, + CIPHER_CCMP, + CIPHER_TKIP_CCMP, + CIPHER_UNKNOWN, +} CIPHER_TYPE; + +uint8_t wifi_get_opmode(void); +uint8_t wifi_get_opmode_default(void); +bool wifi_set_opmode(uint8_t opmode); +bool wifi_set_opmode_current(uint8_t opmode); +uint8_t wifi_get_broadcast_if(void); +bool wifi_set_broadcast_if(uint8_t interface); + +struct bss_info { + STAILQ_ENTRY(bss_info) next; + + uint8_t bssid[6]; + uint8_t ssid[32]; + uint8_t ssid_len; + uint8_t channel; + sint8 rssi; + AUTH_MODE authmode; + uint8_t is_hidden; + sint16 freq_offset; + sint16 freqcal_val; + uint8_t* esp_mesh_ie; + uint8_t simple_pair; + CIPHER_TYPE pairwise_cipher; + CIPHER_TYPE group_cipher; + uint32_t phy_11b : 1; + uint32_t phy_11g : 1; + uint32_t phy_11n : 1; + uint32_t wps : 1; + uint32_t reserved : 28; +}; + +typedef struct _scaninfo { + STAILQ_HEAD(, bss_info) * pbss; + struct espconn* pespconn; + uint8_t totalpage; + uint8_t pagenum; + uint8_t page_sn; + uint8_t data_cnt; +} scaninfo; + +typedef enum { + OK = 0, + FAIL, + PENDING, + BUSY, + CANCEL, +} STATUS; + +typedef void (*scan_done_cb_t)(void* arg, STATUS status); + +typedef struct { + int8 rssi; + AUTH_MODE authmode; +} wifi_fast_scan_threshold_t; + +struct station_config { + uint8_t ssid[32]; + uint8_t password[64]; + uint8_t channel; + uint8_t bssid_set; // Note: If bssid_set is 1, station will just connect to the router + // with both ssid[] and bssid[] matched. Please check about this. + uint8_t bssid[6]; + wifi_fast_scan_threshold_t threshold; + bool open_and_wep_mode_disable; // Can connect to open/wep router by default. + bool all_channel_scan; +}; + +bool wifi_station_get_config(struct station_config* config); +bool wifi_station_get_config_default(struct station_config* config); +bool wifi_station_set_config(struct station_config* config); +bool wifi_station_set_config_current(struct station_config* config); + +bool wifi_station_connect(void); +bool wifi_station_disconnect(void); + +void wifi_enable_signaling_measurement(void); +void wifi_disable_signaling_measurement(void); + +sint8 wifi_station_get_rssi(void); + +typedef enum { + WIFI_SCAN_TYPE_ACTIVE = 0, /**< active scan */ + WIFI_SCAN_TYPE_PASSIVE, /**< passive scan */ +} wifi_scan_type_t; + +/** @brief Range of active scan times per channel */ +typedef struct { + uint32_t min; /**< minimum active scan time per channel, units: millisecond */ + uint32_t max; /**< maximum active scan time per channel, units: millisecond, values above 1500ms may + cause station to disconnect from AP and are not recommended. */ +} wifi_active_scan_time_t; + +/** @brief Aggregate of active & passive scan time per channel */ +typedef union { + wifi_active_scan_time_t active; /**< active scan time per channel, units: millisecond. */ + uint32_t passive; /**< passive scan time per channel, units: millisecond, values above 1500ms may + cause station to disconnect from AP and are not recommended. */ +} wifi_scan_time_t; + +struct scan_config { + uint8_t* ssid; // Note: ssid == NULL, don't filter ssid. + uint8_t* bssid; // Note: bssid == NULL, don't filter bssid. + uint8_t channel; // Note: channel == 0, scan all channels, otherwise scan set channel. + uint8_t show_hidden; // Note: show_hidden == 1, can get hidden ssid routers' info. + wifi_scan_type_t scan_type; // scan type, active or passive + wifi_scan_time_t scan_time; // scan time per channel +}; + +bool wifi_station_scan(struct scan_config* config, scan_done_cb_t cb); + +uint8_t wifi_station_get_auto_connect(void); +bool wifi_station_set_auto_connect(uint8_t set); + +bool wifi_station_set_reconnect_policy(bool set); + +enum { + STATION_IDLE = 0, + STATION_CONNECTING, + STATION_WRONG_PASSWORD, + STATION_NO_AP_FOUND, + STATION_CONNECT_FAIL, + STATION_GOT_IP +}; + +enum dhcp_status { DHCP_STOPPED, DHCP_STARTED }; + +uint8_t wifi_station_get_connect_status(void); + +uint8_t wifi_station_get_current_ap_id(void); +bool wifi_station_ap_change(uint8_t current_ap_id); +bool wifi_station_ap_number_set(uint8_t ap_number); +uint8_t wifi_station_get_ap_info(struct station_config config[]); + +bool wifi_station_dhcpc_start(void); +bool wifi_station_dhcpc_stop(void); +enum dhcp_status wifi_station_dhcpc_status(void); +bool wifi_station_dhcpc_set_maxtry(uint8_t num); + +char* wifi_station_get_hostname(void); +bool wifi_station_set_hostname(char* name); + +int wifi_station_set_cert_key(uint8_t* client_cert, int client_cert_len, uint8_t* private_key, int private_key_len, + uint8_t* private_key_passwd, int private_key_passwd_len); +void wifi_station_clear_cert_key(void); +int wifi_station_set_username(uint8_t* username, int len); +void wifi_station_clear_username(void); + +struct softap_config { + uint8_t ssid[32]; + uint8_t password[64]; + uint8_t ssid_len; // Note: Recommend to set it according to your ssid + uint8_t channel; // Note: support 1 ~ 13 + AUTH_MODE authmode; // Note: Don't support AUTH_WEP in softAP mode. + uint8_t ssid_hidden; // Note: default 0 + uint8_t max_connection; // Note: default 4, max 4 + uint16_t beacon_interval; // Note: support 100 ~ 60000 ms, default 100 +}; + +bool wifi_softap_get_config(struct softap_config* config); +bool wifi_softap_get_config_default(struct softap_config* config); +bool wifi_softap_set_config(struct softap_config* config); +bool wifi_softap_set_config_current(struct softap_config* config); + +struct station_info { + STAILQ_ENTRY(station_info) next; + + uint8_t bssid[6]; + struct ip_addr ip; +}; + +struct dhcps_lease { + bool enable; + struct ip_addr start_ip; + struct ip_addr end_ip; +}; + +enum dhcps_offer_option { + OFFER_START = 0x00, + OFFER_ROUTER = 0x01, + OFFER_END, +}; + +uint8_t wifi_softap_get_station_num(void); +struct station_info* wifi_softap_get_station_info(void); +bool wifi_softap_set_station_info (uint8_t* mac, struct ip_addr*); +void wifi_softap_free_station_info(void); + +bool wifi_softap_dhcps_start(void); +bool wifi_softap_dhcps_stop(void); + +bool wifi_softap_set_dhcps_lease(struct dhcps_lease* please); +bool wifi_softap_get_dhcps_lease(struct dhcps_lease* please); +uint32_t wifi_softap_get_dhcps_lease_time(void); +bool wifi_softap_set_dhcps_lease_time(uint32_t minute); +bool wifi_softap_reset_dhcps_lease_time(void); + +enum dhcp_status wifi_softap_dhcps_status(void); +bool wifi_softap_set_dhcps_offer_option(uint8_t level, void* optarg); + +#define STATION_IF 0x00 +#define SOFTAP_IF 0x01 + +bool wifi_get_ip_info(uint8_t if_index, struct ip_info* info); +bool wifi_set_ip_info(uint8_t if_index, struct ip_info* info); +bool wifi_get_macaddr(uint8_t if_index, uint8_t* macaddr); +bool wifi_set_macaddr(uint8_t if_index, uint8_t* macaddr); + +uint8_t wifi_get_channel(void); +bool wifi_set_channel(uint8_t channel); + +void wifi_status_led_install(uint8_t gpio_id, uint32_t gpio_name, uint8_t gpio_func); +void wifi_status_led_uninstall(); + +void wifi_promiscuous_enable(uint8_t promiscuous); + +typedef void (*wifi_promiscuous_cb_t)(uint8_t* buf, uint16_t len); + +void wifi_set_promiscuous_rx_cb(wifi_promiscuous_cb_t cb); + +void wifi_promiscuous_set_mac(const uint8_t* address); + +enum phy_mode { PHY_MODE_11B = 1, PHY_MODE_11G = 2, PHY_MODE_11N = 3 }; + +enum phy_mode wifi_get_phy_mode(void); +bool wifi_set_phy_mode(enum phy_mode mode); + +enum sleep_type { NONE_SLEEP_T = 0, LIGHT_SLEEP_T, MODEM_SLEEP_T }; + +enum sleep_level { MIN_SLEEP_T, MAX_SLEEP_T }; + +bool wifi_set_sleep_type(enum sleep_type type); +enum sleep_type wifi_get_sleep_type(void); +bool wifi_set_sleep_level(enum sleep_level level); +enum sleep_level wifi_get_sleep_level(void); +bool wifi_set_listen_interval(uint8_t interval); +uint8_t wifi_get_listen_interval(void); + +void wifi_fpm_open(void); +void wifi_fpm_close(void); +void wifi_fpm_do_wakeup(void); +sint8 wifi_fpm_do_sleep(uint32_t sleep_time_in_us); +void wifi_fpm_set_sleep_type(enum sleep_type type); +enum sleep_type wifi_fpm_get_sleep_type(void); + +typedef void (*fpm_wakeup_cb)(void); +void wifi_fpm_set_wakeup_cb(fpm_wakeup_cb cb); + +void wifi_fpm_auto_sleep_set_in_null_mode(uint8_t req); + +enum { + EVENT_STAMODE_CONNECTED = 0, + EVENT_STAMODE_DISCONNECTED, + EVENT_STAMODE_AUTHMODE_CHANGE, + EVENT_STAMODE_GOT_IP, + EVENT_STAMODE_DHCP_TIMEOUT, + EVENT_SOFTAPMODE_STACONNECTED, + EVENT_SOFTAPMODE_STADISCONNECTED, + EVENT_SOFTAPMODE_PROBEREQRECVED, + EVENT_OPMODE_CHANGED, + EVENT_SOFTAPMODE_DISTRIBUTE_STA_IP, + EVENT_MAX +}; + +enum { + REASON_UNSPECIFIED = 1, + REASON_AUTH_EXPIRE = 2, + REASON_AUTH_LEAVE = 3, + REASON_ASSOC_EXPIRE = 4, + REASON_ASSOC_TOOMANY = 5, + REASON_NOT_AUTHED = 6, + REASON_NOT_ASSOCED = 7, + REASON_ASSOC_LEAVE = 8, + REASON_ASSOC_NOT_AUTHED = 9, + REASON_DISASSOC_PWRCAP_BAD = 10, /* 11h */ + REASON_DISASSOC_SUPCHAN_BAD = 11, /* 11h */ + REASON_IE_INVALID = 13, /* 11i */ + REASON_MIC_FAILURE = 14, /* 11i */ + REASON_4WAY_HANDSHAKE_TIMEOUT = 15, /* 11i */ + REASON_GROUP_KEY_UPDATE_TIMEOUT = 16, /* 11i */ + REASON_IE_IN_4WAY_DIFFERS = 17, /* 11i */ + REASON_GROUP_CIPHER_INVALID = 18, /* 11i */ + REASON_PAIRWISE_CIPHER_INVALID = 19, /* 11i */ + REASON_AKMP_INVALID = 20, /* 11i */ + REASON_UNSUPP_RSN_IE_VERSION = 21, /* 11i */ + REASON_INVALID_RSN_IE_CAP = 22, /* 11i */ + REASON_802_1X_AUTH_FAILED = 23, /* 11i */ + REASON_CIPHER_SUITE_REJECTED = 24, /* 11i */ + + REASON_BEACON_TIMEOUT = 200, + REASON_NO_AP_FOUND = 201, + REASON_AUTH_FAIL = 202, + REASON_ASSOC_FAIL = 203, + REASON_HANDSHAKE_TIMEOUT = 204, +}; + +typedef struct { + uint8_t ssid[32]; + uint8_t ssid_len; + uint8_t bssid[6]; + uint8_t channel; +} Event_StaMode_Connected_t; + +typedef struct { + uint8_t ssid[32]; + uint8_t ssid_len; + uint8_t bssid[6]; + uint8_t reason; +} Event_StaMode_Disconnected_t; + +typedef struct { + uint8_t old_mode; + uint8_t new_mode; +} Event_StaMode_AuthMode_Change_t; + +typedef struct { + struct ip_addr ip; + struct ip_addr mask; + struct ip_addr gw; +} Event_StaMode_Got_IP_t; + +typedef struct { + uint8_t mac[6]; + uint8_t aid; +} Event_SoftAPMode_StaConnected_t; + +typedef struct { + uint8_t mac[6]; + struct ip_addr ip; + uint8_t aid; +} Event_SoftAPMode_Distribute_Sta_IP_t; + +typedef struct { + uint8_t mac[6]; + uint8_t aid; +} Event_SoftAPMode_StaDisconnected_t; + +typedef struct { + int rssi; + uint8_t mac[6]; +} Event_SoftAPMode_ProbeReqRecved_t; + +typedef struct { + uint8_t old_opmode; + uint8_t new_opmode; +} Event_OpMode_Change_t; + +typedef union { + Event_StaMode_Connected_t connected; + Event_StaMode_Disconnected_t disconnected; + Event_StaMode_AuthMode_Change_t auth_change; + Event_StaMode_Got_IP_t got_ip; + Event_SoftAPMode_StaConnected_t sta_connected; + Event_SoftAPMode_Distribute_Sta_IP_t distribute_sta_ip; + Event_SoftAPMode_StaDisconnected_t sta_disconnected; + Event_SoftAPMode_ProbeReqRecved_t ap_probereqrecved; + Event_OpMode_Change_t opmode_changed; +} Event_Info_u; + +typedef struct _esp_event { + uint32_t event; + Event_Info_u event_info; +} System_Event_t; + +typedef void (*wifi_event_handler_cb_t)(System_Event_t* event); + +void wifi_set_event_handler_cb(wifi_event_handler_cb_t cb); + +typedef enum wps_type { + WPS_TYPE_DISABLE = 0, + WPS_TYPE_PBC, + WPS_TYPE_PIN, + WPS_TYPE_DISPLAY, + WPS_TYPE_MAX, +} WPS_TYPE_t; + +enum wps_cb_status { + WPS_CB_ST_SUCCESS = 0, + WPS_CB_ST_FAILED, + WPS_CB_ST_TIMEOUT, + WPS_CB_ST_WEP, +}; + +bool wifi_wps_enable(WPS_TYPE_t wps_type); +bool wifi_wps_disable(void); +bool wifi_wps_start(void); + +typedef void (*wps_st_cb_t)(int status); +bool wifi_set_wps_cb(wps_st_cb_t cb); + +typedef void (*freedom_outside_cb_t)(uint8_t status); +int wifi_register_send_pkt_freedom_cb(freedom_outside_cb_t cb); +void wifi_unregister_send_pkt_freedom_cb(void); +int wifi_send_pkt_freedom(uint8_t* buf, int len, bool sys_seq); + +int wifi_rfid_locp_recv_open(void); +void wifi_rfid_locp_recv_close(void); + +typedef void (*rfid_locp_cb_t)(uint8_t* frm, int len, int rssi); +int wifi_register_rfid_locp_recv_cb(rfid_locp_cb_t cb); +void wifi_unregister_rfid_locp_recv_cb(void); + +enum FIXED_RATE { + PHY_RATE_48 = 0x8, + PHY_RATE_24 = 0x9, + PHY_RATE_12 = 0xA, + PHY_RATE_6 = 0xB, + PHY_RATE_54 = 0xC, + PHY_RATE_36 = 0xD, + PHY_RATE_18 = 0xE, + PHY_RATE_9 = 0xF, +}; + +#define FIXED_RATE_MASK_NONE 0x00 +#define FIXED_RATE_MASK_STA 0x01 +#define FIXED_RATE_MASK_AP 0x02 +#define FIXED_RATE_MASK_ALL 0x03 + +int wifi_set_user_fixed_rate(uint8_t enable_mask, uint8_t rate); +int wifi_get_user_fixed_rate(uint8_t* enable_mask, uint8_t* rate); + +enum support_rate { + RATE_11B5M = 0, + RATE_11B11M = 1, + RATE_11B1M = 2, + RATE_11B2M = 3, + RATE_11G6M = 4, + RATE_11G12M = 5, + RATE_11G24M = 6, + RATE_11G48M = 7, + RATE_11G54M = 8, + RATE_11G9M = 9, + RATE_11G18M = 10, + RATE_11G36M = 11, +}; + +int wifi_set_user_sup_rate(uint8_t min, uint8_t max); + +enum RATE_11B_ID { + RATE_11B_B11M = 0, + RATE_11B_B5M = 1, + RATE_11B_B2M = 2, + RATE_11B_B1M = 3, +}; + +enum RATE_11G_ID { + RATE_11G_G54M = 0, + RATE_11G_G48M = 1, + RATE_11G_G36M = 2, + RATE_11G_G24M = 3, + RATE_11G_G18M = 4, + RATE_11G_G12M = 5, + RATE_11G_G9M = 6, + RATE_11G_G6M = 7, + RATE_11G_B5M = 8, + RATE_11G_B2M = 9, + RATE_11G_B1M = 10 +}; + +enum RATE_11N_ID { + RATE_11N_MCS7S = 0, + RATE_11N_MCS7 = 1, + RATE_11N_MCS6 = 2, + RATE_11N_MCS5 = 3, + RATE_11N_MCS4 = 4, + RATE_11N_MCS3 = 5, + RATE_11N_MCS2 = 6, + RATE_11N_MCS1 = 7, + RATE_11N_MCS0 = 8, + RATE_11N_B5M = 9, + RATE_11N_B2M = 10, + RATE_11N_B1M = 11 +}; + +#define RC_LIMIT_11B 0 +#define RC_LIMIT_11G 1 +#define RC_LIMIT_11N 2 +#define RC_LIMIT_P2P_11G 3 +#define RC_LIMIT_P2P_11N 4 +#define RC_LIMIT_NUM 5 + +#define LIMIT_RATE_MASK_NONE 0x00 +#define LIMIT_RATE_MASK_STA 0x01 +#define LIMIT_RATE_MASK_AP 0x02 +#define LIMIT_RATE_MASK_ALL 0x03 + +bool wifi_set_user_rate_limit(uint8_t mode, uint8_t ifidx, uint8_t max, uint8_t min); +uint8_t wifi_get_user_limit_rate_mask(void); +bool wifi_set_user_limit_rate_mask(uint8_t enable_mask); + +enum { + USER_IE_BEACON = 0, + USER_IE_PROBE_REQ, + USER_IE_PROBE_RESP, + USER_IE_ASSOC_REQ, + USER_IE_ASSOC_RESP, + USER_IE_MAX, +}; + +typedef void (*user_ie_manufacturer_recv_cb_t)(uint8_t type, const uint8_t sa[6], const uint8_t m_oui[3], uint8_t* ie, + uint8_t ie_len, int rssi); + +bool wifi_set_user_ie(bool enable, uint8_t* m_oui, uint8_t type, uint8_t* user_ie, uint8_t len); +int wifi_register_user_ie_manufacturer_recv_cb(user_ie_manufacturer_recv_cb_t cb); +void wifi_unregister_user_ie_manufacturer_recv_cb(void); + +void wifi_enable_gpio_wakeup(uint32_t i, GPIO_INT_TYPE intr_status); +void wifi_disable_gpio_wakeup(void); + +void uart_div_modify(uint8_t uart_no, uint32_t DivLatchValue); + +typedef enum { + WIFI_COUNTRY_POLICY_AUTO, /**< Country policy is auto, use the country info of AP to which the station is connected */ + WIFI_COUNTRY_POLICY_MANUAL, /**< Country policy is manual, always use the configured country info */ +} WIFI_COUNTRY_POLICY; + +typedef struct { + char cc[3]; /**< country code string */ + uint8_t schan; /**< start channel */ + uint8_t nchan; /**< total channel number */ + uint8_t policy; /**< country policy */ +} wifi_country_t; + +/** + * @brief configure country info + * + * @attention 1. The default country is {.cc="CN", .schan=1, .nchan=13, policy=WIFI_COUNTRY_POLICY_AUTO} + * @attention 2. When the country policy is WIFI_COUNTRY_POLICY_AUTO, use the country info of AP to which the station is + * connected. E.g. if the configured country info is {.cc="USA", .schan=1, .nchan=11}, the country info of + * the AP to which the station is connected is {.cc="JP", .schan=1, .nchan=14}, then our country info is + * {.cc="JP", .schan=1, .nchan=14}. If the station disconnected from the AP, the country info back to + * {.cc="USA", .schan=1, .nchan=11} again. + * @attention 3. When the country policy is WIFI_COUNTRY_POLICY_MANUAL, always use the configured country info. + * @attention 4. When the country info is changed because of configuration or because the station connects to a different + * external AP, the country IE in probe response/beacon of the soft-AP is changed also. + * @attention 5. The country configuration is not stored into flash + * + * @param wifi_country_t *country: the configured country info + * + * @return true : succeed + * @return false : fail + */ +bool wifi_set_country(wifi_country_t* country); + +/** + * @brief get the current country info + * + * @param wifi_country_t *country: country info + * + * @return true : succeed + * @return false : fail + */ +bool wifi_get_country(wifi_country_t* country); + +#ifdef __cplusplus +} +#endif diff --git a/Sming/Arch/Esp8266/Components/esp8266/include/esp_wifi_sniffer.h b/Sming/Arch/Esp8266/Components/esp8266/include/esp_wifi_sniffer.h index 9814dcfe2c..9e5ee6e7d7 100644 --- a/Sming/Arch/Esp8266/Components/esp8266/include/esp_wifi_sniffer.h +++ b/Sming/Arch/Esp8266/Components/esp8266/include/esp_wifi_sniffer.h @@ -8,10 +8,10 @@ #pragma once -#include +#include /* ============================================== - Promiscous callback structures, see ESP manual + Promiscuous callback structures, see ESP manual ============================================== */ struct RxControl { signed rssi : 8; diff --git a/Sming/Arch/Esp8266/Components/esp8266/include/espconn.h b/Sming/Arch/Esp8266/Components/esp8266/include/espconn.h new file mode 100644 index 0000000000..acfc4f67d0 --- /dev/null +++ b/Sming/Arch/Esp8266/Components/esp8266/include/espconn.h @@ -0,0 +1,755 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2016 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, + * it is free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef __ESPCONN_H__ +#define __ESPCONN_H__ + +typedef sint8 err_t; + +typedef void *espconn_handle; +typedef void (* espconn_connect_callback)(void *arg); +typedef void (* espconn_reconnect_callback)(void *arg, sint8 err); + +/* Definitions for error constants. */ + +#define ESPCONN_OK 0 /* No error, everything OK. */ +#define ESPCONN_MEM -1 /* Out of memory error. */ +#define ESPCONN_TIMEOUT -3 /* Timeout. */ +#define ESPCONN_RTE -4 /* Routing problem. */ +#define ESPCONN_INPROGRESS -5 /* Operation in progress */ +#define ESPCONN_MAXNUM -7 /* Total number exceeds the set maximum*/ + +#define ESPCONN_ABRT -8 /* Connection aborted. */ +#define ESPCONN_RST -9 /* Connection reset. */ +#define ESPCONN_CLSD -10 /* Connection closed. */ +#define ESPCONN_CONN -11 /* Not connected. */ + +#define ESPCONN_ARG -12 /* Illegal argument. */ +#define ESPCONN_IF -14 /* UDP send error */ +#define ESPCONN_ISCONN -15 /* Already connected. */ + +#define ESPCONN_HANDSHAKE -28 /* ssl handshake failed */ +#define ESPCONN_SSL_INVALID_DATA -61 /* ssl application invalid */ + +/** Protocol family and type of the espconn */ +enum espconn_type { + ESPCONN_INVALID = 0, + /* ESPCONN_TCP Group */ + ESPCONN_TCP = 0x10, + /* ESPCONN_UDP Group */ + ESPCONN_UDP = 0x20, +}; + +/** Current state of the espconn. Non-TCP espconn are always in state ESPCONN_NONE! */ +enum espconn_state { + ESPCONN_NONE, + ESPCONN_WAIT, + ESPCONN_LISTEN, + ESPCONN_CONNECT, + ESPCONN_WRITE, + ESPCONN_READ, + ESPCONN_CLOSE +}; + +typedef struct _esp_tcp { + int remote_port; + int local_port; + uint8 local_ip[4]; + uint8 remote_ip[4]; + espconn_connect_callback connect_callback; + espconn_reconnect_callback reconnect_callback; + espconn_connect_callback disconnect_callback; + espconn_connect_callback write_finish_fn; +} esp_tcp; + +typedef struct _esp_udp { + int remote_port; + int local_port; + uint8 local_ip[4]; + uint8 remote_ip[4]; +} esp_udp; + +typedef struct _remot_info{ + enum espconn_state state; + int remote_port; + uint8 remote_ip[4]; +}remot_info; + +/** A callback prototype to inform about events for a espconn */ +typedef void (* espconn_recv_callback)(void *arg, char *pdata, unsigned short len); +typedef void (* espconn_sent_callback)(void *arg); + +/** A espconn descriptor */ +struct espconn { + /** type of the espconn (TCP, UDP) */ + enum espconn_type type; + /** current state of the espconn */ + enum espconn_state state; + union { + esp_tcp *tcp; + esp_udp *udp; + } proto; + /** A callback function that is informed about events for this espconn */ + espconn_recv_callback recv_callback; + espconn_sent_callback sent_callback; + uint8 link_cnt; + void *reverse; +}; + +enum espconn_option{ + ESPCONN_START = 0x00, + ESPCONN_REUSEADDR = 0x01, + ESPCONN_NODELAY = 0x02, + ESPCONN_COPY = 0x04, + ESPCONN_KEEPALIVE = 0x08, + ESPCONN_MANUALRECV = 0x10, + ESPCONN_END +}; + +enum espconn_level{ + ESPCONN_KEEPIDLE, + ESPCONN_KEEPINTVL, + ESPCONN_KEEPCNT +}; + +enum { + ESPCONN_IDLE = 0, + ESPCONN_CLIENT, + ESPCONN_SERVER, + ESPCONN_BOTH, + ESPCONN_MAX +}; + +struct espconn_packet{ + uint16 sent_length; /* sent length successful*/ + uint16 snd_buf_size; /* Available buffer size for sending */ + uint16 snd_queuelen; /* Available buffer space for sending */ + uint16 total_queuelen; /* total Available buffer space for sending */ + uint32 packseqno; /* seqno to be sent */ + uint32 packseq_nxt; /* seqno expected */ + uint32 packnum; +}; + +struct mdns_info { + char *host_name; + char *server_name; + uint16 server_port; + unsigned long ipAddr; + char *txt_data[10]; +}; +/****************************************************************************** + * FunctionName : espconn_connect + * Description : The function given as the connect + * Parameters : espconn -- the espconn used to listen the connection + * Returns : none +*******************************************************************************/ + +sint8 espconn_connect(struct espconn *espconn); + +/****************************************************************************** + * FunctionName : espconn_disconnect + * Description : disconnect with host + * Parameters : espconn -- the espconn used to disconnect the connection + * Returns : none +*******************************************************************************/ + +sint8 espconn_disconnect(struct espconn *espconn); + +/****************************************************************************** + * FunctionName : espconn_delete + * Description : disconnect with host + * Parameters : espconn -- the espconn used to disconnect the connection + * Returns : none +*******************************************************************************/ + +sint8 espconn_delete(struct espconn *espconn); + +/****************************************************************************** + * FunctionName : espconn_accept + * Description : The function given as the listen + * Parameters : espconn -- the espconn used to listen the connection + * Returns : none +*******************************************************************************/ + +sint8 espconn_accept(struct espconn *espconn); + +/****************************************************************************** + * FunctionName : espconn_create + * Description : sent data for client or server + * Parameters : espconn -- espconn to the data transmission + * Returns : result +*******************************************************************************/ + +sint8 espconn_create(struct espconn *espconn); + +/****************************************************************************** + * FunctionName : espconn_tcp_get_max_con + * Description : get the number of simulatenously active TCP connections + * Parameters : none + * Returns : none +*******************************************************************************/ + +uint8 espconn_tcp_get_max_con(void); + +/****************************************************************************** + * FunctionName : espconn_tcp_set_max_con + * Description : set the number of simulatenously active TCP connections + * Parameters : num -- total number + * Returns : none +*******************************************************************************/ + +sint8 espconn_tcp_set_max_con(uint8 num); + +/****************************************************************************** + * FunctionName : espconn_tcp_get_max_con_allow + * Description : get the count of simulatenously active connections on the server + * Parameters : espconn -- espconn to get the count + * Returns : result +*******************************************************************************/ + +sint8 espconn_tcp_get_max_con_allow(struct espconn *espconn); + +/****************************************************************************** + * FunctionName : espconn_tcp_set_max_con_allow + * Description : set the count of simulatenously active connections on the server + * Parameters : espconn -- espconn to set the count + * num -- support the connection number + * Returns : result +*******************************************************************************/ + +sint8 espconn_tcp_set_max_con_allow(struct espconn *espconn, uint8 num); + +/****************************************************************************** + * FunctionName : espconn_regist_time + * Description : used to specify the time that should be called when don't recv data + * Parameters : espconn -- the espconn used to the connection + * interval -- the timer when don't recv data + * Returns : none +*******************************************************************************/ + +sint8 espconn_regist_time(struct espconn *espconn, uint32 interval, uint8 type_flag); + +/****************************************************************************** + * FunctionName : espconn_get_connection_info + * Description : used to specify the function that should be called when disconnect + * Parameters : espconn -- espconn to set the err callback + * discon_cb -- err callback function to call when err + * Returns : none +*******************************************************************************/ + +sint8 espconn_get_connection_info(struct espconn *pespconn, remot_info **pcon_info, uint8 typeflags); + +/****************************************************************************** + * FunctionName : espconn_get_packet_info + * Description : get the packet info with host + * Parameters : espconn -- the espconn used to disconnect the connection + * infoarg -- the packet info + * Returns : the errur code +*******************************************************************************/ + +sint8 espconn_get_packet_info(struct espconn *espconn, struct espconn_packet* infoarg); + +/****************************************************************************** + * FunctionName : espconn_regist_sentcb + * Description : Used to specify the function that should be called when data + * has been successfully delivered to the remote host. + * Parameters : struct espconn *espconn -- espconn to set the sent callback + * espconn_sent_callback sent_cb -- sent callback function to + * call for this espconn when data is successfully sent + * Returns : none +*******************************************************************************/ + +sint8 espconn_regist_sentcb(struct espconn *espconn, espconn_sent_callback sent_cb); + +/****************************************************************************** + * FunctionName : espconn_regist_sentcb + * Description : Used to specify the function that should be called when data + * has been successfully delivered to the remote host. + * Parameters : espconn -- espconn to set the sent callback + * sent_cb -- sent callback function to call for this espconn + * when data is successfully sent + * Returns : none +*******************************************************************************/ + +sint8 espconn_regist_write_finish(struct espconn *espconn, espconn_connect_callback write_finish_fn); + +/****************************************************************************** + * FunctionName : espconn_send + * Description : sent data for client or server + * Parameters : espconn -- espconn to set for client or server + * psent -- data to send + * length -- length of data to send + * Returns : none +*******************************************************************************/ + +sint8 espconn_send(struct espconn *espconn, uint8 *psent, uint16 length); + +/****************************************************************************** + * FunctionName : espconn_sent + * Description : sent data for client or server + * Parameters : espconn -- espconn to set for client or server + * psent -- data to send + * length -- length of data to send + * Returns : none +*******************************************************************************/ + +sint8 espconn_sent(struct espconn *espconn, uint8 *psent, uint16 length); + +/****************************************************************************** + * FunctionName : espconn_sendto + * Description : send data for UDP + * Parameters : espconn -- espconn to set for UDP + * psent -- data to send + * length -- length of data to send + * Returns : error +*******************************************************************************/ + +sint16 espconn_sendto(struct espconn *espconn, uint8 *psent, uint16 length); + +/****************************************************************************** + * FunctionName : espconn_regist_connectcb + * Description : used to specify the function that should be called when + * connects to host. + * Parameters : espconn -- espconn to set the connect callback + * connect_cb -- connected callback function to call when connected + * Returns : none +*******************************************************************************/ + +sint8 espconn_regist_connectcb(struct espconn *espconn, espconn_connect_callback connect_cb); + +/****************************************************************************** + * FunctionName : espconn_regist_recvcb + * Description : used to specify the function that should be called when recv + * data from host. + * Parameters : espconn -- espconn to set the recv callback + * recv_cb -- recv callback function to call when recv data + * Returns : none +*******************************************************************************/ + +sint8 espconn_regist_recvcb(struct espconn *espconn, espconn_recv_callback recv_cb); + +/****************************************************************************** + * FunctionName : espconn_regist_reconcb + * Description : used to specify the function that should be called when connection + * because of err disconnect. + * Parameters : espconn -- espconn to set the err callback + * recon_cb -- err callback function to call when err + * Returns : none +*******************************************************************************/ + +sint8 espconn_regist_reconcb(struct espconn *espconn, espconn_reconnect_callback recon_cb); + +/****************************************************************************** + * FunctionName : espconn_regist_disconcb + * Description : used to specify the function that should be called when disconnect + * Parameters : espconn -- espconn to set the err callback + * discon_cb -- err callback function to call when err + * Returns : none +*******************************************************************************/ + +sint8 espconn_regist_disconcb(struct espconn *espconn, espconn_connect_callback discon_cb); + +/****************************************************************************** + * FunctionName : espconn_port + * Description : access port value for client so that we don't end up bouncing + * all connections at the same time . + * Parameters : none + * Returns : access port value +*******************************************************************************/ + +uint32 espconn_port(void); + +/****************************************************************************** + * FunctionName : espconn_set_opt + * Description : access port value for client so that we don't end up bouncing + * all connections at the same time . + * Parameters : none + * Returns : access port value +*******************************************************************************/ + +sint8 espconn_set_opt(struct espconn *espconn, uint8 opt); + +/****************************************************************************** + * FunctionName : espconn_clear_opt + * Description : clear the option for connections so that we don't end up bouncing + * all connections at the same time . + * Parameters : espconn -- the espconn used to set the connection + * opt -- the option for clear + * Returns : the result +*******************************************************************************/ + +sint8 espconn_clear_opt(struct espconn *espconn, uint8 opt); + +/****************************************************************************** + * FunctionName : espconn_set_keepalive + * Description : access level value for connection so that we set the value for + * keep alive + * Parameters : espconn -- the espconn used to set the connection + * level -- the connection's level + * value -- the value of time(s) + * Returns : access port value +*******************************************************************************/ + +sint8 espconn_set_keepalive(struct espconn *espconn, uint8 level, void* optarg); + +/****************************************************************************** + * FunctionName : espconn_get_keepalive + * Description : access level value for connection so that we get the value for + * keep alive + * Parameters : espconn -- the espconn used to get the connection + * level -- the connection's level + * Returns : access keep alive value +*******************************************************************************/ + +sint8 espconn_get_keepalive(struct espconn *espconn, uint8 level, void *optarg); + +/****************************************************************************** + * TypedefName : dns_found_callback + * Description : Callback which is invoked when a hostname is found. + * Parameters : name -- pointer to the name that was looked up. + * ipaddr -- pointer to an ip_addr_t containing the IP address of + * the hostname, or NULL if the name could not be found (or on any + * other error). + * callback_arg -- a user-specified callback argument passed to + * dns_gethostbyname +*******************************************************************************/ + +typedef void (*dns_found_callback)(const char *name, ip_addr_t *ipaddr, void *callback_arg); + +/****************************************************************************** + * FunctionName : espconn_gethostbyname + * Description : Resolve a hostname (string) into an IP address. + * Parameters : pespconn -- espconn to resolve a hostname + * hostname -- the hostname that is to be queried + * addr -- pointer to a ip_addr_t where to store the address if + * it is already cached in the dns_table (only valid if ESPCONN_OK + * is returned!) + * found -- a callback function to be called on success, failure + * or timeout (only if ERR_INPROGRESS is returned!) + * Returns : err_t return code + * - ESPCONN_OK if hostname is a valid IP address string or the host + * name is already in the local names table. + * - ESPCONN_INPROGRESS enqueue a request to be sent to the DNS server + * for resolution if no errors are present. + * - ESPCONN_ARG: dns client not initialized or invalid hostname +*******************************************************************************/ + +err_t espconn_gethostbyname(struct espconn *pespconn, const char *hostname, ip_addr_t *addr, dns_found_callback found); + +/****************************************************************************** + * FunctionName : espconn_abort + * Description : Forcely abort with host + * Parameters : espconn -- the espconn used to connect with the host + * Returns : result +*******************************************************************************/ + +sint8 espconn_abort(struct espconn *espconn); + +/****************************************************************************** + * FunctionName : espconn_encry_connect + * Description : The function given as connection + * Parameters : espconn -- the espconn used to connect with the host + * Returns : none +*******************************************************************************/ + +sint8 espconn_secure_connect(struct espconn *espconn); + +/****************************************************************************** + * FunctionName : espconn_encry_disconnect + * Description : The function given as the disconnection + * Parameters : espconn -- the espconn used to disconnect with the host + * Returns : none +*******************************************************************************/ + +sint8 espconn_secure_disconnect(struct espconn *espconn); + +/****************************************************************************** + * FunctionName : espconn_secure_send + * Description : sent data for client or server + * Parameters : espconn -- espconn to set for client or server + * psent -- data to send + * length -- length of data to send + * Returns : none +*******************************************************************************/ + +sint8 espconn_secure_send(struct espconn *espconn, uint8 *psent, uint16 length); + +/****************************************************************************** + * FunctionName : espconn_encry_sent + * Description : sent data for client or server + * Parameters : espconn -- espconn to set for client or server + * psent -- data to send + * length -- length of data to send + * Returns : none +*******************************************************************************/ + +sint8 espconn_secure_sent(struct espconn *espconn, uint8 *psent, uint16 length); + +/****************************************************************************** + * FunctionName : espconn_secure_set_size + * Description : set the buffer size for client or server + * Parameters : level -- set for client or server + * 1: client,2:server,3:client and server + * size -- buffer size + * Returns : true or false +*******************************************************************************/ + +bool espconn_secure_set_size(uint8 level, uint16 size); + +/****************************************************************************** + * FunctionName : espconn_secure_get_size + * Description : get buffer size for client or server + * Parameters : level -- set for client or server + * 1: client,2:server,3:client and server + * Returns : buffer size for client or server +*******************************************************************************/ + +sint16 espconn_secure_get_size(uint8 level); + +/****************************************************************************** + * FunctionName : espconn_secure_ca_enable + * Description : enable the certificate authenticate and set the flash sector + * as client or server + * Parameters : level -- set for client or server + * 1: client,2:server,3:client and server + * flash_sector -- flash sector for save certificate + * Returns : result true or false +*******************************************************************************/ + +bool espconn_secure_ca_enable(uint8 level, uint32 flash_sector ); + +/****************************************************************************** + * FunctionName : espconn_secure_ca_disable + * Description : disable the certificate authenticate as client or server + * Parameters : level -- set for client or server + * 1: client,2:server,3:client and server + * Returns : result true or false +*******************************************************************************/ + +bool espconn_secure_ca_disable(uint8 level); + + +/****************************************************************************** + * FunctionName : espconn_secure_cert_req_enable + * Description : enable the client certificate authenticate and set the flash sector + * as client or server + * Parameters : level -- set for client or server + * 1: client,2:server,3:client and server + * flash_sector -- flash sector for save certificate + * Returns : result true or false +*******************************************************************************/ + +bool espconn_secure_cert_req_enable(uint8 level, uint32 flash_sector ); + +/****************************************************************************** + * FunctionName : espconn_secure_ca_disable + * Description : disable the client certificate authenticate as client or server + * Parameters : level -- set for client or server + * 1: client,2:server,3:client and server + * Returns : result true or false +*******************************************************************************/ + +bool espconn_secure_cert_req_disable(uint8 level); + +/****************************************************************************** + * FunctionName : espconn_secure_set_default_certificate + * Description : Load the certificates in memory depending on compile-time + * and user options. + * Parameters : certificate -- Load the certificate + * length -- Load the certificate length + * Returns : result true or false +*******************************************************************************/ + +bool espconn_secure_set_default_certificate(const uint8* certificate, uint16 length); + +/****************************************************************************** + * FunctionName : espconn_secure_set_default_private_key + * Description : Load the key in memory depending on compile-time + * and user options. + * Parameters : private_key -- Load the key + * length -- Load the key length + * Returns : result true or false +*******************************************************************************/ + +bool espconn_secure_set_default_private_key(const uint8* private_key, uint16 length); + +/****************************************************************************** + * FunctionName : espconn_secure_accept + * Description : The function given as the listen + * Parameters : espconn -- the espconn used to listen the connection + * Returns : result +*******************************************************************************/ + +sint8 espconn_secure_accept(struct espconn *espconn); + +/****************************************************************************** + * FunctionName : espconn_secure_accepts + * Description : delete the secure server host + * Parameters : espconn -- the espconn used to listen the connection + * Returns : result +*******************************************************************************/ + +sint8 espconn_secure_delete(struct espconn *espconn); + +/****************************************************************************** + * FunctionName : espconn_igmp_join + * Description : join a multicast group + * Parameters : host_ip -- the ip address of udp server + * multicast_ip -- multicast ip given by user + * Returns : none +*******************************************************************************/ +sint8 espconn_igmp_join(ip_addr_t *host_ip, ip_addr_t *multicast_ip); + +/****************************************************************************** + * FunctionName : espconn_igmp_leave + * Description : leave a multicast group + * Parameters : host_ip -- the ip address of udp server + * multicast_ip -- multicast ip given by user + * Returns : none +*******************************************************************************/ +sint8 espconn_igmp_leave(ip_addr_t *host_ip, ip_addr_t *multicast_ip); + +/****************************************************************************** + * FunctionName : espconn_recv_hold + * Description : hold tcp receive + * Parameters : espconn -- espconn to hold + * Returns : none +*******************************************************************************/ +sint8 espconn_recv_hold(struct espconn *pespconn); + +/****************************************************************************** + * FunctionName : espconn_recv_unhold + * Description : unhold tcp receive + * Parameters : espconn -- espconn to unhold + * Returns : none +*******************************************************************************/ +sint8 espconn_recv_unhold(struct espconn *pespconn); + +/****************************************************************************** + * FunctionName : espconn_recved_len + * Description : get TCP readable data bytes + * Parameters : espconn -- espconn to unhold + * Returns : result +*******************************************************************************/ +sint16 espconn_recved_len(struct espconn *espconn); + +/****************************************************************************** + * FunctionName : espconn_mdns_init + * Description : register a device with mdns + * Parameters : ipAddr -- the ip address of device + * hostname -- the hostname of device + * Returns : none +*******************************************************************************/ + +void espconn_mdns_init(struct mdns_info *info); +/****************************************************************************** + * FunctionName : espconn_mdns_close + * Description : close a device with mdns + * Parameters : a + * Returns : none +*******************************************************************************/ + +void espconn_mdns_close(void); +/****************************************************************************** + * FunctionName : espconn_mdns_server_register + * Description : register a device with mdns + * Parameters : a + * Returns : none +*******************************************************************************/ +void espconn_mdns_server_register(void); + +/****************************************************************************** + * FunctionName : espconn_mdns_server_unregister + * Description : unregister a device with mdns + * Parameters : a + * Returns : none +*******************************************************************************/ +void espconn_mdns_server_unregister(void); + +/****************************************************************************** + * FunctionName : espconn_mdns_get_servername + * Description : get server name of device with mdns + * Parameters : a + * Returns : none +*******************************************************************************/ + +char* espconn_mdns_get_servername(void); +/****************************************************************************** + * FunctionName : espconn_mdns_set_servername + * Description : set server name of device with mdns + * Parameters : a + * Returns : none +*******************************************************************************/ +void espconn_mdns_set_servername(const char *name); + +/****************************************************************************** + * FunctionName : espconn_mdns_set_hostname + * Description : set host name of device with mdns + * Parameters : a + * Returns : none +*******************************************************************************/ +void espconn_mdns_set_hostname(char *name); + +/****************************************************************************** + * FunctionName : espconn_mdns_get_hostname + * Description : get host name of device with mdns + * Parameters : a + * Returns : none +*******************************************************************************/ +char* espconn_mdns_get_hostname(void); + +/****************************************************************************** + * FunctionName : espconn_mdns_disable + * Description : disable a device with mdns + * Parameters : a + * Returns : none +*******************************************************************************/ +void espconn_mdns_disable(void); + +/****************************************************************************** + * FunctionName : espconn_mdns_enable + * Description : disable a device with mdns + * Parameters : a + * Returns : none +*******************************************************************************/ +void espconn_mdns_enable(void); +/****************************************************************************** + * FunctionName : espconn_dns_setserver + * Description : Initialize one of the DNS servers. + * Parameters : numdns -- the index of the DNS server to set must + * be < DNS_MAX_SERVERS = 2 + * dnsserver -- IP address of the DNS server to set + * Returns : none +*******************************************************************************/ +void espconn_dns_setserver(uint8 numdns, ip_addr_t *dnsserver); +/****************************************************************************** + * FunctionName : espconn_dns_getserver + * Description : get dns server. + * Parameters : numdns -- the index of the DNS server, must + * be < DNS_MAX_SERVERS = 2 + * Returns : dnsserver -- IP address of the DNS server to set +*******************************************************************************/ +ip_addr_t espconn_dns_getserver(uint8 numdns); +#endif + diff --git a/Sming/Arch/Esp8266/Components/esp8266/include/espinc/eagle_soc.h b/Sming/Arch/Esp8266/Components/esp8266/include/espinc/eagle_soc.h index 844f2f21dd..fcb72fcc97 100644 --- a/Sming/Arch/Esp8266/Components/esp8266/include/espinc/eagle_soc.h +++ b/Sming/Arch/Esp8266/Components/esp8266/include/espinc/eagle_soc.h @@ -25,8 +25,7 @@ #ifndef _EAGLE_SOC_H_ #define _EAGLE_SOC_H_ -#include -#include +#include /* IO definitions (access restrictions to peripheral registers) */ @@ -69,8 +68,6 @@ #define BIT0 0x00000001 //}} -#define BIT(nr) (1UL << (nr)) - #define REG_WRITE(_r, _v) (*(volatile uint32_t *)(_r)) = (_v) #define REG_READ(_r) (*(volatile uint32_t *)(_r)) diff --git a/Sming/Arch/Esp8266/Components/esp8266/include/espinc/spi_register.h b/Sming/Arch/Esp8266/Components/esp8266/include/espinc/spi_register.h index 288b4d69f1..64b8429ccd 100644 --- a/Sming/Arch/Esp8266/Components/esp8266/include/espinc/spi_register.h +++ b/Sming/Arch/Esp8266/Components/esp8266/include/espinc/spi_register.h @@ -78,7 +78,7 @@ #define SPI_MOSI_DELAY_NUM 0x00000007 #define SPI_MOSI_DELAY_NUM_S 23 #define SPI_MOSI_DELAY_MODE 0x00000003 //mode 0 : posedge; data set at positive edge of clk - //mode 1 : negedge + 1 cycle delay, only if freq<10MHz ; data set at negitive edge of clk + //mode 1 : negedge + 1 cycle delay, only if freq<10MHz ; data set at negative edge of clk //mode 2 : Do not use this mode. #define SPI_MOSI_DELAY_MODE_S 21 #define SPI_MISO_DELAY_NUM 0x00000007 diff --git a/Sming/Arch/Esp8266/Components/esp8266/include/espinc/spi_struct.h b/Sming/Arch/Esp8266/Components/esp8266/include/espinc/spi_struct.h index 0fc0bc417d..27ee0e962f 100644 --- a/Sming/Arch/Esp8266/Components/esp8266/include/espinc/spi_struct.h +++ b/Sming/Arch/Esp8266/Components/esp8266/include/espinc/spi_struct.h @@ -104,7 +104,7 @@ typedef struct { uint32_t clkcnt_h: 6; /*In the master mode it must be floor((spi_clkcnt_n+1)/2-1). In the slave mode it must be 0.*/ uint32_t clkcnt_n: 6; /*In the master mode it is the divider of spi_clk. So spi_clk frequency is system/(spi_clkdiv_pre+1)/(spi_clkcnt_n+1)*/ uint32_t clkdiv_pre: 13; /*In the master mode it is pre-divider of spi_clk.*/ - uint32_t clk_equ_sysclk: 1; /*In the master mode 1: spi_clk is eqaul to system 0: spi_clk is divided from system clock.*/ + uint32_t clk_equ_sysclk: 1; /*In the master mode 1: spi_clk is equal to system 0: spi_clk is divided from system clock.*/ }; uint32_t val; } clock; diff --git a/Sming/Arch/Esp8266/Components/esp8266/include/espnow.h b/Sming/Arch/Esp8266/Components/esp8266/include/espnow.h new file mode 100644 index 0000000000..4a35f3d800 --- /dev/null +++ b/Sming/Arch/Esp8266/Components/esp8266/include/espnow.h @@ -0,0 +1,80 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2016 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, + * it is 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 + +#ifdef __cplusplus +extern "C" { +#endif + +enum esp_now_role { + ESP_NOW_ROLE_IDLE = 0, + ESP_NOW_ROLE_CONTROLLER, + ESP_NOW_ROLE_SLAVE, + ESP_NOW_ROLE_COMBO, + ESP_NOW_ROLE_MAX, +}; + +typedef void (*esp_now_recv_cb_t)(uint8_t* mac_addr, uint8_t* data, uint8_t len); +typedef void (*esp_now_send_cb_t)(uint8_t* mac_addr, uint8_t status); + +int esp_now_init(void); +int esp_now_deinit(void); + +int esp_now_register_send_cb(esp_now_send_cb_t cb); +int esp_now_unregister_send_cb(void); + +int esp_now_register_recv_cb(esp_now_recv_cb_t cb); +int esp_now_unregister_recv_cb(void); + +int esp_now_send(uint8_t* da, uint8_t* data, int len); + +int esp_now_add_peer(uint8_t* mac_addr, uint8_t role, uint8_t channel, uint8_t* key, uint8_t key_len); +int esp_now_del_peer(uint8_t* mac_addr); + +int esp_now_set_self_role(uint8_t role); +int esp_now_get_self_role(void); + +int esp_now_set_peer_role(uint8_t* mac_addr, uint8_t role); +int esp_now_get_peer_role(uint8_t* mac_addr); + +int esp_now_set_peer_channel(uint8_t* mac_addr, uint8_t channel); +int esp_now_get_peer_channel(uint8_t* mac_addr); + +int esp_now_set_peer_key(uint8_t* mac_addr, uint8_t* key, uint8_t key_len); +int esp_now_get_peer_key(uint8_t* mac_addr, uint8_t* key, uint8_t* key_len); + +uint8_t* esp_now_fetch_peer(bool restart); + +int esp_now_is_peer_exist(uint8_t* mac_addr); + +int esp_now_get_cnt_info(uint8_t* all_cnt, uint8_t* encrypt_cnt); + +int esp_now_set_kok(uint8_t* key, uint8_t len); + +#ifdef __cplusplus +} +#endif diff --git a/Sming/Arch/Esp8266/Components/esp8266/include/ets_sys.h b/Sming/Arch/Esp8266/Components/esp8266/include/ets_sys.h new file mode 100644 index 0000000000..4d9eb1109c --- /dev/null +++ b/Sming/Arch/Esp8266/Components/esp8266/include/ets_sys.h @@ -0,0 +1,129 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2016 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, + * it is 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 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint32_t ETSSignal; +typedef uint32_t ETSParam; + +typedef struct ETSEventTag ETSEvent; + +struct ETSEventTag { + ETSSignal sig; + ETSParam par; +}; + +typedef void (*ETSTask)(ETSEvent* e); + +/* timer related */ +typedef uint32_t ETSHandle; +typedef void ETSTimerFunc(void* timer_arg); + +typedef struct _ETSTIMER_ { + struct _ETSTIMER_* timer_next; + uint32_t timer_expire; + uint32_t timer_period; + ETSTimerFunc* timer_func; + void* timer_arg; +} ETSTimer; + +/* Watchdog */ +void ets_wdt_enable(void); +void ets_wdt_disable(void); +void wdt_feed(void); + +/* interrupt related */ +#define ETS_SDIO_INUM 1 +#define ETS_SLC_INUM 1 +#define ETS_SPI_INUM 2 +#define ETS_GPIO_INUM 4 +#define ETS_UART_INUM 5 +#define ETS_UART1_INUM 5 +#define ETS_FRC_TIMER1_INUM 9 /* use edge*/ + +typedef void (*ets_isr_t)(void*); + +void ets_intr_lock(void); +void ets_intr_unlock(void); +void ets_isr_attach(int i, ets_isr_t func, void* arg); +void ets_isr_mask(uint32 mask); +void ets_isr_unmask(uint32 unmask); + +void NmiTimSetFunc(void (*func)(void)); + +#define ETS_INTR_LOCK() ets_intr_lock() + +#define ETS_INTR_UNLOCK() ets_intr_unlock() + +#define ETS_FRC_TIMER1_INTR_ATTACH(func, arg) ets_isr_attach(ETS_FRC_TIMER1_INUM, (func), (void*)(arg)) + +#define ETS_FRC_TIMER1_NMI_INTR_ATTACH(func) NmiTimSetFunc(func) + +#define ETS_SDIO_INTR_ATTACH(func, arg) ets_isr_attach(ETS_SDIO_INUM, (func), (void*)(arg)) + +#define ETS_SLC_INTR_ATTACH(func, arg) ets_isr_attach(ETS_SLC_INUM, (func), (void*)(arg)) + +#define ETS_GPIO_INTR_ATTACH(func, arg) ets_isr_attach(ETS_GPIO_INUM, (func), (void*)(arg)) + +#define ETS_UART_INTR_ATTACH(func, arg) ets_isr_attach(ETS_UART_INUM, (func), (void*)(arg)) + +#define ETS_SPI_INTR_ATTACH(func, arg) ets_isr_attach(ETS_SPI_INUM, (func), (void*)(arg)) + +#define ETS_INTR_ENABLE(inum) ets_isr_unmask((1 << inum)) + +#define ETS_INTR_DISABLE(inum) ets_isr_mask((1 << inum)) + +#define ETS_UART_INTR_ENABLE() ETS_INTR_ENABLE(ETS_UART_INUM) + +#define ETS_UART_INTR_DISABLE() ETS_INTR_DISABLE(ETS_UART_INUM) + +#define ETS_FRC1_INTR_ENABLE() ETS_INTR_ENABLE(ETS_FRC_TIMER1_INUM) + +#define ETS_FRC1_INTR_DISABLE() ETS_INTR_DISABLE(ETS_FRC_TIMER1_INUM) + +#define ETS_GPIO_INTR_ENABLE() ETS_INTR_ENABLE(ETS_GPIO_INUM) + +#define ETS_GPIO_INTR_DISABLE() ETS_INTR_DISABLE(ETS_GPIO_INUM) + +#define ETS_SLC_INTR_ENABLE() ETS_INTR_ENABLE(ETS_SLC_INUM) + +#define ETS_SLC_INTR_DISABLE() ETS_INTR_DISABLE(ETS_SLC_INUM) + +#define ETS_SPI_INTR_ENABLE() ETS_INTR_ENABLE(ETS_SPI_INUM) + +#define ETS_SPI_INTR_DISABLE() ETS_INTR_DISABLE(ETS_SPI_INUM) + +#define ETS_SDIO_INTR_ENABLE() ETS_INTR_ENABLE(ETS_SDIO_INUM) + +#define ETS_SDIO_INTR_DISABLE() ETS_INTR_DISABLE(ETS_SDIO_INUM) + +#ifdef __cplusplus +} +#endif diff --git a/Sming/Arch/Esp8266/Components/esp8266/include/gpio.h b/Sming/Arch/Esp8266/Components/esp8266/include/gpio.h new file mode 100644 index 0000000000..2eb11add5d --- /dev/null +++ b/Sming/Arch/Esp8266/Components/esp8266/include/gpio.h @@ -0,0 +1,121 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2016 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, + * it is 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 + +#ifdef __cplusplus +extern "C" { +#endif + +#define GPIO_PIN_ADDR(i) (GPIO_PIN0_ADDRESS + i * 4) + +#define GPIO_ID_IS_PIN_REGISTER(reg_id) ((reg_id >= GPIO_ID_PIN0) && (reg_id <= GPIO_ID_PIN(GPIO_PIN_COUNT - 1))) + +#define GPIO_REGID_TO_PINIDX(reg_id) ((reg_id)-GPIO_ID_PIN0) + +typedef enum { + GPIO_PIN_INTR_DISABLE = 0, + GPIO_PIN_INTR_POSEDGE = 1, + GPIO_PIN_INTR_NEGEDGE = 2, + GPIO_PIN_INTR_ANYEDGE = 3, + GPIO_PIN_INTR_LOLEVEL = 4, + GPIO_PIN_INTR_HILEVEL = 5 +} GPIO_INT_TYPE; + +#define GPIO_OUTPUT_SET(gpio_no, bit_value) \ + gpio_output_set((bit_value) << gpio_no, ((~(bit_value)) & 0x01) << gpio_no, 1 << gpio_no, 0) +#define GPIO_DIS_OUTPUT(gpio_no) gpio_output_set(0, 0, 0, 1 << gpio_no) +#define GPIO_INPUT_GET(gpio_no) ((gpio_input_get() >> gpio_no) & BIT0) + +/* GPIO interrupt handler, registered through gpio_intr_handler_register */ +typedef void (*gpio_intr_handler_fn_t)(uint32_t intr_mask, void* arg); + +/* + * Initialize GPIO. This includes reading the GPIO Configuration DataSet + * to initialize "output enables" and pin configurations for each gpio pin. + * Must be called once during startup. + */ +void gpio_init(void); + +/* + * Change GPIO pin output by setting, clearing, or disabling pins. + * In general, it is expected that a bit will be set in at most one + * of these masks. If a bit is clear in all masks, the output state + * remains unchanged. + * + * There is no particular ordering guaranteed; so if the order of + * writes is significant, calling code should divide a single call + * into multiple calls. + */ +void gpio_output_set(uint32_t set_mask, uint32_t clear_mask, uint32_t enable_mask, uint32_t disable_mask); + +/* + * Sample the value of GPIO input pins and returns a bitmask. + */ +uint32_t gpio_input_get(void); + +/* + * Set the specified GPIO register to the specified value. + * This is a very general and powerful interface that is not + * expected to be used during normal operation. It is intended + * mainly for debug, or for unusual requirements. + */ +void gpio_register_set(uint32_t reg_id, uint32_t value); + +/* Get the current value of the specified GPIO register. */ +uint32_t gpio_register_get(uint32_t reg_id); + +/* + * Register an application-specific interrupt handler for GPIO pin + * interrupts. Once the interrupt handler is called, it will not + * be called again until after a call to gpio_intr_ack. Any GPIO + * interrupts that occur during the interim are masked. + * + * The application-specific handler is called with a mask of + * pending GPIO interrupts. After processing pin interrupts, the + * application-specific handler may wish to use gpio_intr_pending + * to check for any additional pending interrupts before it returns. + */ +void gpio_intr_handler_register(gpio_intr_handler_fn_t fn, void* arg); + +/* Determine which GPIO interrupts are pending. */ +uint32_t gpio_intr_pending(void); + +/* + * Acknowledge GPIO interrupts. + * Intended to be called from the gpio_intr_handler_fn. + */ +void gpio_intr_ack(uint32_t ack_mask); + +void gpio_pin_wakeup_enable(uint32_t i, GPIO_INT_TYPE intr_state); + +void gpio_pin_wakeup_disable(); + +void gpio_pin_intr_state_set(uint32_t i, GPIO_INT_TYPE intr_state); + +#ifdef __cplusplus +} +#endif diff --git a/Sming/Arch/Esp8266/Components/esp8266/include/mem.h b/Sming/Arch/Esp8266/Components/esp8266/include/mem.h deleted file mode 100644 index 3fc4826695..0000000000 --- a/Sming/Arch/Esp8266/Components/esp8266/include/mem.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef SDK_INTERNAL - -// Missing from early SDK versions -extern void *pvPortMalloc(size_t xWantedSize, const char *file, uint32 line); -extern void *pvPortZalloc(size_t xWantedSize, const char *file, uint32 line); -extern void pvPortFree(void *ptr); -extern void vPortFree(void *ptr, const char *file, uint32 line); -extern void *vPortMalloc(size_t xWantedSize); - -#endif - -#include_next - -#ifdef __cplusplus -} -#endif - diff --git a/Sming/Arch/Esp8266/Components/esp8266/include/os_type.h b/Sming/Arch/Esp8266/Components/esp8266/include/os_type.h new file mode 100644 index 0000000000..8fbed594e5 --- /dev/null +++ b/Sming/Arch/Esp8266/Components/esp8266/include/os_type.h @@ -0,0 +1,43 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2016 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, + * it is 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 +#include "ets_sys.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define os_signal_t ETSSignal +#define os_param_t ETSParam +#define os_event_t ETSEvent +#define os_task_t ETSTask +#define os_timer_t ETSTimer +#define os_timer_func_t ETSTimerFunc + +#ifdef __cplusplus +} +#endif diff --git a/Sming/Arch/Esp8266/Components/esp8266/include/osapi.h b/Sming/Arch/Esp8266/Components/esp8266/include/osapi.h new file mode 100644 index 0000000000..17e9b018b8 --- /dev/null +++ b/Sming/Arch/Esp8266/Components/esp8266/include/osapi.h @@ -0,0 +1,109 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2016 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, + * it is 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 +#include +#include "os_type.h" +#include "ets_sys.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void ets_bzero(void* s, size_t n); +void ets_delay_us(uint32_t us); +void ets_install_putc1(void (*p)(char c)); + +#define os_bzero ets_bzero +#define os_delay_us ets_delay_us +#define os_install_putc1 ets_install_putc1 + +int ets_memcmp(const void* str1, const void* str2, unsigned int nbyte); +void* ets_memcpy(void* dest, const void* src, unsigned int nbyte); +void* ets_memmove(void* dest, const void* src, unsigned int nbyte); +void* ets_memset(void* dest, int val, unsigned int nbyte); + +int ets_strcmp(const char* s1, const char* s2); +char* ets_strcpy(char* s1, const char* s2); +int ets_strlen(const char* s); +int ets_strncmp(const char* s1, const char* s2, unsigned int n); +char* ets_strncpy(char* s1, const char* s2, unsigned int n); +char* ets_strstr(const char* s1, const char* s2); + +#define os_memcmp ets_memcmp +#define os_memcpy ets_memcpy +#define os_memmove ets_memmove +#define os_memset ets_memset +#define os_strcat strcat +#define os_strchr strchr +#define os_strcmp ets_strcmp +#define os_strcpy ets_strcpy +#define os_strlen ets_strlen +#define os_strncmp ets_strncmp +#define os_strncpy ets_strncpy +#define os_strstr ets_strstr + +void ets_timer_arm_new(os_timer_t* ptimer, uint32_t time, bool repeat_flag, bool ms_flag); +void ets_timer_disarm(os_timer_t* ptimer); +void ets_timer_setfn(os_timer_t* ptimer, os_timer_func_t* pfunction, void* parg); + +#ifdef USE_US_TIMER +#define os_timer_arm_us(a, b, c) ets_timer_arm_new(a, b, c, 0) +#endif +#define os_timer_arm(a, b, c) ets_timer_arm_new(a, b, c, 1) +#define os_timer_disarm ets_timer_disarm +#define os_timer_setfn ets_timer_setfn + +int ets_vprintf (int (*print_function)(int), const char * format, va_list arg) __attribute__ ((format (printf, 2, 0))); +int ets_sprintf(char* str, const char* format, ...) __attribute__((format(printf, 2, 3))); +int os_printf_plus(const char* format, ...) __attribute__((format(printf, 1, 2))); +int ets_snprintf(char* str, unsigned int size, const char* format, ...) __attribute__((format(printf, 3, 4))); +int ets_putc(int); +int ets_write_char(int ch); + +#define os_sprintf_plus ets_sprintf +#define os_sprintf(buf, fmt, ...) os_sprintf_plus(buf, fmt, ##__VA_ARGS__) + +#define os_snprintf_plus ets_snprintf +#define os_snprintf(buf, size, fmt, ...) os_snprintf_plus(buf, size, fmt, ##__VA_ARGS__) + +#ifdef USE_OPTIMIZE_PRINTF +#define os_printf(fmt, ...) \ + do { \ + static const char flash_str[] ICACHE_RODATA_ATTR STORE_ATTR = fmt; \ + os_printf_plus(flash_str, ##__VA_ARGS__); \ + } while(0) +#else +#define os_printf os_printf_plus +#endif + +unsigned long os_random(void); +int os_get_random(unsigned char* buf, size_t len); + +#ifdef __cplusplus +} +#endif diff --git a/Sming/Arch/Esp8266/Components/esp8266/include/pwm.h b/Sming/Arch/Esp8266/Components/esp8266/include/pwm.h new file mode 100644 index 0000000000..c9c3a6f211 --- /dev/null +++ b/Sming/Arch/Esp8266/Components/esp8266/include/pwm.h @@ -0,0 +1,60 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2016 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, + * it is 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 + +#ifdef __cplusplus +extern "C" { +#endif + +/*pwm.h: function and macro definition of PWM API , driver level */ +/*user_light.h: user interface for light API, user level*/ +/*user_light_adj: API for color changing and lighting effects, user level*/ + +/*SUPPORT UP TO 8 PWM CHANNEL*/ +#define PWM_CHANNEL_NUM_MAX 8 + +struct pwm_param { + uint32_t period; + uint32_t freq; + uint32_t duty[PWM_CHANNEL_NUM_MAX]; //PWM_CHANNEL<=8 +}; + +/* pwm_init should be called only once, for now */ +void pwm_init(uint32_t period, uint32_t* duty, uint32_t pwm_channel_num, uint32_t (*pin_info_list)[3]); +void pwm_start(void); + +void pwm_set_duty(uint32_t duty, uint8_t channel); +uint32_t pwm_get_duty(uint8_t channel); +void pwm_set_period(uint32_t period); +uint32_t pwm_get_period(void); + +uint32_t get_pwm_version(void); +void set_pwm_debug_en(uint8_t print_en); + +#ifdef __cplusplus +} +#endif diff --git a/Sming/Arch/Esp8266/Components/esp8266/include/sdk/mem.h b/Sming/Arch/Esp8266/Components/esp8266/include/sdk/mem.h new file mode 100644 index 0000000000..df1950df4a --- /dev/null +++ b/Sming/Arch/Esp8266/Components/esp8266/include/sdk/mem.h @@ -0,0 +1,26 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void* pvPortMalloc(size_t xWantedSize, const char* file, uint32 line); +void* pvPortCalloc(size_t count, size_t size, const char*, unsigned); +void* pvPortZalloc(size_t xWantedSize, const char* file, uint32 line); +void vPortFree(void* ptr, const char* file, uint32 line); +void* vPortMalloc(size_t xWantedSize); +void pvPortFree(void* ptr); + +#ifndef os_malloc +#define os_malloc(s) pvPortMalloc(s, "", __LINE__) +#define os_calloc(l, s) pvPortCalloc(l, s, "", __LINE__) +#define os_realloc(p, s) pvPortRealloc(p, s, "", __LINE__) +#define os_zalloc(s) pvPortZalloc(s, "", __LINE__) +#define os_free(s) vPortFree(s, "", __LINE__) +#endif + +#ifdef __cplusplus +} +#endif diff --git a/Sming/Arch/Esp8266/Components/esp8266/include/simple_pair.h b/Sming/Arch/Esp8266/Components/esp8266/include/simple_pair.h new file mode 100644 index 0000000000..5b2976b8cb --- /dev/null +++ b/Sming/Arch/Esp8266/Components/esp8266/include/simple_pair.h @@ -0,0 +1,69 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2016 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, + * it is 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 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + SP_ST_STA_FINISH = 0, + SP_ST_AP_FINISH = 0, + SP_ST_AP_RECV_NEG, + SP_ST_STA_AP_REFUSE_NEG, + /* all following is err */ + SP_ST_WAIT_TIMEOUT, + SP_ST_SEND_ERROR, + SP_ST_KEY_INSTALL_ERR, + SP_ST_KEY_OVERLAP_ERR, //means the same macaddr has two different keys + SP_ST_OP_ERROR, + SP_ST_UNKNOWN_ERROR, + SP_ST_MAX, +} SP_ST_t; + +typedef void (*simple_pair_status_cb_t)(uint8_t* sa, uint8_t status); + +int register_simple_pair_status_cb(simple_pair_status_cb_t cb); +void unregister_simple_pair_status_cb(void); + +int simple_pair_init(void); +void simple_pair_deinit(void); + +int simple_pair_state_reset(void); +int simple_pair_ap_enter_announce_mode(void); +int simple_pair_sta_enter_scan_mode(void); + +int simple_pair_sta_start_negotiate(void); +int simple_pair_ap_start_negotiate(void); +int simple_pair_ap_refuse_negotiate(void); + +int simple_pair_set_peer_ref(uint8_t* peer_mac, uint8_t* tmp_key, uint8_t* ex_key); +int simple_pair_get_peer_ref(uint8_t* peer_mac, uint8_t* tmp_key, uint8_t* ex_key); + +#ifdef __cplusplus +} +#endif diff --git a/Sming/Arch/Esp8266/Components/esp8266/include/smartconfig.h b/Sming/Arch/Esp8266/Components/esp8266/include/smartconfig.h new file mode 100644 index 0000000000..d4f647f110 --- /dev/null +++ b/Sming/Arch/Esp8266/Components/esp8266/include/smartconfig.h @@ -0,0 +1,57 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2016 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, + * it is 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 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + SC_STATUS_WAIT = 0, + SC_STATUS_FIND_CHANNEL, + SC_STATUS_GETTING_SSID_PSWD, + SC_STATUS_LINK, + SC_STATUS_LINK_OVER, +} sc_status; + +typedef enum { + SC_TYPE_ESPTOUCH = 0, + SC_TYPE_AIRKISS, + SC_TYPE_ESPTOUCH_AIRKISS, +} sc_type; + +typedef void (*sc_callback_t)(sc_status status, void* pdata); + +const char* smartconfig_get_version(void); +bool smartconfig_start(sc_callback_t cb, ...); +bool smartconfig_stop(void); +bool esptouch_set_timeout(uint8_t time_s); //15s~255s, offset:45s +bool smartconfig_set_type(sc_type type); + +#ifdef __cplusplus +} +#endif diff --git a/Sming/Arch/Esp8266/Components/esp8266/include/spi_flash.h b/Sming/Arch/Esp8266/Components/esp8266/include/spi_flash.h new file mode 100644 index 0000000000..6933cd98b3 --- /dev/null +++ b/Sming/Arch/Esp8266/Components/esp8266/include/spi_flash.h @@ -0,0 +1,65 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2016 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, + * it is 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 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + SPI_FLASH_RESULT_OK, + SPI_FLASH_RESULT_ERR, + SPI_FLASH_RESULT_TIMEOUT, +} SpiFlashOpResult; + +typedef struct { + uint32_t deviceId; + uint32_t chip_size; // chip size in byte + uint32_t block_size; + uint32_t sector_size; + uint32_t page_size; + uint32_t status_mask; +} SpiFlashChip; + +#define SPI_FLASH_SEC_SIZE 4096 + +uint32_t spi_flash_get_id(void); +SpiFlashOpResult spi_flash_erase_sector(uint16_t sec); +SpiFlashOpResult spi_flash_write(uint32_t des_addr, uint32_t* src_addr, uint32_t size); +SpiFlashOpResult spi_flash_read(uint32_t src_addr, uint32_t* des_addr, uint32_t size); + +typedef SpiFlashOpResult (*user_spi_flash_read)(SpiFlashChip* spi, uint32_t src_addr, uint32_t* des_addr, + uint32_t size); + +void spi_flash_set_read_func(user_spi_flash_read read); + +bool spi_flash_erase_protect_enable(void); +bool spi_flash_erase_protect_disable(void); + +#ifdef __cplusplus +} +#endif diff --git a/Sming/Arch/Esp8266/Components/esp8266/include/user_interface.h b/Sming/Arch/Esp8266/Components/esp8266/include/user_interface.h new file mode 100644 index 0000000000..29eb2ca854 --- /dev/null +++ b/Sming/Arch/Esp8266/Components/esp8266/include/user_interface.h @@ -0,0 +1,4 @@ +#pragma once + +#include "esp_system.h" +#include "esp_wifi.h" diff --git a/Sming/Arch/Esp8266/Components/esp8266/include/wpa2_enterprise.h b/Sming/Arch/Esp8266/Components/esp8266/include/wpa2_enterprise.h new file mode 100644 index 0000000000..86cfb5bcea --- /dev/null +++ b/Sming/Arch/Esp8266/Components/esp8266/include/wpa2_enterprise.h @@ -0,0 +1,68 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2016 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, + * it is 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 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef long os_time_t; + +struct os_time { + os_time_t sec; + os_time_t usec; +}; + +typedef int (*get_time_func_t)(struct os_time* t); + +int wifi_station_set_wpa2_enterprise_auth(int enable); + +int wifi_station_set_enterprise_cert_key(uint8_t* client_cert, int client_cert_len, uint8_t* private_key, + int private_key_len, uint8_t* private_key_passwd, int private_key_passwd_len); +void wifi_station_clear_enterprise_cert_key(void); + +int wifi_station_set_enterprise_ca_cert(uint8_t* ca_cert, int ca_cert_len); +void wifi_station_clear_enterprise_ca_cert(void); + +int wifi_station_set_enterprise_identity(uint8_t* identity, int len); +void wifi_station_clear_enterprise_identity(void); + +int wifi_station_set_enterprise_username(uint8_t* username, int len); +void wifi_station_clear_enterprise_username(void); + +int wifi_station_set_enterprise_password(uint8_t* password, int len); +void wifi_station_clear_enterprise_password(void); + +int wifi_station_set_enterprise_new_password(uint8_t* new_password, int len); +void wifi_station_clear_enterprise_new_password(void); + +void wifi_station_set_enterprise_disable_time_check(bool disable); +bool wifi_station_get_enterprise_disable_time_check(void); + +void wpa2_enterprise_set_user_get_time(get_time_func_t cb); + +#ifdef __cplusplus +} +#endif diff --git a/Sming/Arch/Esp8266/Components/esp8266/ld/eagle.rom.addr.v6.ld b/Sming/Arch/Esp8266/Components/esp8266/ld/eagle.rom.addr.v6.ld new file mode 100644 index 0000000000..2628776040 --- /dev/null +++ b/Sming/Arch/Esp8266/Components/esp8266/ld/eagle.rom.addr.v6.ld @@ -0,0 +1,350 @@ +PROVIDE ( Cache_Read_Disable = 0x400047f0 ); +PROVIDE ( Cache_Read_Enable = 0x40004678 ); +PROVIDE ( FilePacketSendReqMsgProc = 0x400035a0 ); +PROVIDE ( FlashDwnLdParamCfgMsgProc = 0x4000368c ); +PROVIDE ( FlashDwnLdStartMsgProc = 0x40003538 ); +PROVIDE ( FlashDwnLdStopReqMsgProc = 0x40003658 ); +PROVIDE ( GetUartDevice = 0x40003f4c ); +PROVIDE ( MD5Final = 0x40009900 ); +PROVIDE ( MD5Init = 0x40009818 ); +PROVIDE ( MD5Update = 0x40009834 ); +PROVIDE ( MemDwnLdStartMsgProc = 0x400036c4 ); +PROVIDE ( MemDwnLdStopReqMsgProc = 0x4000377c ); +PROVIDE ( MemPacketSendReqMsgProc = 0x400036f0 ); +PROVIDE ( RcvMsg = 0x40003eac ); +PROVIDE ( SHA1Final = 0x4000b648 ); +PROVIDE ( SHA1Init = 0x4000b584 ); +PROVIDE ( SHA1Transform = 0x4000a364 ); +PROVIDE ( SHA1Update = 0x4000b5a8 ); +PROVIDE ( SPI_read_status = 0x400043c8 ); +PROVIDE ( SPI_write_status = 0x40004400 ); +PROVIDE ( SPI_write_enable = 0x4000443c ); +PROVIDE ( Wait_SPI_Idle = 0x4000448c ); +PROVIDE ( Enable_QMode = 0x400044c0 ); +PROVIDE ( SPIEraseArea = 0x40004b44 ); +PROVIDE ( SPIEraseBlock = 0x400049b4 ); +PROVIDE ( SPIEraseChip = 0x40004984 ); +PROVIDE ( SPIEraseSector = 0x40004a00 ); +PROVIDE ( SPILock = 0x400048a8 ); +PROVIDE ( SPIParamCfg = 0x40004c2c ); +PROVIDE ( SPIRead = 0x40004b1c ); +PROVIDE ( SPIReadModeCnfig = 0x400048ec ); +PROVIDE ( SPIUnlock = 0x40004878 ); +PROVIDE ( SPIWrite = 0x40004a4c ); +PROVIDE ( SelectSpiFunction = 0x40003f58 ); +PROVIDE ( SendMsg = 0x40003cf4 ); +PROVIDE ( UartConnCheck = 0x40003230 ); +PROVIDE ( UartConnectProc = 0x400037a0 ); +PROVIDE ( UartDwnLdProc = 0x40003368 ); +PROVIDE ( UartGetCmdLn = 0x40003ef4 ); +PROVIDE ( UartRegReadProc = 0x4000381c ); +PROVIDE ( UartRegWriteProc = 0x400037ac ); +PROVIDE ( UartRxString = 0x40003c30 ); +PROVIDE ( Uart_Init = 0x40003a14 ); +PROVIDE ( _DebugExceptionVector = 0x40000010 ); +PROVIDE ( _DoubleExceptionVector = 0x40000070 ); +PROVIDE ( _KernelExceptionVector = 0x40000030 ); +PROVIDE ( _NMIExceptionVector = 0x40000020 ); +PROVIDE ( _ResetHandler = 0x400000a4 ); +PROVIDE ( _ResetVector = 0x40000080 ); +PROVIDE ( _UserExceptionVector = 0x40000050 ); +PROVIDE ( __adddf3 = 0x4000c538 ); +PROVIDE ( __addsf3 = 0x4000c180 ); +PROVIDE ( __divdf3 = 0x4000cb94 ); +PROVIDE ( __divdi3 = 0x4000ce60 ); +PROVIDE ( __divsi3 = 0x4000dc88 ); +PROVIDE ( __extendsfdf2 = 0x4000cdfc ); +PROVIDE ( __fixdfsi = 0x4000ccb8 ); +PROVIDE ( __fixunsdfsi = 0x4000cd00 ); +PROVIDE ( __fixunssfsi = 0x4000c4c4 ); +PROVIDE ( __floatsidf = 0x4000e2f0 ); +PROVIDE ( __floatsisf = 0x4000e2ac ); +PROVIDE ( __floatunsidf = 0x4000e2e8 ); +PROVIDE ( __floatunsisf = 0x4000e2a4 ); +PROVIDE ( __muldf3 = 0x4000c8f0 ); +PROVIDE ( __muldi3 = 0x40000650 ); +PROVIDE ( __mulsf3 = 0x4000c3dc ); +PROVIDE ( __subdf3 = 0x4000c688 ); +PROVIDE ( __subsf3 = 0x4000c268 ); +PROVIDE ( __truncdfsf2 = 0x4000cd5c ); +PROVIDE ( __udivdi3 = 0x4000d310 ); +PROVIDE ( __udivsi3 = 0x4000e21c ); +PROVIDE ( __umoddi3 = 0x4000d770 ); +PROVIDE ( __umodsi3 = 0x4000e268 ); +PROVIDE ( __umulsidi3 = 0x4000dcf0 ); +PROVIDE ( _rom_store = 0x4000e388 ); +PROVIDE ( _rom_store_table = 0x4000e328 ); +PROVIDE ( _start = 0x4000042c ); +PROVIDE ( _xtos_alloca_handler = 0x4000dbe0 ); +PROVIDE ( _xtos_c_wrapper_handler = 0x40000598 ); +PROVIDE ( _xtos_cause3_handler = 0x40000590 ); +PROVIDE ( _xtos_ints_off = 0x4000bda4 ); +PROVIDE ( _xtos_ints_on = 0x4000bd84 ); +PROVIDE ( _xtos_l1int_handler = 0x4000048c ); +PROVIDE ( _xtos_p_none = 0x4000dbf8 ); +PROVIDE ( _xtos_restore_intlevel = 0x4000056c ); +PROVIDE ( _xtos_return_from_exc = 0x4000dc54 ); +PROVIDE ( _xtos_set_exception_handler = 0x40000454 ); +PROVIDE ( _xtos_set_interrupt_handler = 0x4000bd70 ); +PROVIDE ( _xtos_set_interrupt_handler_arg = 0x4000bd28 ); +PROVIDE ( _xtos_set_intlevel = 0x4000dbfc ); +PROVIDE ( _xtos_set_min_intlevel = 0x4000dc18 ); +PROVIDE ( _xtos_set_vpri = 0x40000574 ); +PROVIDE ( _xtos_syscall_handler = 0x4000dbe4 ); +PROVIDE ( _xtos_unhandled_exception = 0x4000dc44 ); +PROVIDE ( _xtos_unhandled_interrupt = 0x4000dc3c ); +PROVIDE ( aes_decrypt = 0x400092d4 ); +PROVIDE ( aes_decrypt_deinit = 0x400092e4 ); +PROVIDE ( aes_decrypt_init = 0x40008ea4 ); +PROVIDE ( aes_unwrap = 0x40009410 ); +PROVIDE ( base64_decode = 0x40009648 ); +PROVIDE ( base64_encode = 0x400094fc ); +PROVIDE ( bzero = 0x4000de84 ); +PROVIDE ( cmd_parse = 0x40000814 ); +PROVIDE ( conv_str_decimal = 0x40000b24 ); +PROVIDE ( conv_str_hex = 0x40000cb8 ); +PROVIDE ( convert_para_str = 0x40000a60 ); +PROVIDE ( dtm_get_intr_mask = 0x400026d0 ); +PROVIDE ( dtm_params_init = 0x4000269c ); +PROVIDE ( dtm_set_intr_mask = 0x400026c8 ); +PROVIDE ( dtm_set_params = 0x400026dc ); +PROVIDE ( eprintf = 0x40001d14 ); +PROVIDE ( eprintf_init_buf = 0x40001cb8 ); +PROVIDE ( eprintf_to_host = 0x40001d48 ); +PROVIDE ( est_get_printf_buf_remain_len = 0x40002494 ); +PROVIDE ( est_reset_printf_buf_len = 0x4000249c ); +PROVIDE ( ets_bzero = 0x40002ae8 ); +PROVIDE ( ets_char2xdigit = 0x40002b74 ); +PROVIDE ( ets_delay_us = 0x40002ecc ); +PROVIDE ( ets_enter_sleep = 0x400027b8 ); +PROVIDE ( ets_external_printf = 0x40002578 ); +PROVIDE ( ets_get_cpu_frequency = 0x40002f0c ); +PROVIDE ( ets_getc = 0x40002bcc ); +PROVIDE ( ets_install_external_printf = 0x40002450 ); +PROVIDE ( ets_install_putc1 = 0x4000242c ); +PROVIDE ( ets_install_putc2 = 0x4000248c ); +PROVIDE ( ets_install_uart_printf = 0x40002438 ); +PROVIDE ( ets_intr_lock = 0x40000f74 ); +PROVIDE ( ets_intr_unlock = 0x40000f80 ); +PROVIDE ( ets_isr_attach = 0x40000f88 ); +PROVIDE ( ets_isr_mask = 0x40000f98 ); +PROVIDE ( ets_isr_unmask = 0x40000fa8 ); +PROVIDE ( ets_memcmp = 0x400018d4 ); +PROVIDE ( ets_memcpy = 0x400018b4 ); +PROVIDE ( ets_memmove = 0x400018c4 ); +PROVIDE ( ets_memset = 0x400018a4 ); +PROVIDE ( ets_post = 0x40000e24 ); +PROVIDE ( ets_printf = 0x400024cc ); +PROVIDE ( ets_putc = 0x40002be8 ); +PROVIDE ( ets_rtc_int_register = 0x40002a40 ); +PROVIDE ( ets_run = 0x40000e04 ); +PROVIDE ( ets_set_idle_cb = 0x40000dc0 ); +PROVIDE ( ets_set_user_start = 0x40000fbc ); +PROVIDE ( ets_str2macaddr = 0x40002af8 ); +PROVIDE ( ets_strcmp = 0x40002aa8 ); +PROVIDE ( ets_strcpy = 0x40002a88 ); +PROVIDE ( ets_strlen = 0x40002ac8 ); +PROVIDE ( ets_strncmp = 0x40002ab8 ); +PROVIDE ( ets_strncpy = 0x40002a98 ); +PROVIDE ( ets_strstr = 0x40002ad8 ); +PROVIDE ( ets_task = 0x40000dd0 ); +PROVIDE ( ets_timer_arm = 0x40002cc4 ); +PROVIDE ( ets_timer_disarm = 0x40002d40 ); +PROVIDE ( ets_timer_done = 0x40002d80 ); +PROVIDE ( ets_timer_handler_isr = 0x40002da8 ); +PROVIDE ( ets_timer_init = 0x40002e68 ); +PROVIDE ( ets_timer_setfn = 0x40002c48 ); +PROVIDE ( ets_uart_printf = 0x40002544 ); +PROVIDE ( ets_update_cpu_frequency = 0x40002f04 ); +PROVIDE ( ets_vprintf = 0x40001f00 ); +PROVIDE ( ets_wdt_disable = 0x400030f0 ); +PROVIDE ( ets_wdt_enable = 0x40002fa0 ); +PROVIDE ( ets_wdt_get_mode = 0x40002f34 ); +PROVIDE ( ets_wdt_init = 0x40003170 ); +PROVIDE ( ets_wdt_restore = 0x40003158 ); +PROVIDE ( ets_write_char = 0x40001da0 ); +PROVIDE ( get_first_seg = 0x4000091c ); +PROVIDE ( gpio_init = 0x40004c50 ); +PROVIDE ( gpio_input_get = 0x40004cf0 ); +PROVIDE ( gpio_intr_ack = 0x40004dcc ); +PROVIDE ( gpio_intr_handler_register = 0x40004e28 ); +PROVIDE ( gpio_intr_pending = 0x40004d88 ); +PROVIDE ( gpio_intr_test = 0x40004efc ); +PROVIDE ( gpio_output_set = 0x40004cd0 ); +PROVIDE ( gpio_pin_intr_state_set = 0x40004d90 ); +PROVIDE ( gpio_pin_wakeup_disable = 0x40004ed4 ); +PROVIDE ( gpio_pin_wakeup_enable = 0x40004e90 ); +PROVIDE ( gpio_register_get = 0x40004d5c ); +PROVIDE ( gpio_register_set = 0x40004d04 ); +PROVIDE ( hmac_md5 = 0x4000a2cc ); +PROVIDE ( hmac_md5_vector = 0x4000a160 ); +PROVIDE ( hmac_sha1 = 0x4000ba28 ); +PROVIDE ( hmac_sha1_vector = 0x4000b8b4 ); +PROVIDE ( lldesc_build_chain = 0x40004f40 ); +PROVIDE ( lldesc_num2link = 0x40005050 ); +PROVIDE ( lldesc_set_owner = 0x4000507c ); +PROVIDE ( main = 0x40000fec ); +PROVIDE ( md5_vector = 0x400097ac ); +PROVIDE ( mem_calloc = 0x40001c2c ); +PROVIDE ( mem_free = 0x400019e0 ); +PROVIDE ( mem_init = 0x40001998 ); +PROVIDE ( mem_malloc = 0x40001b40 ); +PROVIDE ( mem_realloc = 0x40001c6c ); +PROVIDE ( mem_trim = 0x40001a14 ); +PROVIDE ( mem_zalloc = 0x40001c58 ); +PROVIDE ( memcmp = 0x4000dea8 ); +PROVIDE ( memcpy = 0x4000df48 ); +PROVIDE ( memmove = 0x4000e04c ); +PROVIDE ( memset = 0x4000e190 ); +PROVIDE ( multofup = 0x400031c0 ); +PROVIDE ( pbkdf2_sha1 = 0x4000b840 ); +PROVIDE ( phy_get_romfuncs = 0x40006b08 ); +PROVIDE ( rand = 0x40000600 ); +PROVIDE ( rc4_skip = 0x4000dd68 ); +PROVIDE ( recv_packet = 0x40003d08 ); +PROVIDE ( remove_head_space = 0x40000a04 ); +PROVIDE ( rijndaelKeySetupDec = 0x40008dd0 ); +PROVIDE ( rijndaelKeySetupEnc = 0x40009300 ); +PROVIDE ( rom_abs_temp = 0x400060c0 ); +PROVIDE ( rom_ana_inf_gating_en = 0x40006b10 ); +PROVIDE ( rom_cal_tos_v50 = 0x40007a28 ); +PROVIDE ( rom_chip_50_set_channel = 0x40006f84 ); +PROVIDE ( rom_chip_v5_disable_cca = 0x400060d0 ); +PROVIDE ( rom_chip_v5_enable_cca = 0x400060ec ); +PROVIDE ( rom_chip_v5_rx_init = 0x4000711c ); +PROVIDE ( rom_chip_v5_sense_backoff = 0x4000610c ); +PROVIDE ( rom_chip_v5_tx_init = 0x4000718c ); +PROVIDE ( rom_dc_iq_est = 0x4000615c ); +PROVIDE ( rom_en_pwdet = 0x400061b8 ); +PROVIDE ( rom_get_bb_atten = 0x40006238 ); +PROVIDE ( rom_get_corr_power = 0x40006260 ); +PROVIDE ( rom_get_fm_sar_dout = 0x400062dc ); +PROVIDE ( rom_get_noisefloor = 0x40006394 ); +PROVIDE ( rom_get_power_db = 0x400063b0 ); +PROVIDE ( rom_i2c_readReg = 0x40007268 ); +PROVIDE ( rom_i2c_readReg_Mask = 0x4000729c ); +PROVIDE ( rom_i2c_writeReg = 0x400072d8 ); +PROVIDE ( rom_i2c_writeReg_Mask = 0x4000730c ); +PROVIDE ( rom_iq_est_disable = 0x40006400 ); +PROVIDE ( rom_iq_est_enable = 0x40006430 ); +PROVIDE ( rom_linear_to_db = 0x40006484 ); +PROVIDE ( rom_mhz2ieee = 0x400065a4 ); +PROVIDE ( rom_pbus_dco___SA2 = 0x40007bf0 ); +PROVIDE ( rom_pbus_debugmode = 0x4000737c ); +PROVIDE ( rom_pbus_enter_debugmode = 0x40007410 ); +PROVIDE ( rom_pbus_exit_debugmode = 0x40007448 ); +PROVIDE ( rom_pbus_force_test = 0x4000747c ); +PROVIDE ( rom_pbus_rd = 0x400074d8 ); +PROVIDE ( rom_pbus_set_rxgain = 0x4000754c ); +PROVIDE ( rom_pbus_set_txgain = 0x40007610 ); +PROVIDE ( rom_pbus_workmode = 0x40007648 ); +PROVIDE ( rom_pbus_xpd_rx_off = 0x40007688 ); +PROVIDE ( rom_pbus_xpd_rx_on = 0x400076cc ); +PROVIDE ( rom_pbus_xpd_tx_off = 0x400076fc ); +PROVIDE ( rom_pbus_xpd_tx_on = 0x40007740 ); +PROVIDE ( rom_pbus_xpd_tx_on__low_gain = 0x400077a0 ); +PROVIDE ( rom_phy_reset_req = 0x40007804 ); +PROVIDE ( rom_restart_cal = 0x4000781c ); +PROVIDE ( rom_rfcal_pwrctrl = 0x40007eb4 ); +PROVIDE ( rom_rfcal_rxiq = 0x4000804c ); +PROVIDE ( rom_rfcal_rxiq_set_reg = 0x40008264 ); +PROVIDE ( rom_rfcal_txcap = 0x40008388 ); +PROVIDE ( rom_rfcal_txiq = 0x40008610 ); +PROVIDE ( rom_rfcal_txiq_cover = 0x400088b8 ); +PROVIDE ( rom_rfcal_txiq_set_reg = 0x40008a70 ); +PROVIDE ( rom_rfpll_reset = 0x40007868 ); +PROVIDE ( rom_rfpll_set_freq = 0x40007968 ); +PROVIDE ( rom_rxiq_cover_mg_mp = 0x40008b6c ); +PROVIDE ( rom_rxiq_get_mis = 0x40006628 ); +PROVIDE ( rom_sar_init = 0x40006738 ); +PROVIDE ( rom_set_ana_inf_tx_scale = 0x4000678c ); +PROVIDE ( rom_set_channel_freq = 0x40006c50 ); +PROVIDE ( rom_set_loopback_gain = 0x400067c8 ); +PROVIDE ( rom_set_noise_floor = 0x40006830 ); +PROVIDE ( rom_set_rxclk_en = 0x40006550 ); +PROVIDE ( rom_set_txbb_atten = 0x40008c6c ); +PROVIDE ( rom_set_txclk_en = 0x4000650c ); +PROVIDE ( rom_set_txiq_cal = 0x40008d34 ); +PROVIDE ( rom_start_noisefloor = 0x40006874 ); +PROVIDE ( rom_start_tx_tone = 0x400068b4 ); +PROVIDE ( rom_stop_tx_tone = 0x4000698c ); +PROVIDE ( rom_tx_mac_disable = 0x40006a98 ); +PROVIDE ( rom_tx_mac_enable = 0x40006ad4 ); +PROVIDE ( rom_txtone_linear_pwr = 0x40006a1c ); +PROVIDE ( rom_write_rfpll_sdm = 0x400078dc ); +PROVIDE ( roundup2 = 0x400031b4 ); +PROVIDE ( rtc_enter_sleep = 0x40002870 ); +PROVIDE ( rtc_get_reset_reason = 0x400025e0 ); +PROVIDE ( rtc_intr_handler = 0x400029ec ); +PROVIDE ( rtc_set_sleep_mode = 0x40002668 ); +PROVIDE ( save_rxbcn_mactime = 0x400027a4 ); +PROVIDE ( save_tsf_us = 0x400027ac ); +PROVIDE ( send_packet = 0x40003c80 ); +PROVIDE ( sha1_prf = 0x4000ba48 ); +PROVIDE ( sha1_vector = 0x4000a2ec ); +PROVIDE ( sip_alloc_to_host_evt = 0x40005180 ); +PROVIDE ( sip_get_ptr = 0x400058a8 ); +PROVIDE ( sip_get_state = 0x40005668 ); +PROVIDE ( sip_init_attach = 0x4000567c ); +PROVIDE ( sip_install_rx_ctrl_cb = 0x4000544c ); +PROVIDE ( sip_install_rx_data_cb = 0x4000545c ); +PROVIDE ( sip_post = 0x400050fc ); +PROVIDE ( sip_post_init = 0x400056c4 ); +PROVIDE ( sip_reclaim_from_host_cmd = 0x4000534c ); +PROVIDE ( sip_reclaim_tx_data_pkt = 0x400052c0 ); +PROVIDE ( sip_send = 0x40005808 ); +PROVIDE ( sip_to_host_chain_append = 0x40005864 ); +PROVIDE ( sip_to_host_evt_send_done = 0x40005234 ); +PROVIDE ( slc_add_credits = 0x400060ac ); +PROVIDE ( slc_enable = 0x40005d90 ); +PROVIDE ( slc_from_host_chain_fetch = 0x40005f24 ); +PROVIDE ( slc_from_host_chain_recycle = 0x40005e94 ); +PROVIDE ( slc_init_attach = 0x40005c50 ); +PROVIDE ( slc_init_credit = 0x4000608c ); +PROVIDE ( slc_pause_from_host = 0x40006014 ); +PROVIDE ( slc_reattach = 0x40005c1c ); +PROVIDE ( slc_resume_from_host = 0x4000603c ); +PROVIDE ( slc_select_tohost_gpio = 0x40005dc0 ); +PROVIDE ( slc_select_tohost_gpio_mode = 0x40005db8 ); +PROVIDE ( slc_send_to_host_chain = 0x40005de4 ); +PROVIDE ( slc_set_host_io_max_window = 0x40006068 ); +PROVIDE ( slc_to_host_chain_recycle = 0x40005f10 ); +PROVIDE ( software_reset = 0x4000264c ); +PROVIDE ( spi_flash_attach = 0x40004644 ); +PROVIDE ( srand = 0x400005f0 ); +PROVIDE ( strcmp = 0x4000bdc8 ); +PROVIDE ( strcpy = 0x4000bec8 ); +PROVIDE ( strlen = 0x4000bf4c ); +PROVIDE ( strncmp = 0x4000bfa8 ); +PROVIDE ( strncpy = 0x4000c0a0 ); +PROVIDE ( strstr = 0x4000e1e0 ); +PROVIDE ( timer_insert = 0x40002c64 ); +PROVIDE ( uartAttach = 0x4000383c ); +PROVIDE ( uart_baudrate_detect = 0x40003924 ); +PROVIDE ( uart_buff_switch = 0x400038a4 ); +PROVIDE ( uart_rx_intr_handler = 0x40003bbc ); +PROVIDE ( uart_rx_one_char = 0x40003b8c ); +PROVIDE ( uart_rx_one_char_block = 0x40003b64 ); +PROVIDE ( uart_rx_readbuff = 0x40003ec8 ); +PROVIDE ( uart_tx_one_char = 0x40003b30 ); +PROVIDE ( wepkey_128 = 0x4000bc40 ); +PROVIDE ( wepkey_64 = 0x4000bb3c ); +PROVIDE ( xthal_bcopy = 0x40000688 ); +PROVIDE ( xthal_copy123 = 0x4000074c ); +PROVIDE ( xthal_get_ccompare = 0x4000dd4c ); +PROVIDE ( xthal_get_ccount = 0x4000dd38 ); +PROVIDE ( xthal_get_interrupt = 0x4000dd58 ); +PROVIDE ( xthal_get_intread = 0x4000dd58 ); +PROVIDE ( xthal_memcpy = 0x400006c4 ); +PROVIDE ( xthal_set_ccompare = 0x4000dd40 ); +PROVIDE ( xthal_set_intclear = 0x4000dd60 ); +PROVIDE ( xthal_spill_registers_into_stack_nw = 0x4000e320 ); +PROVIDE ( xthal_window_spill = 0x4000e324 ); +PROVIDE ( xthal_window_spill_nw = 0x4000e320 ); + +PROVIDE ( Te0 = 0x3fffccf0 ); +PROVIDE ( Td0 = 0x3fffd100 ); +PROVIDE ( Td4s = 0x3fffd500); +PROVIDE ( rcons = 0x3fffd0f0); +PROVIDE ( UartDev = 0x3fffde10 ); +PROVIDE ( flashchip = 0x3fffc714); diff --git a/Sming/Arch/Esp8266/Components/esp8266/ESP8266_NONOS_SDK b/Sming/Arch/Esp8266/Components/esp8266/sdk similarity index 100% rename from Sming/Arch/Esp8266/Components/esp8266/ESP8266_NONOS_SDK rename to Sming/Arch/Esp8266/Components/esp8266/sdk diff --git a/Sming/Arch/Esp8266/Components/esp8266/ESP8266_NONOS_SDK.patch b/Sming/Arch/Esp8266/Components/esp8266/sdk.patch similarity index 100% rename from Sming/Arch/Esp8266/Components/esp8266/ESP8266_NONOS_SDK.patch rename to Sming/Arch/Esp8266/Components/esp8266/sdk.patch diff --git a/Sming/Arch/Esp8266/Components/esp8266/startup.cpp b/Sming/Arch/Esp8266/Components/esp8266/startup.cpp index f171bb20a9..facaec0a26 100644 --- a/Sming/Arch/Esp8266/Components/esp8266/startup.cpp +++ b/Sming/Arch/Esp8266/Components/esp8266/startup.cpp @@ -8,15 +8,15 @@ * */ -#include #include "Platform/System.h" #include #include #include -#include #include +#include extern void init(); +extern void cpp_core_initialize(); extern "C" void user_init(void) { @@ -44,29 +44,6 @@ extern "C" void user_init(void) init(); // User code init } -// For compatibility with SDK v1.1 -extern "C" void WEAK_ATTR user_rf_pre_init(void) -{ - // RTC startup fix, author pvvx - volatile uint32 * ptr_reg_rtc_ram = (volatile uint32 *)0x60001000; - if((ptr_reg_rtc_ram[24] >> 16) > 4) { - ptr_reg_rtc_ram[24] &= 0xFFFF; - ptr_reg_rtc_ram[30] &= 0; - } -} - -extern "C" uint32 ICACHE_FLASH_ATTR WEAK_ATTR user_rf_cal_sector_set(void) -{ - auto rfCal = *Storage::findPartition(Storage::Partition::SubType::Data::rfCal); - return rfCal.address(); -} - -#ifdef SDK_INTERNAL -#include -#endif - -#if defined(ESP_SDK_VERSION_MAJOR) and ESP_SDK_VERSION_MAJOR>=3 - extern "C" void ICACHE_FLASH_ATTR WEAK_ATTR user_pre_init(void) { Storage::initialize(); @@ -90,13 +67,8 @@ extern "C" void ICACHE_FLASH_ATTR WEAK_ATTR user_pre_init(void) auto& part = partitions[i]; os_printf("partition[%u]: %u, 0x%08x, 0x%08x\n", i, part.type, part.addr, part.size); } - if(sizeMap < FLASH_SIZE_8M_MAP_512_512) { - os_printf("** Note: SDK 3.0.1 requires spiFlash size >= 1M\n"); - } while(1) { // Cannot proceed }; } } - -#endif /* defined(ESP_SDK_VERSION_MAJOR) and ESP_SDK_VERSION_MAJOR>=3 */ diff --git a/Sming/Arch/Esp8266/Components/esp_no_wifi/app_main.c b/Sming/Arch/Esp8266/Components/esp_no_wifi/app_main.c index 1ae71df6bf..2cc37dfa9d 100644 --- a/Sming/Arch/Esp8266/Components/esp_no_wifi/app_main.c +++ b/Sming/Arch/Esp8266/Components/esp_no_wifi/app_main.c @@ -2,6 +2,7 @@ #include #include #include +#include extern uint8_t _bss_start, _bss_end; extern struct rst_info rst_if; diff --git a/Sming/Arch/Esp8266/Components/esp_no_wifi/include/esp_wifi.h b/Sming/Arch/Esp8266/Components/esp_no_wifi/include/esp_wifi.h deleted file mode 100644 index 0ab76b8b96..0000000000 --- a/Sming/Arch/Esp8266/Components/esp_no_wifi/include/esp_wifi.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#ifdef __cplusplus -} -#endif diff --git a/Sming/Arch/Esp8266/Components/esp_no_wifi/user_interface.c b/Sming/Arch/Esp8266/Components/esp_no_wifi/user_interface.c index a1dd80bd21..967a291d54 100644 --- a/Sming/Arch/Esp8266/Components/esp_no_wifi/user_interface.c +++ b/Sming/Arch/Esp8266/Components/esp_no_wifi/user_interface.c @@ -1,4 +1,5 @@ #include +#include #include bool protect_flag; @@ -309,9 +310,6 @@ uint8_t system_get_os_print(void) return os_print_enabled; } -void ets_write_char(char ch); -int ets_vprintf(void* routine, const char* format, va_list arg); - int os_printf_plus(const char* format, ...) { if(!os_print_enabled) { diff --git a/Sming/Arch/Esp8266/Components/fatfs/README.rst b/Sming/Arch/Esp8266/Components/fatfs/README.rst deleted file mode 100644 index 0f85a7d7a7..0000000000 --- a/Sming/Arch/Esp8266/Components/fatfs/README.rst +++ /dev/null @@ -1,6 +0,0 @@ -FAT Filing System -================= - -Required by the SDCard library. - -http://elm-chan.org/fsw/ff/00index_e.html diff --git a/Sming/Arch/Esp8266/Components/fatfs/diskio.h b/Sming/Arch/Esp8266/Components/fatfs/diskio.h deleted file mode 100644 index c7e901d332..0000000000 --- a/Sming/Arch/Esp8266/Components/fatfs/diskio.h +++ /dev/null @@ -1,85 +0,0 @@ -/*----------------------------------------------------------------------- -/ Low level disk interface modlue include file (C)ChaN, 2014 -/-----------------------------------------------------------------------*/ - -#ifndef _DISKIO_DEFINED -#define _DISKIO_DEFINED - -#ifdef __cplusplus -extern "C" { -#endif - -#include "integer.h" - - -/* Status of Disk Functions */ -typedef BYTE DSTATUS; - -/* Results of Disk Functions */ -typedef enum { - RES_OK = 0, /* 0: Successful */ - RES_ERROR, /* 1: R/W Error */ - RES_WRPRT, /* 2: Write Protected */ - RES_NOTRDY, /* 3: Not Ready */ - RES_PARERR /* 4: Invalid Parameter */ -} DRESULT; - - -/*---------------------------------------*/ -/* Prototypes for disk control functions */ - - -DSTATUS disk_initialize (BYTE pdrv); -DSTATUS disk_status (BYTE pdrv); -DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count); -DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count); -DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); - - -/* Disk Status Bits (DSTATUS) */ -#define STA_NOINIT 0x01 /* Drive not initialized */ -#define STA_NODISK 0x02 /* No medium in the drive */ -#define STA_PROTECT 0x04 /* Write protected */ - - -/* Command code for disk_ioctrl fucntion */ - -/* Generic command (Used by FatFs) */ -#define CTRL_SYNC 0 /* Complete pending write process (needed at _FS_READONLY == 0) */ -#define GET_SECTOR_COUNT 1 /* Get media size (needed at _USE_MKFS == 1) */ -#define GET_SECTOR_SIZE 2 /* Get sector size (needed at _MAX_SS != _MIN_SS) */ -#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at _USE_MKFS == 1) */ -#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */ - -/* Generic command (Not used by FatFs) */ -#define CTRL_POWER 5 /* Get/Set power status */ -#define CTRL_LOCK 6 /* Lock/Unlock media removal */ -#define CTRL_EJECT 7 /* Eject media */ -#define CTRL_FORMAT 8 /* Create physical format on the media */ - -/* MMC/SDC specific command (Not used by FatFs) */ -#define MMC_GET_TYPE 10 /* Get card type */ -#define MMC_GET_CSD 11 /* Get CSD */ -#define MMC_GET_CID 12 /* Get CID */ -#define MMC_GET_OCR 13 /* Get OCR */ -#define MMC_GET_SDSTAT 14 /* Get SD status */ - -/* ATA/CF specific command (Not used by FatFs) */ -#define ATA_GET_REV 20 /* Get F/W revision */ -#define ATA_GET_MODEL 21 /* Get model name */ -#define ATA_GET_SN 22 /* Get serial number */ - - -/* MMC card type flags (MMC_GET_TYPE) */ -#define CT_MMC 0x01 /* MMC ver 3 */ -#define CT_SD1 0x02 /* SD ver 1 */ -#define CT_SD2 0x04 /* SD ver 2 */ -#define CT_SDC (CT_SD1|CT_SD2) /* SD */ -#define CT_BLOCK 0x08 /* Block addressing */ - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Sming/Arch/Esp8266/Components/fatfs/ff.c b/Sming/Arch/Esp8266/Components/fatfs/ff.c deleted file mode 100644 index 30d2e714c8..0000000000 --- a/Sming/Arch/Esp8266/Components/fatfs/ff.c +++ /dev/null @@ -1,4635 +0,0 @@ -/*----------------------------------------------------------------------------/ -/ FatFs - FAT file system module R0.11 (C)ChaN, 2015 -/-----------------------------------------------------------------------------/ -/ FatFs module is a free software that opened under license policy of -/ following conditions. -/ -/ Copyright (C) 2015, ChaN, all right reserved. -/ -/ 1. Redistributions of source code must retain the above copyright notice, -/ this condition and the following disclaimer. -/ -/ This software is provided by the copyright holder and contributors "AS IS" -/ and any warranties related to this software are DISCLAIMED. -/ The copyright owner or contributors be NOT LIABLE for any damages caused -/ by use of this software. -/----------------------------------------------------------------------------*/ - - -#include "ff.h" /* Declarations of FatFs API */ -#include "diskio.h" /* Declarations of disk I/O functions */ - - -/*-------------------------------------------------------------------------- - - Module Private Definitions - ----------------------------------------------------------------------------*/ - -#if _FATFS != 32020 /* Revision ID */ -#error Wrong include file (ff.h). -#endif - - -/* Reentrancy related */ -#if _FS_REENTRANT -#if _USE_LFN == 1 -#error Static LFN work area cannot be used at thread-safe configuration -#endif -#define ENTER_FF(fs) { if (!lock_fs(fs)) return FR_TIMEOUT; } -#define LEAVE_FF(fs, res) { unlock_fs(fs, res); return res; } -#else -#define ENTER_FF(fs) -#define LEAVE_FF(fs, res) return res -#endif - -#define ABORT(fs, res) { fp->err = (BYTE)(res); LEAVE_FF(fs, res); } - - -/* Definitions of sector size */ -#if (_MAX_SS < _MIN_SS) || (_MAX_SS != 512 && _MAX_SS != 1024 && _MAX_SS != 2048 && _MAX_SS != 4096) || (_MIN_SS != 512 && _MIN_SS != 1024 && _MIN_SS != 2048 && _MIN_SS != 4096) -#error Wrong sector size configuration -#endif -#if _MAX_SS == _MIN_SS -#define SS(fs) ((UINT)_MAX_SS) /* Fixed sector size */ -#else -#define SS(fs) ((fs)->ssize) /* Variable sector size */ -#endif - - -/* Timestamp feature */ -#if _FS_NORTC == 1 -#if _NORTC_YEAR < 1980 || _NORTC_YEAR > 2107 || _NORTC_MON < 1 || _NORTC_MON > 12 || _NORTC_MDAY < 1 || _NORTC_MDAY > 31 -#error Invalid _FS_NORTC settings -#endif -#define GET_FATTIME() ((DWORD)(_NORTC_YEAR - 1980) << 25 | (DWORD)_NORTC_MON << 21 | (DWORD)_NORTC_MDAY << 16) -#else -#define GET_FATTIME() get_fattime() -#endif - - -/* File access control feature */ -#if _FS_LOCK -#if _FS_READONLY -#error _FS_LOCK must be 0 at read-only configuration -#endif -typedef struct { - FATFS *fs; /* Object ID 1, volume (NULL:blank entry) */ - DWORD clu; /* Object ID 2, directory (0:root) */ - WORD idx; /* Object ID 3, directory index */ - WORD ctr; /* Object open counter, 0:none, 0x01..0xFF:read mode open count, 0x100:write mode */ -} FILESEM; -#endif - - - -/* DBCS code ranges and SBCS extend character conversion table */ - -#if _CODE_PAGE == 932 /* Japanese Shift-JIS */ -#define _DF1S 0x81 /* DBC 1st byte range 1 start */ -#define _DF1E 0x9F /* DBC 1st byte range 1 end */ -#define _DF2S 0xE0 /* DBC 1st byte range 2 start */ -#define _DF2E 0xFC /* DBC 1st byte range 2 end */ -#define _DS1S 0x40 /* DBC 2nd byte range 1 start */ -#define _DS1E 0x7E /* DBC 2nd byte range 1 end */ -#define _DS2S 0x80 /* DBC 2nd byte range 2 start */ -#define _DS2E 0xFC /* DBC 2nd byte range 2 end */ - -#elif _CODE_PAGE == 936 /* Simplified Chinese GBK */ -#define _DF1S 0x81 -#define _DF1E 0xFE -#define _DS1S 0x40 -#define _DS1E 0x7E -#define _DS2S 0x80 -#define _DS2E 0xFE - -#elif _CODE_PAGE == 949 /* Korean */ -#define _DF1S 0x81 -#define _DF1E 0xFE -#define _DS1S 0x41 -#define _DS1E 0x5A -#define _DS2S 0x61 -#define _DS2E 0x7A -#define _DS3S 0x81 -#define _DS3E 0xFE - -#elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */ -#define _DF1S 0x81 -#define _DF1E 0xFE -#define _DS1S 0x40 -#define _DS1E 0x7E -#define _DS2S 0xA1 -#define _DS2E 0xFE - -#elif _CODE_PAGE == 437 /* U.S. (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F,0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 720 /* Arabic (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x45,0x41,0x84,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x49,0x49,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 737 /* Greek (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \ - 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xE7,0xE8,0xF1,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 775 /* Baltic (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 850 /* Multilingual Latin 1 (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ - 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 852 /* Latin 2 (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F,0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0x9F, \ - 0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF} - -#elif _CODE_PAGE == 855 /* Cyrillic (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F,0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \ - 0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \ - 0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 857 /* Turkish (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x98,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \ - 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0x59,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 858 /* Multilingual Latin 1 + Euro (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ - 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 862 /* Hebrew (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 866 /* Russian (OEM) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0x90,0x91,0x92,0x93,0x9d,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 874 /* Thai (OEM, Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 1250 /* Central Europe (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xA3,0xB4,0xB5,0xB6,0xB7,0xB8,0xA5,0xAA,0xBB,0xBC,0xBD,0xBC,0xAF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} - -#elif _CODE_PAGE == 1251 /* Cyrillic (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x82,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x80,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \ - 0xA0,0xA2,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB2,0xA5,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xA3,0xBD,0xBD,0xAF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF} - -#elif _CODE_PAGE == 1252 /* Latin 1 (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0xAd,0x9B,0x8C,0x9D,0xAE,0x9F, \ - 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} - -#elif _CODE_PAGE == 1253 /* Greek (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xA2,0xB8,0xB9,0xBA, \ - 0xE0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xFB,0xBC,0xFD,0xBF,0xFF} - -#elif _CODE_PAGE == 1254 /* Turkish (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x9D,0x9E,0x9F, \ - 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} - -#elif _CODE_PAGE == 1255 /* Hebrew (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 1256 /* Arabic (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x8C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0x41,0xE1,0x41,0xE3,0xE4,0xE5,0xE6,0x43,0x45,0x45,0x45,0x45,0xEC,0xED,0x49,0x49,0xF0,0xF1,0xF2,0xF3,0x4F,0xF5,0xF6,0xF7,0xF8,0x55,0xFA,0x55,0x55,0xFD,0xFE,0xFF} - -#elif _CODE_PAGE == 1257 /* Baltic (Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ - 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xBC,0xBD,0xBE,0xAF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} - -#elif _CODE_PAGE == 1258 /* Vietnam (OEM, Windows) */ -#define _DF1S 0 -#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0xAC,0x9D,0x9E,0x9F, \ - 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ - 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xEC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xFE,0x9F} - -#elif _CODE_PAGE == 1 /* ASCII (for only non-LFN cfg) */ -#if _USE_LFN -#error Cannot use LFN feature without valid code page. -#endif -#define _DF1S 0 - -#else -#error Unknown code page - -#endif - - -/* Character code support macros */ -#define IsUpper(c) (((c)>='A')&&((c)<='Z')) -#define IsLower(c) (((c)>='a')&&((c)<='z')) -#define IsDigit(c) (((c)>='0')&&((c)<='9')) - -#if _DF1S /* Code page is DBCS */ - -#ifdef _DF2S /* Two 1st byte areas */ -#define IsDBCS1(c) (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E)) -#else /* One 1st byte area */ -#define IsDBCS1(c) ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) -#endif - -#ifdef _DS3S /* Three 2nd byte areas */ -#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E)) -#else /* Two 2nd byte areas */ -#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E)) -#endif - -#else /* Code page is SBCS */ - -#define IsDBCS1(c) 0 -#define IsDBCS2(c) 0 - -#endif /* _DF1S */ - - -/* Name status flags */ -#define NSFLAG 11 /* Index of name status byte in fn[] */ -#define NS_LOSS 0x01 /* Out of 8.3 format */ -#define NS_LFN 0x02 /* Force to create LFN entry */ -#define NS_LAST 0x04 /* Last segment */ -#define NS_BODY 0x08 /* Lower case flag (body) */ -#define NS_EXT 0x10 /* Lower case flag (ext) */ -#define NS_DOT 0x20 /* Dot entry */ - - -/* FAT sub-type boundaries (Differ from specs but correct for real DOS/Windows) */ -#define MIN_FAT16 4086U /* Minimum number of clusters as FAT16 */ -#define MIN_FAT32 65526U /* Minimum number of clusters as FAT32 */ - - -/* FatFs refers the members in the FAT structures as byte array instead of -/ structure member because the structure is not binary compatible between -/ different platforms */ - -#define BS_jmpBoot 0 /* x86 jump instruction (3) */ -#define BS_OEMName 3 /* OEM name (8) */ -#define BPB_BytsPerSec 11 /* Sector size [byte] (2) */ -#define BPB_SecPerClus 13 /* Cluster size [sector] (1) */ -#define BPB_RsvdSecCnt 14 /* Size of reserved area [sector] (2) */ -#define BPB_NumFATs 16 /* Number of FAT copies (1) */ -#define BPB_RootEntCnt 17 /* Number of root directory entries for FAT12/16 (2) */ -#define BPB_TotSec16 19 /* Volume size [sector] (2) */ -#define BPB_Media 21 /* Media descriptor (1) */ -#define BPB_FATSz16 22 /* FAT size [sector] (2) */ -#define BPB_SecPerTrk 24 /* Track size [sector] (2) */ -#define BPB_NumHeads 26 /* Number of heads (2) */ -#define BPB_HiddSec 28 /* Number of special hidden sectors (4) */ -#define BPB_TotSec32 32 /* Volume size [sector] (4) */ -#define BS_DrvNum 36 /* Physical drive number (2) */ -#define BS_BootSig 38 /* Extended boot signature (1) */ -#define BS_VolID 39 /* Volume serial number (4) */ -#define BS_VolLab 43 /* Volume label (8) */ -#define BS_FilSysType 54 /* File system type (1) */ -#define BPB_FATSz32 36 /* FAT size [sector] (4) */ -#define BPB_ExtFlags 40 /* Extended flags (2) */ -#define BPB_FSVer 42 /* File system version (2) */ -#define BPB_RootClus 44 /* Root directory first cluster (4) */ -#define BPB_FSInfo 48 /* Offset of FSINFO sector (2) */ -#define BPB_BkBootSec 50 /* Offset of backup boot sector (2) */ -#define BS_DrvNum32 64 /* Physical drive number (2) */ -#define BS_BootSig32 66 /* Extended boot signature (1) */ -#define BS_VolID32 67 /* Volume serial number (4) */ -#define BS_VolLab32 71 /* Volume label (8) */ -#define BS_FilSysType32 82 /* File system type (1) */ -#define FSI_LeadSig 0 /* FSI: Leading signature (4) */ -#define FSI_StrucSig 484 /* FSI: Structure signature (4) */ -#define FSI_Free_Count 488 /* FSI: Number of free clusters (4) */ -#define FSI_Nxt_Free 492 /* FSI: Last allocated cluster (4) */ -#define MBR_Table 446 /* MBR: Partition table offset (2) */ -#define SZ_PTE 16 /* MBR: Size of a partition table entry */ -#define BS_55AA 510 /* Signature word (2) */ - -#define DIR_Name 0 /* Short file name (11) */ -#define DIR_Attr 11 /* Attribute (1) */ -#define DIR_NTres 12 /* Lower case flag (1) */ -#define DIR_CrtTimeTenth 13 /* Created time sub-second (1) */ -#define DIR_CrtTime 14 /* Created time (2) */ -#define DIR_CrtDate 16 /* Created date (2) */ -#define DIR_LstAccDate 18 /* Last accessed date (2) */ -#define DIR_FstClusHI 20 /* Higher 16-bit of first cluster (2) */ -#define DIR_WrtTime 22 /* Modified time (2) */ -#define DIR_WrtDate 24 /* Modified date (2) */ -#define DIR_FstClusLO 26 /* Lower 16-bit of first cluster (2) */ -#define DIR_FileSize 28 /* File size (4) */ -#define LDIR_Ord 0 /* LFN entry order and LLE flag (1) */ -#define LDIR_Attr 11 /* LFN attribute (1) */ -#define LDIR_Type 12 /* LFN type (1) */ -#define LDIR_Chksum 13 /* Sum of corresponding SFN entry */ -#define LDIR_FstClusLO 26 /* Must be zero (0) */ -#define SZ_DIRE 32 /* Size of a directory entry */ -#define LLEF 0x40 /* Last long entry flag in LDIR_Ord */ -#define DDEM 0xE5 /* Deleted directory entry mark at DIR_Name[0] */ -#define RDDEM 0x05 /* Replacement of the character collides with DDEM */ - - - - -/*------------------------------------------------------------*/ -/* Module private work area */ -/*------------------------------------------------------------*/ -/* Remark: Uninitialized variables with static duration are -/ guaranteed zero/null at start-up. If not, either the linker -/ or start-up routine being used is out of ANSI-C standard. -*/ - -#if _VOLUMES < 1 || _VOLUMES > 9 -#error Wrong _VOLUMES setting -#endif -static FATFS *FatFs[_VOLUMES]; /* Pointer to the file system objects (logical drives) */ -static WORD Fsid; /* File system mount ID */ - -#if _FS_RPATH && _VOLUMES >= 2 -static BYTE CurrVol; /* Current drive */ -#endif - -#if _FS_LOCK -static FILESEM Files[_FS_LOCK]; /* Open object lock semaphores */ -#endif - -#if _USE_LFN == 0 /* Non LFN feature */ -#define DEFINE_NAMEBUF BYTE sfn[12] -#define INIT_BUF(dobj) (dobj).fn = sfn -#define FREE_BUF() -#else -#if _MAX_LFN < 12 || _MAX_LFN > 255 -#error Wrong _MAX_LFN setting -#endif -#if _USE_LFN == 1 /* LFN feature with static working buffer */ -static WCHAR LfnBuf[_MAX_LFN + 1]; -#define DEFINE_NAMEBUF BYTE sfn[12] -#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = LfnBuf; } -#define FREE_BUF() -#elif _USE_LFN == 2 /* LFN feature with dynamic working buffer on the stack */ -#define DEFINE_NAMEBUF BYTE sfn[12]; WCHAR lbuf[_MAX_LFN + 1] -#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = lbuf; } -#define FREE_BUF() -#elif _USE_LFN == 3 /* LFN feature with dynamic working buffer on the heap */ -#define DEFINE_NAMEBUF BYTE sfn[12]; WCHAR *lfn -#define INIT_BUF(dobj) { lfn = ff_memalloc((_MAX_LFN + 1) * 2); if (!lfn) LEAVE_FF((dobj).fs, FR_NOT_ENOUGH_CORE); (dobj).lfn = lfn; (dobj).fn = sfn; } -#define FREE_BUF() ff_memfree(lfn) -#else -#error Wrong _USE_LFN setting -#endif -#endif - -#ifdef _EXCVT -static const BYTE ExCvt[] = _EXCVT; /* Upper conversion table for extended characters */ -#endif - - - - - - -/*-------------------------------------------------------------------------- - - Module Private Functions - ----------------------------------------------------------------------------*/ - - -/*-----------------------------------------------------------------------*/ -/* String functions */ -/*-----------------------------------------------------------------------*/ - -/* Copy memory to memory */ -static -void mem_cpy (void* dst, const void* src, UINT cnt) { - BYTE *d = (BYTE*)dst; - const BYTE *s = (const BYTE*)src; - -#if _WORD_ACCESS == 1 - while (cnt >= sizeof (int)) { - *(int*)d = *(int*)s; - d += sizeof (int); s += sizeof (int); - cnt -= sizeof (int); - } -#endif - while (cnt--) - *d++ = *s++; -} - -/* Fill memory */ -static -void mem_set (void* dst, int val, UINT cnt) { - BYTE *d = (BYTE*)dst; - - while (cnt--) - *d++ = (BYTE)val; -} - -/* Compare memory to memory */ -static -int mem_cmp (const void* dst, const void* src, UINT cnt) { - const BYTE *d = (const BYTE *)dst, *s = (const BYTE *)src; - int r = 0; - - while (cnt-- && (r = *d++ - *s++) == 0) ; - return r; -} - -/* Check if chr is contained in the string */ -static -int chk_chr (const char* str, int chr) { - while (*str && *str != chr) str++; - return *str; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Request/Release grant to access the volume */ -/*-----------------------------------------------------------------------*/ -#if _FS_REENTRANT -static -int lock_fs ( - FATFS* fs /* File system object */ -) -{ - return ff_req_grant(fs->sobj); -} - - -static -void unlock_fs ( - FATFS* fs, /* File system object */ - FRESULT res /* Result code to be returned */ -) -{ - if (fs && - res != FR_NOT_ENABLED && - res != FR_INVALID_DRIVE && - res != FR_INVALID_OBJECT && - res != FR_TIMEOUT) { - ff_rel_grant(fs->sobj); - } -} -#endif - - - - -/*-----------------------------------------------------------------------*/ -/* File lock control functions */ -/*-----------------------------------------------------------------------*/ -#if _FS_LOCK - -static -FRESULT chk_lock ( /* Check if the file can be accessed */ - DIR* dp, /* Directory object pointing the file to be checked */ - int acc /* Desired access type (0:Read, 1:Write, 2:Delete/Rename) */ -) -{ - UINT i, be; - - /* Search file semaphore table */ - for (i = be = 0; i < _FS_LOCK; i++) { - if (Files[i].fs) { /* Existing entry */ - if (Files[i].fs == dp->fs && /* Check if the object matched with an open object */ - Files[i].clu == dp->sclust && - Files[i].idx == dp->index) break; - } else { /* Blank entry */ - be = 1; - } - } - if (i == _FS_LOCK) /* The object is not opened */ - return (be || acc == 2) ? FR_OK : FR_TOO_MANY_OPEN_FILES; /* Is there a blank entry for new object? */ - - /* The object has been opened. Reject any open against writing file and all write mode open */ - return (acc || Files[i].ctr == 0x100) ? FR_LOCKED : FR_OK; -} - - -static -int enq_lock (void) /* Check if an entry is available for a new object */ -{ - UINT i; - - for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ; - return (i == _FS_LOCK) ? 0 : 1; -} - - -static -UINT inc_lock ( /* Increment object open counter and returns its index (0:Internal error) */ - DIR* dp, /* Directory object pointing the file to register or increment */ - int acc /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */ -) -{ - UINT i; - - - for (i = 0; i < _FS_LOCK; i++) { /* Find the object */ - if (Files[i].fs == dp->fs && - Files[i].clu == dp->sclust && - Files[i].idx == dp->index) break; - } - - if (i == _FS_LOCK) { /* Not opened. Register it as new. */ - for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ; - if (i == _FS_LOCK) return 0; /* No free entry to register (int err) */ - Files[i].fs = dp->fs; - Files[i].clu = dp->sclust; - Files[i].idx = dp->index; - Files[i].ctr = 0; - } - - if (acc && Files[i].ctr) return 0; /* Access violation (int err) */ - - Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1; /* Set semaphore value */ - - return i + 1; -} - - -static -FRESULT dec_lock ( /* Decrement object open counter */ - UINT i /* Semaphore index (1..) */ -) -{ - WORD n; - FRESULT res; - - - if (--i < _FS_LOCK) { /* Shift index number origin from 0 */ - n = Files[i].ctr; - if (n == 0x100) n = 0; /* If write mode open, delete the entry */ - if (n) n--; /* Decrement read mode open count */ - Files[i].ctr = n; - if (!n) Files[i].fs = 0; /* Delete the entry if open count gets zero */ - res = FR_OK; - } else { - res = FR_INT_ERR; /* Invalid index nunber */ - } - return res; -} - - -static -void clear_lock ( /* Clear lock entries of the volume */ - FATFS *fs -) -{ - UINT i; - - for (i = 0; i < _FS_LOCK; i++) { - if (Files[i].fs == fs) Files[i].fs = 0; - } -} -#endif - - - - -/*-----------------------------------------------------------------------*/ -/* Move/Flush disk access window in the file system object */ -/*-----------------------------------------------------------------------*/ -#if !_FS_READONLY -static -FRESULT sync_window ( - FATFS* fs /* File system object */ -) -{ - DWORD wsect; - UINT nf; - FRESULT res = FR_OK; - - - if (fs->wflag) { /* Write back the sector if it is dirty */ - wsect = fs->winsect; /* Current sector number */ - if (disk_write(fs->drv, fs->win, wsect, 1) != RES_OK) { - res = FR_DISK_ERR; - } else { - fs->wflag = 0; - if (wsect - fs->fatbase < fs->fsize) { /* Is it in the FAT area? */ - for (nf = fs->n_fats; nf >= 2; nf--) { /* Reflect the change to all FAT copies */ - wsect += fs->fsize; - disk_write(fs->drv, fs->win, wsect, 1); - } - } - } - } - return res; -} -#endif - - -static -FRESULT move_window ( - FATFS* fs, /* File system object */ - DWORD sector /* Sector number to make appearance in the fs->win[] */ -) -{ - FRESULT res = FR_OK; - - - if (sector != fs->winsect) { /* Window offset changed? */ -#if !_FS_READONLY - res = sync_window(fs); /* Write-back changes */ -#endif - if (res == FR_OK) { /* Fill sector window with new data */ - if (disk_read(fs->drv, fs->win, sector, 1) != RES_OK) { - sector = 0xFFFFFFFF; /* Invalidate window if data is not reliable */ - res = FR_DISK_ERR; - } - fs->winsect = sector; - } - } - return res; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Synchronize file system and strage device */ -/*-----------------------------------------------------------------------*/ -#if !_FS_READONLY -static -FRESULT sync_fs ( /* FR_OK: successful, FR_DISK_ERR: failed */ - FATFS* fs /* File system object */ -) -{ - FRESULT res; - - - res = sync_window(fs); - if (res == FR_OK) { - /* Update FSINFO sector if needed */ - if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) { - /* Create FSINFO structure */ - mem_set(fs->win, 0, SS(fs)); - ST_WORD(fs->win + BS_55AA, 0xAA55); - ST_DWORD(fs->win + FSI_LeadSig, 0x41615252); - ST_DWORD(fs->win + FSI_StrucSig, 0x61417272); - ST_DWORD(fs->win + FSI_Free_Count, fs->free_clust); - ST_DWORD(fs->win + FSI_Nxt_Free, fs->last_clust); - /* Write it into the FSINFO sector */ - fs->winsect = fs->volbase + 1; - disk_write(fs->drv, fs->win, fs->winsect, 1); - fs->fsi_flag = 0; - } - /* Make sure that no pending write process in the physical drive */ - if (disk_ioctl(fs->drv, CTRL_SYNC, 0) != RES_OK) - res = FR_DISK_ERR; - } - - return res; -} -#endif - - - - -/*-----------------------------------------------------------------------*/ -/* Get sector# from cluster# */ -/*-----------------------------------------------------------------------*/ -/* Hidden API for hacks and disk tools */ - -DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */ - FATFS* fs, /* File system object */ - DWORD clst /* Cluster# to be converted */ -) -{ - clst -= 2; - if (clst >= fs->n_fatent - 2) return 0; /* Invalid cluster# */ - return clst * fs->csize + fs->database; -} - - - - -/*-----------------------------------------------------------------------*/ -/* FAT access - Read value of a FAT entry */ -/*-----------------------------------------------------------------------*/ -/* Hidden API for hacks and disk tools */ - -DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x0FFFFFFF:Cluster status */ - FATFS* fs, /* File system object */ - DWORD clst /* FAT index number (cluster number) to get the value */ -) -{ - UINT wc, bc; - BYTE *p; - DWORD val; - - - if (clst < 2 || clst >= fs->n_fatent) { /* Check range */ - val = 1; /* Internal error */ - - } else { - val = 0xFFFFFFFF; /* Default value falls on disk error */ - - switch (fs->fs_type) { - case FS_FAT12 : - bc = (UINT)clst; bc += bc / 2; - if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break; - wc = fs->win[bc++ % SS(fs)]; - if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break; - wc |= fs->win[bc % SS(fs)] << 8; - val = clst & 1 ? wc >> 4 : (wc & 0xFFF); - break; - - case FS_FAT16 : - if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))) != FR_OK) break; - p = &fs->win[clst * 2 % SS(fs)]; - val = LD_WORD(p); - break; - - case FS_FAT32 : - if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break; - p = &fs->win[clst * 4 % SS(fs)]; - val = LD_DWORD(p) & 0x0FFFFFFF; - break; - - default: - val = 1; /* Internal error */ - } - } - - return val; -} - - - - -/*-----------------------------------------------------------------------*/ -/* FAT access - Change value of a FAT entry */ -/*-----------------------------------------------------------------------*/ -/* Hidden API for hacks and disk tools */ - -#if !_FS_READONLY -FRESULT put_fat ( - FATFS* fs, /* File system object */ - DWORD clst, /* FAT index number (cluster number) to be changed */ - DWORD val /* New value to be set to the entry */ -) -{ - UINT bc; - BYTE *p; - FRESULT res; - - - if (clst < 2 || clst >= fs->n_fatent) { /* Check range */ - res = FR_INT_ERR; - - } else { - switch (fs->fs_type) { - case FS_FAT12 : - bc = (UINT)clst; bc += bc / 2; - res = move_window(fs, fs->fatbase + (bc / SS(fs))); - if (res != FR_OK) break; - p = &fs->win[bc++ % SS(fs)]; - *p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val; - fs->wflag = 1; - res = move_window(fs, fs->fatbase + (bc / SS(fs))); - if (res != FR_OK) break; - p = &fs->win[bc % SS(fs)]; - *p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F)); - fs->wflag = 1; - break; - - case FS_FAT16 : - res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))); - if (res != FR_OK) break; - p = &fs->win[clst * 2 % SS(fs)]; - ST_WORD(p, (WORD)val); - fs->wflag = 1; - break; - - case FS_FAT32 : - res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))); - if (res != FR_OK) break; - p = &fs->win[clst * 4 % SS(fs)]; - val |= LD_DWORD(p) & 0xF0000000; - ST_DWORD(p, val); - fs->wflag = 1; - break; - - default : - res = FR_INT_ERR; - } - } - - return res; -} -#endif /* !_FS_READONLY */ - - - - -/*-----------------------------------------------------------------------*/ -/* FAT handling - Remove a cluster chain */ -/*-----------------------------------------------------------------------*/ -#if !_FS_READONLY -static -FRESULT remove_chain ( - FATFS* fs, /* File system object */ - DWORD clst /* Cluster# to remove a chain from */ -) -{ - FRESULT res; - DWORD nxt; -#if _USE_TRIM - DWORD scl = clst, ecl = clst, rt[2]; -#endif - - if (clst < 2 || clst >= fs->n_fatent) { /* Check range */ - res = FR_INT_ERR; - - } else { - res = FR_OK; - while (clst < fs->n_fatent) { /* Not a last link? */ - nxt = get_fat(fs, clst); /* Get cluster status */ - if (nxt == 0) break; /* Empty cluster? */ - if (nxt == 1) { res = FR_INT_ERR; break; } /* Internal error? */ - if (nxt == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } /* Disk error? */ - res = put_fat(fs, clst, 0); /* Mark the cluster "empty" */ - if (res != FR_OK) break; - if (fs->free_clust != 0xFFFFFFFF) { /* Update FSINFO */ - fs->free_clust++; - fs->fsi_flag |= 1; - } -#if _USE_TRIM - if (ecl + 1 == nxt) { /* Is next cluster contiguous? */ - ecl = nxt; - } else { /* End of contiguous clusters */ - rt[0] = clust2sect(fs, scl); /* Start sector */ - rt[1] = clust2sect(fs, ecl) + fs->csize - 1; /* End sector */ - disk_ioctl(fs->drv, CTRL_TRIM, rt); /* Erase the block */ - scl = ecl = nxt; - } -#endif - clst = nxt; /* Next cluster */ - } - } - - return res; -} -#endif - - - - -/*-----------------------------------------------------------------------*/ -/* FAT handling - Stretch or Create a cluster chain */ -/*-----------------------------------------------------------------------*/ -#if !_FS_READONLY -static -DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */ - FATFS* fs, /* File system object */ - DWORD clst /* Cluster# to stretch. 0 means create a new chain. */ -) -{ - DWORD cs, ncl, scl; - FRESULT res; - - - if (clst == 0) { /* Create a new chain */ - scl = fs->last_clust; /* Get suggested start point */ - if (!scl || scl >= fs->n_fatent) scl = 1; - } - else { /* Stretch the current chain */ - cs = get_fat(fs, clst); /* Check the cluster status */ - if (cs < 2) return 1; /* Invalid value */ - if (cs == 0xFFFFFFFF) return cs; /* A disk error occurred */ - if (cs < fs->n_fatent) return cs; /* It is already followed by next cluster */ - scl = clst; - } - - ncl = scl; /* Start cluster */ - for (;;) { - ncl++; /* Next cluster */ - if (ncl >= fs->n_fatent) { /* Check wrap around */ - ncl = 2; - if (ncl > scl) return 0; /* No free cluster */ - } - cs = get_fat(fs, ncl); /* Get the cluster status */ - if (cs == 0) break; /* Found a free cluster */ - if (cs == 0xFFFFFFFF || cs == 1)/* An error occurred */ - return cs; - if (ncl == scl) return 0; /* No free cluster */ - } - - res = put_fat(fs, ncl, 0x0FFFFFFF); /* Mark the new cluster "last link" */ - if (res == FR_OK && clst != 0) { - res = put_fat(fs, clst, ncl); /* Link it to the previous one if needed */ - } - if (res == FR_OK) { - fs->last_clust = ncl; /* Update FSINFO */ - if (fs->free_clust != 0xFFFFFFFF) { - fs->free_clust--; - fs->fsi_flag |= 1; - } - } else { - ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1; - } - - return ncl; /* Return new cluster number or error code */ -} -#endif /* !_FS_READONLY */ - - - - -/*-----------------------------------------------------------------------*/ -/* FAT handling - Convert offset into cluster with link map table */ -/*-----------------------------------------------------------------------*/ - -#if _USE_FASTSEEK -static -DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */ - FIL* fp, /* Pointer to the file object */ - DWORD ofs /* File offset to be converted to cluster# */ -) -{ - DWORD cl, ncl, *tbl; - - - tbl = fp->cltbl + 1; /* Top of CLMT */ - cl = ofs / SS(fp->fs) / fp->fs->csize; /* Cluster order from top of the file */ - for (;;) { - ncl = *tbl++; /* Number of cluters in the fragment */ - if (!ncl) return 0; /* End of table? (error) */ - if (cl < ncl) break; /* In this fragment? */ - cl -= ncl; tbl++; /* Next fragment */ - } - return cl + *tbl; /* Return the cluster number */ -} -#endif /* _USE_FASTSEEK */ - - - - -/*-----------------------------------------------------------------------*/ -/* Directory handling - Set directory index */ -/*-----------------------------------------------------------------------*/ - -static -FRESULT dir_sdi ( - DIR* dp, /* Pointer to directory object */ - UINT idx /* Index of directory table */ -) -{ - DWORD clst, sect; - UINT ic; - - - dp->index = (WORD)idx; /* Current index */ - clst = dp->sclust; /* Table start cluster (0:root) */ - if (clst == 1 || clst >= dp->fs->n_fatent) /* Check start cluster range */ - return FR_INT_ERR; - if (!clst && dp->fs->fs_type == FS_FAT32) /* Replace cluster# 0 with root cluster# if in FAT32 */ - clst = dp->fs->dirbase; - - if (clst == 0) { /* Static table (root-directory in FAT12/16) */ - if (idx >= dp->fs->n_rootdir) /* Is index out of range? */ - return FR_INT_ERR; - sect = dp->fs->dirbase; - } - else { /* Dynamic table (root-directory in FAT32 or sub-directory) */ - ic = SS(dp->fs) / SZ_DIRE * dp->fs->csize; /* Entries per cluster */ - while (idx >= ic) { /* Follow cluster chain */ - clst = get_fat(dp->fs, clst); /* Get next cluster */ - if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ - if (clst < 2 || clst >= dp->fs->n_fatent) /* Reached to end of table or internal error */ - return FR_INT_ERR; - idx -= ic; - } - sect = clust2sect(dp->fs, clst); - } - dp->clust = clst; /* Current cluster# */ - if (!sect) return FR_INT_ERR; - dp->sect = sect + idx / (SS(dp->fs) / SZ_DIRE); /* Sector# of the directory entry */ - dp->dir = dp->fs->win + (idx % (SS(dp->fs) / SZ_DIRE)) * SZ_DIRE; /* Ptr to the entry in the sector */ - - return FR_OK; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Directory handling - Move directory table index next */ -/*-----------------------------------------------------------------------*/ - -static -FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:Could not stretch */ - DIR* dp, /* Pointer to the directory object */ - int stretch /* 0: Do not stretch table, 1: Stretch table if needed */ -) -{ - DWORD clst; - UINT i; -#if !_FS_READONLY - UINT c; -#endif - - - i = dp->index + 1; - if (!(i & 0xFFFF) || !dp->sect) /* Report EOT when index has reached 65535 */ - return FR_NO_FILE; - - if (!(i % (SS(dp->fs) / SZ_DIRE))) { /* Sector changed? */ - dp->sect++; /* Next sector */ - - if (!dp->clust) { /* Static table */ - if (i >= dp->fs->n_rootdir) /* Report EOT if it reached end of static table */ - return FR_NO_FILE; - } - else { /* Dynamic table */ - if (((i / (SS(dp->fs) / SZ_DIRE)) & (dp->fs->csize - 1)) == 0) { /* Cluster changed? */ - clst = get_fat(dp->fs, dp->clust); /* Get next cluster */ - if (clst <= 1) return FR_INT_ERR; - if (clst == 0xFFFFFFFF) return FR_DISK_ERR; - if (clst >= dp->fs->n_fatent) { /* If it reached end of dynamic table, */ -#if !_FS_READONLY - if (!stretch) return FR_NO_FILE; /* If do not stretch, report EOT */ - clst = create_chain(dp->fs, dp->clust); /* Stretch cluster chain */ - if (clst == 0) return FR_DENIED; /* No free cluster */ - if (clst == 1) return FR_INT_ERR; - if (clst == 0xFFFFFFFF) return FR_DISK_ERR; - /* Clean-up stretched table */ - if (sync_window(dp->fs)) return FR_DISK_ERR;/* Flush disk access window */ - mem_set(dp->fs->win, 0, SS(dp->fs)); /* Clear window buffer */ - dp->fs->winsect = clust2sect(dp->fs, clst); /* Cluster start sector */ - for (c = 0; c < dp->fs->csize; c++) { /* Fill the new cluster with 0 */ - dp->fs->wflag = 1; - if (sync_window(dp->fs)) return FR_DISK_ERR; - dp->fs->winsect++; - } - dp->fs->winsect -= c; /* Rewind window offset */ -#else - if (!stretch) return FR_NO_FILE; /* If do not stretch, report EOT (this is to suppress warning) */ - return FR_NO_FILE; /* Report EOT */ -#endif - } - dp->clust = clst; /* Initialize data for new cluster */ - dp->sect = clust2sect(dp->fs, clst); - } - } - } - - dp->index = (WORD)i; /* Current index */ - dp->dir = dp->fs->win + (i % (SS(dp->fs) / SZ_DIRE)) * SZ_DIRE; /* Current entry in the window */ - - return FR_OK; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Directory handling - Reserve directory entry */ -/*-----------------------------------------------------------------------*/ - -#if !_FS_READONLY -static -FRESULT dir_alloc ( - DIR* dp, /* Pointer to the directory object */ - UINT nent /* Number of contiguous entries to allocate (1-21) */ -) -{ - FRESULT res; - UINT n; - - - res = dir_sdi(dp, 0); - if (res == FR_OK) { - n = 0; - do { - res = move_window(dp->fs, dp->sect); - if (res != FR_OK) break; - if (dp->dir[0] == DDEM || dp->dir[0] == 0) { /* Is it a free entry? */ - if (++n == nent) break; /* A block of contiguous free entries is found */ - } else { - n = 0; /* Not a blank entry. Restart to search */ - } - res = dir_next(dp, 1); /* Next entry with table stretch enabled */ - } while (res == FR_OK); - } - if (res == FR_NO_FILE) res = FR_DENIED; /* No directory entry to allocate */ - return res; -} -#endif - - - - -/*-----------------------------------------------------------------------*/ -/* Directory handling - Load/Store start cluster number */ -/*-----------------------------------------------------------------------*/ - -static -DWORD ld_clust ( - FATFS* fs, /* Pointer to the fs object */ - BYTE* dir /* Pointer to the directory entry */ -) -{ - DWORD cl; - - cl = LD_WORD(dir + DIR_FstClusLO); - if (fs->fs_type == FS_FAT32) - cl |= (DWORD)LD_WORD(dir + DIR_FstClusHI) << 16; - - return cl; -} - - -#if !_FS_READONLY -static -void st_clust ( - BYTE* dir, /* Pointer to the directory entry */ - DWORD cl /* Value to be set */ -) -{ - ST_WORD(dir + DIR_FstClusLO, cl); - ST_WORD(dir + DIR_FstClusHI, cl >> 16); -} -#endif - - - - -/*-----------------------------------------------------------------------*/ -/* LFN handling - Test/Pick/Fit an LFN segment from/to directory entry */ -/*-----------------------------------------------------------------------*/ -#if _USE_LFN -static -const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30}; /* Offset of LFN characters in the directory entry */ - - -static -int cmp_lfn ( /* 1:Matched, 0:Not matched */ - WCHAR* lfnbuf, /* Pointer to the LFN to be compared */ - BYTE* dir /* Pointer to the directory entry containing a part of LFN */ -) -{ - UINT i, s; - WCHAR wc, uc; - - - i = ((dir[LDIR_Ord] & ~LLEF) - 1) * 13; /* Get offset in the LFN buffer */ - s = 0; wc = 1; - do { - uc = LD_WORD(dir + LfnOfs[s]); /* Pick an LFN character from the entry */ - if (wc) { /* Last character has not been processed */ - wc = ff_wtoupper(uc); /* Convert it to upper case */ - if (i >= _MAX_LFN || wc != ff_wtoupper(lfnbuf[i++])) /* Compare it */ - return 0; /* Not matched */ - } else { - if (uc != 0xFFFF) return 0; /* Check filler */ - } - } while (++s < 13); /* Repeat until all characters in the entry are checked */ - - if ((dir[LDIR_Ord] & LLEF) && wc && lfnbuf[i]) /* Last segment matched but different length */ - return 0; - - return 1; /* The part of LFN matched */ -} - - - -static -int pick_lfn ( /* 1:Succeeded, 0:Buffer overflow */ - WCHAR* lfnbuf, /* Pointer to the Unicode-LFN buffer */ - BYTE* dir /* Pointer to the directory entry */ -) -{ - UINT i, s; - WCHAR wc, uc; - - - i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */ - - s = 0; wc = 1; - do { - uc = LD_WORD(dir + LfnOfs[s]); /* Pick an LFN character from the entry */ - if (wc) { /* Last character has not been processed */ - if (i >= _MAX_LFN) return 0; /* Buffer overflow? */ - lfnbuf[i++] = wc = uc; /* Store it */ - } else { - if (uc != 0xFFFF) return 0; /* Check filler */ - } - } while (++s < 13); /* Read all character in the entry */ - - if (dir[LDIR_Ord] & LLEF) { /* Put terminator if it is the last LFN part */ - if (i >= _MAX_LFN) return 0; /* Buffer overflow? */ - lfnbuf[i] = 0; - } - - return 1; -} - - -#if !_FS_READONLY -static -void fit_lfn ( - const WCHAR* lfnbuf, /* Pointer to the LFN buffer */ - BYTE* dir, /* Pointer to the directory entry */ - BYTE ord, /* LFN order (1-20) */ - BYTE sum /* SFN sum */ -) -{ - UINT i, s; - WCHAR wc; - - - dir[LDIR_Chksum] = sum; /* Set check sum */ - dir[LDIR_Attr] = AM_LFN; /* Set attribute. LFN entry */ - dir[LDIR_Type] = 0; - ST_WORD(dir + LDIR_FstClusLO, 0); - - i = (ord - 1) * 13; /* Get offset in the LFN buffer */ - s = wc = 0; - do { - if (wc != 0xFFFF) wc = lfnbuf[i++]; /* Get an effective character */ - ST_WORD(dir+LfnOfs[s], wc); /* Put it */ - if (!wc) wc = 0xFFFF; /* Padding characters following last character */ - } while (++s < 13); - if (wc == 0xFFFF || !lfnbuf[i]) ord |= LLEF; /* Bottom LFN part is the start of LFN sequence */ - dir[LDIR_Ord] = ord; /* Set the LFN order */ -} - -#endif -#endif - - - - -/*-----------------------------------------------------------------------*/ -/* Create numbered name */ -/*-----------------------------------------------------------------------*/ -#if _USE_LFN -static -void gen_numname ( - BYTE* dst, /* Pointer to the buffer to store numbered SFN */ - const BYTE* src, /* Pointer to SFN */ - const WCHAR* lfn, /* Pointer to LFN */ - UINT seq /* Sequence number */ -) -{ - BYTE ns[8], c; - UINT i, j; - WCHAR wc; - DWORD sr; - - - mem_cpy(dst, src, 11); - - if (seq > 5) { /* On many collisions, generate a hash number instead of sequential number */ - sr = seq; - while (*lfn) { /* Create a CRC */ - wc = *lfn++; - for (i = 0; i < 16; i++) { - sr = (sr << 1) + (wc & 1); - wc >>= 1; - if (sr & 0x10000) sr ^= 0x11021; - } - } - seq = (UINT)sr; - } - - /* itoa (hexdecimal) */ - i = 7; - do { - c = (seq % 16) + '0'; - if (c > '9') c += 7; - ns[i--] = c; - seq /= 16; - } while (seq); - ns[i] = '~'; - - /* Append the number */ - for (j = 0; j < i && dst[j] != ' '; j++) { - if (IsDBCS1(dst[j])) { - if (j == i - 1) break; - j++; - } - } - do { - dst[j++] = (i < 8) ? ns[i++] : ' '; - } while (j < 8); -} -#endif - - - - -/*-----------------------------------------------------------------------*/ -/* Calculate sum of an SFN */ -/*-----------------------------------------------------------------------*/ -#if _USE_LFN -static -BYTE sum_sfn ( - const BYTE* dir /* Pointer to the SFN entry */ -) -{ - BYTE sum = 0; - UINT n = 11; - - do sum = (sum >> 1) + (sum << 7) + *dir++; while (--n); - return sum; -} -#endif - - - - -/*-----------------------------------------------------------------------*/ -/* Directory handling - Find an object in the directory */ -/*-----------------------------------------------------------------------*/ - -static -FRESULT dir_find ( - DIR* dp /* Pointer to the directory object linked to the file name */ -) -{ - FRESULT res; - BYTE c, *dir; -#if _USE_LFN - BYTE a, ord, sum; -#endif - - res = dir_sdi(dp, 0); /* Rewind directory object */ - if (res != FR_OK) return res; - -#if _USE_LFN - ord = sum = 0xFF; dp->lfn_idx = 0xFFFF; /* Reset LFN sequence */ -#endif - do { - res = move_window(dp->fs, dp->sect); - if (res != FR_OK) break; - dir = dp->dir; /* Ptr to the directory entry of current index */ - c = dir[DIR_Name]; - if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ -#if _USE_LFN /* LFN configuration */ - a = dir[DIR_Attr] & AM_MASK; - if (c == DDEM || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */ - ord = 0xFF; dp->lfn_idx = 0xFFFF; /* Reset LFN sequence */ - } else { - if (a == AM_LFN) { /* An LFN entry is found */ - if (dp->lfn) { - if (c & LLEF) { /* Is it start of LFN sequence? */ - sum = dir[LDIR_Chksum]; - c &= ~LLEF; ord = c; /* LFN start order */ - dp->lfn_idx = dp->index; /* Start index of LFN */ - } - /* Check validity of the LFN entry and compare it with given name */ - ord = (c == ord && sum == dir[LDIR_Chksum] && cmp_lfn(dp->lfn, dir)) ? ord - 1 : 0xFF; - } - } else { /* An SFN entry is found */ - if (!ord && sum == sum_sfn(dir)) break; /* LFN matched? */ - if (!(dp->fn[NSFLAG] & NS_LOSS) && !mem_cmp(dir, dp->fn, 11)) break; /* SFN matched? */ - ord = 0xFF; dp->lfn_idx = 0xFFFF; /* Reset LFN sequence */ - } - } -#else /* Non LFN configuration */ - if (!(dir[DIR_Attr] & AM_VOL) && !mem_cmp(dir, dp->fn, 11)) /* Is it a valid entry? */ - break; -#endif - res = dir_next(dp, 0); /* Next entry */ - } while (res == FR_OK); - - return res; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Read an object from the directory */ -/*-----------------------------------------------------------------------*/ -#if _FS_MINIMIZE <= 1 || _USE_LABEL || _FS_RPATH >= 2 -static -FRESULT dir_read ( - DIR* dp, /* Pointer to the directory object */ - int vol /* Filtered by 0:file/directory or 1:volume label */ -) -{ - FRESULT res; - BYTE a, c, *dir; -#if _USE_LFN - BYTE ord = 0xFF, sum = 0xFF; -#endif - - res = FR_NO_FILE; - while (dp->sect) { - res = move_window(dp->fs, dp->sect); - if (res != FR_OK) break; - dir = dp->dir; /* Ptr to the directory entry of current index */ - c = dir[DIR_Name]; - if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ - a = dir[DIR_Attr] & AM_MASK; -#if _USE_LFN /* LFN configuration */ - if (c == DDEM || (!_FS_RPATH && c == '.') || (int)((a & ~AM_ARC) == AM_VOL) != vol) { /* An entry without valid data */ - ord = 0xFF; - } else { - if (a == AM_LFN) { /* An LFN entry is found */ - if (c & LLEF) { /* Is it start of LFN sequence? */ - sum = dir[LDIR_Chksum]; - c &= ~LLEF; ord = c; - dp->lfn_idx = dp->index; - } - /* Check LFN validity and capture it */ - ord = (c == ord && sum == dir[LDIR_Chksum] && pick_lfn(dp->lfn, dir)) ? ord - 1 : 0xFF; - } else { /* An SFN entry is found */ - if (ord || sum != sum_sfn(dir)) /* Is there a valid LFN? */ - dp->lfn_idx = 0xFFFF; /* It has no LFN. */ - break; - } - } -#else /* Non LFN configuration */ - if (c != DDEM && (_FS_RPATH || c != '.') && a != AM_LFN && (int)((a & ~AM_ARC) == AM_VOL) == vol) /* Is it a valid entry? */ - break; -#endif - res = dir_next(dp, 0); /* Next entry */ - if (res != FR_OK) break; - } - - if (res != FR_OK) dp->sect = 0; - - return res; -} -#endif /* _FS_MINIMIZE <= 1 || _USE_LABEL || _FS_RPATH >= 2 */ - - - - -/*-----------------------------------------------------------------------*/ -/* Register an object to the directory */ -/*-----------------------------------------------------------------------*/ -#if !_FS_READONLY -static -FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many SFN collision, FR_DISK_ERR:Disk error */ - DIR* dp /* Target directory with object name to be created */ -) -{ - FRESULT res; -#if _USE_LFN /* LFN configuration */ - UINT n, nent; - BYTE sn[12], *fn, sum; - WCHAR *lfn; - - - fn = dp->fn; lfn = dp->lfn; - mem_cpy(sn, fn, 12); - - if (_FS_RPATH && (sn[NSFLAG] & NS_DOT)) /* Cannot create dot entry */ - return FR_INVALID_NAME; - - if (sn[NSFLAG] & NS_LOSS) { /* When LFN is out of 8.3 format, generate a numbered name */ - fn[NSFLAG] = 0; dp->lfn = 0; /* Find only SFN */ - for (n = 1; n < 100; n++) { - gen_numname(fn, sn, lfn, n); /* Generate a numbered name */ - res = dir_find(dp); /* Check if the name collides with existing SFN */ - if (res != FR_OK) break; - } - if (n == 100) return FR_DENIED; /* Abort if too many collisions */ - if (res != FR_NO_FILE) return res; /* Abort if the result is other than 'not collided' */ - fn[NSFLAG] = sn[NSFLAG]; dp->lfn = lfn; - } - - if (sn[NSFLAG] & NS_LFN) { /* When LFN is to be created, allocate entries for an SFN + LFNs. */ - for (n = 0; lfn[n]; n++) ; - nent = (n + 25) / 13; - } else { /* Otherwise allocate an entry for an SFN */ - nent = 1; - } - res = dir_alloc(dp, nent); /* Allocate entries */ - - if (res == FR_OK && --nent) { /* Set LFN entry if needed */ - res = dir_sdi(dp, dp->index - nent); - if (res == FR_OK) { - sum = sum_sfn(dp->fn); /* Sum value of the SFN tied to the LFN */ - do { /* Store LFN entries in bottom first */ - res = move_window(dp->fs, dp->sect); - if (res != FR_OK) break; - fit_lfn(dp->lfn, dp->dir, (BYTE)nent, sum); - dp->fs->wflag = 1; - res = dir_next(dp, 0); /* Next entry */ - } while (res == FR_OK && --nent); - } - } -#else /* Non LFN configuration */ - res = dir_alloc(dp, 1); /* Allocate an entry for SFN */ -#endif - - if (res == FR_OK) { /* Set SFN entry */ - res = move_window(dp->fs, dp->sect); - if (res == FR_OK) { - mem_set(dp->dir, 0, SZ_DIRE); /* Clean the entry */ - mem_cpy(dp->dir, dp->fn, 11); /* Put SFN */ -#if _USE_LFN - dp->dir[DIR_NTres] = dp->fn[NSFLAG] & (NS_BODY | NS_EXT); /* Put NT flag */ -#endif - dp->fs->wflag = 1; - } - } - - return res; -} -#endif /* !_FS_READONLY */ - - - - -/*-----------------------------------------------------------------------*/ -/* Remove an object from the directory */ -/*-----------------------------------------------------------------------*/ -#if !_FS_READONLY && !_FS_MINIMIZE -static -FRESULT dir_remove ( /* FR_OK: Successful, FR_DISK_ERR: A disk error */ - DIR* dp /* Directory object pointing the entry to be removed */ -) -{ - FRESULT res; -#if _USE_LFN /* LFN configuration */ - UINT i; - - i = dp->index; /* SFN index */ - res = dir_sdi(dp, (dp->lfn_idx == 0xFFFF) ? i : dp->lfn_idx); /* Goto the SFN or top of the LFN entries */ - if (res == FR_OK) { - do { - res = move_window(dp->fs, dp->sect); - if (res != FR_OK) break; - mem_set(dp->dir, 0, SZ_DIRE); /* Clear and mark the entry "deleted" */ - *dp->dir = DDEM; - dp->fs->wflag = 1; - if (dp->index >= i) break; /* When reached SFN, all entries of the object has been deleted. */ - res = dir_next(dp, 0); /* Next entry */ - } while (res == FR_OK); - if (res == FR_NO_FILE) res = FR_INT_ERR; - } - -#else /* Non LFN configuration */ - res = dir_sdi(dp, dp->index); - if (res == FR_OK) { - res = move_window(dp->fs, dp->sect); - if (res == FR_OK) { - mem_set(dp->dir, 0, SZ_DIRE); /* Clear and mark the entry "deleted" */ - *dp->dir = DDEM; - dp->fs->wflag = 1; - } - } -#endif - - return res; -} -#endif /* !_FS_READONLY */ - - - - -/*-----------------------------------------------------------------------*/ -/* Get file information from directory entry */ -/*-----------------------------------------------------------------------*/ -#if _FS_MINIMIZE <= 1 || _FS_RPATH >= 2 -static -void get_fileinfo ( /* No return code */ - DIR* dp, /* Pointer to the directory object */ - FILINFO* fno /* Pointer to the file information to be filled */ -) -{ - UINT i; - TCHAR *p, c; - BYTE *dir; -#if _USE_LFN - WCHAR w, *lfn; -#endif - - p = fno->fname; - if (dp->sect) { /* Get SFN */ - dir = dp->dir; - i = 0; - while (i < 11) { /* Copy name body and extension */ - c = (TCHAR)dir[i++]; - if (c == ' ') continue; /* Skip padding spaces */ - if (c == RDDEM) c = (TCHAR)DDEM; /* Restore replaced DDEM character */ - if (i == 9) *p++ = '.'; /* Insert a . if extension is exist */ -#if _USE_LFN - if (IsUpper(c) && (dir[DIR_NTres] & (i >= 9 ? NS_EXT : NS_BODY))) - c += 0x20; /* To lower */ -#if _LFN_UNICODE - if (IsDBCS1(c) && i != 8 && i != 11 && IsDBCS2(dir[i])) - c = c << 8 | dir[i++]; - c = ff_convert(c, 1); /* OEM -> Unicode */ - if (!c) c = '?'; -#endif -#endif - *p++ = c; - } - fno->fattrib = dir[DIR_Attr]; /* Attribute */ - fno->fsize = LD_DWORD(dir + DIR_FileSize); /* Size */ - fno->fdate = LD_WORD(dir + DIR_WrtDate); /* Date */ - fno->ftime = LD_WORD(dir + DIR_WrtTime); /* Time */ - } - *p = 0; /* Terminate SFN string by a \0 */ - -#if _USE_LFN - if (fno->lfname) { - i = 0; p = fno->lfname; - if (dp->sect && fno->lfsize && dp->lfn_idx != 0xFFFF) { /* Get LFN if available */ - lfn = dp->lfn; - while ((w = *lfn++) != 0) { /* Get an LFN character */ -#if !_LFN_UNICODE - w = ff_convert(w, 0); /* Unicode -> OEM */ - if (!w) { i = 0; break; } /* No LFN if it could not be converted */ - if (_DF1S && w >= 0x100) /* Put 1st byte if it is a DBC (always false on SBCS cfg) */ - p[i++] = (TCHAR)(w >> 8); -#endif - if (i >= fno->lfsize - 1) { i = 0; break; } /* No LFN if buffer overflow */ - p[i++] = (TCHAR)w; - } - } - p[i] = 0; /* Terminate LFN string by a \0 */ - } -#endif -} -#endif /* _FS_MINIMIZE <= 1 || _FS_RPATH >= 2 */ - - - - -/*-----------------------------------------------------------------------*/ -/* Pattern matching */ -/*-----------------------------------------------------------------------*/ -#if _USE_FIND && _FS_MINIMIZE <= 1 -static -WCHAR get_achar ( /* Get a character and advances ptr 1 or 2 */ - const TCHAR** ptr /* Pointer to pointer to the SBCS/DBCS/Unicode string */ -) -{ - WCHAR chr; - -#if !_LFN_UNICODE - chr = (BYTE)*(*ptr)++; /* Get a byte */ - if (IsLower(chr)) chr -= 0x20; /* To upper ASCII char */ - if (IsDBCS1(chr) && IsDBCS2(**ptr)) /* Get DBC 2nd byte if needed */ - chr = chr << 8 | (BYTE)*(*ptr)++; -#ifdef _EXCVT - if (chr >= 0x80) chr = ExCvt[chr - 0x80]; /* To upper SBCS extended char */ -#endif -#else - chr = ff_wtoupper(*(*ptr)++); /* Get a word and to upper */ -#endif - return chr; -} - - -static -int pattern_matching ( /* Return value: 0:mismatched, 1:matched */ - const TCHAR* pat, /* Matching pattern */ - const TCHAR* nam, /* String to be tested */ - int skip, /* Number of pre-skip chars (number of ?s) */ - int inf /* Infinite search (* specified) */ -) -{ - const TCHAR *pp, *np; - WCHAR pc, nc; - int nm, nx; - - - while (skip--) { /* Pre-skip name chars */ - if (!get_achar(&nam)) return 0; /* Branch mismatched if less name chars */ - } - if (!*pat && inf) return 1; /* (short circuit) */ - - do { - pp = pat; np = nam; /* Top of pattern and name to match */ - for (;;) { - if (*pp == '?' || *pp == '*') { /* Wildcard? */ - nm = nx = 0; - do { /* Analyze the wildcard chars */ - if (*pp++ == '?') nm++; else nx = 1; - } while (*pp == '?' || *pp == '*'); - if (pattern_matching(pp, np, nm, nx)) return 1; /* Test new branch (recurs upto number of wildcard blocks in the pattern) */ - nc = *np; break; /* Branch mismatched */ - } - pc = get_achar(&pp); /* Get a pattern char */ - nc = get_achar(&np); /* Get a name char */ - if (pc != nc) break; /* Branch mismatched? */ - if (!pc) return 1; /* Branch matched? (matched at end of both strings) */ - } - get_achar(&nam); /* nam++ */ - } while (inf && nc); /* Retry until end of name if infinite search is specified */ - - return 0; -} -#endif /* _USE_FIND && _FS_MINIMIZE <= 1 */ - - - - -/*-----------------------------------------------------------------------*/ -/* Pick a segment and create the object name in directory form */ -/*-----------------------------------------------------------------------*/ - -static -FRESULT create_name ( - DIR* dp, /* Pointer to the directory object */ - const TCHAR** path /* Pointer to pointer to the segment in the path string */ -) -{ -#if _USE_LFN /* LFN configuration */ - BYTE b, cf; - WCHAR w, *lfn; - UINT i, ni, si, di; - const TCHAR *p; - - /* Create LFN in Unicode */ - for (p = *path; *p == '/' || *p == '\\'; p++) ; /* Strip duplicated separator */ - lfn = dp->lfn; - si = di = 0; - for (;;) { - w = p[si++]; /* Get a character */ - if (w < ' ' || w == '/' || w == '\\') break; /* Break on end of segment */ - if (di >= _MAX_LFN) /* Reject too long name */ - return FR_INVALID_NAME; -#if !_LFN_UNICODE - w &= 0xFF; - if (IsDBCS1(w)) { /* Check if it is a DBC 1st byte (always false on SBCS cfg) */ - b = (BYTE)p[si++]; /* Get 2nd byte */ - w = (w << 8) + b; /* Create a DBC */ - if (!IsDBCS2(b)) - return FR_INVALID_NAME; /* Reject invalid sequence */ - } - w = ff_convert(w, 1); /* Convert ANSI/OEM to Unicode */ - if (!w) return FR_INVALID_NAME; /* Reject invalid code */ -#endif - if (w < 0x80 && chk_chr("\"*:<>\?|\x7F", w)) /* Reject illegal characters for LFN */ - return FR_INVALID_NAME; - lfn[di++] = w; /* Store the Unicode character */ - } - *path = &p[si]; /* Return pointer to the next segment */ - cf = (w < ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */ -#if _FS_RPATH - if ((di == 1 && lfn[di - 1] == '.') || /* Is this a dot entry? */ - (di == 2 && lfn[di - 1] == '.' && lfn[di - 2] == '.')) { - lfn[di] = 0; - for (i = 0; i < 11; i++) - dp->fn[i] = (i < di) ? '.' : ' '; - dp->fn[i] = cf | NS_DOT; /* This is a dot entry */ - return FR_OK; - } -#endif - while (di) { /* Strip trailing spaces and dots */ - w = lfn[di - 1]; - if (w != ' ' && w != '.') break; - di--; - } - if (!di) return FR_INVALID_NAME; /* Reject nul string */ - - lfn[di] = 0; /* LFN is created */ - - /* Create SFN in directory form */ - mem_set(dp->fn, ' ', 11); - for (si = 0; lfn[si] == ' ' || lfn[si] == '.'; si++) ; /* Strip leading spaces and dots */ - if (si) cf |= NS_LOSS | NS_LFN; - while (di && lfn[di - 1] != '.') di--; /* Find extension (di<=si: no extension) */ - - b = i = 0; ni = 8; - for (;;) { - w = lfn[si++]; /* Get an LFN character */ - if (!w) break; /* Break on end of the LFN */ - if (w == ' ' || (w == '.' && si != di)) { /* Remove spaces and dots */ - cf |= NS_LOSS | NS_LFN; continue; - } - - if (i >= ni || si == di) { /* Extension or end of SFN */ - if (ni == 11) { /* Long extension */ - cf |= NS_LOSS | NS_LFN; break; - } - if (si != di) cf |= NS_LOSS | NS_LFN; /* Out of 8.3 format */ - if (si > di) break; /* No extension */ - si = di; i = 8; ni = 11; /* Enter extension section */ - b <<= 2; continue; - } - - if (w >= 0x80) { /* Non ASCII character */ -#ifdef _EXCVT - w = ff_convert(w, 0); /* Unicode -> OEM code */ - if (w) w = ExCvt[w - 0x80]; /* Convert extended character to upper (SBCS) */ -#else - w = ff_convert(ff_wtoupper(w), 0); /* Upper converted Unicode -> OEM code */ -#endif - cf |= NS_LFN; /* Force create LFN entry */ - } - - if (_DF1S && w >= 0x100) { /* DBC (always false at SBCS cfg) */ - if (i >= ni - 1) { - cf |= NS_LOSS | NS_LFN; i = ni; continue; - } - dp->fn[i++] = (BYTE)(w >> 8); - } else { /* SBC */ - if (!w || chk_chr("+,;=[]", w)) { /* Replace illegal characters for SFN */ - w = '_'; cf |= NS_LOSS | NS_LFN;/* Lossy conversion */ - } else { - if (IsUpper(w)) { /* ASCII large capital */ - b |= 2; - } else { - if (IsLower(w)) { /* ASCII small capital */ - b |= 1; w -= 0x20; - } - } - } - } - dp->fn[i++] = (BYTE)w; - } - - if (dp->fn[0] == DDEM) dp->fn[0] = RDDEM; /* If the first character collides with deleted mark, replace it with RDDEM */ - - if (ni == 8) b <<= 2; - if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03) /* Create LFN entry when there are composite capitals */ - cf |= NS_LFN; - if (!(cf & NS_LFN)) { /* When LFN is in 8.3 format without extended character, NT flags are created */ - if ((b & 0x03) == 0x01) cf |= NS_EXT; /* NT flag (Extension has only small capital) */ - if ((b & 0x0C) == 0x04) cf |= NS_BODY; /* NT flag (Filename has only small capital) */ - } - - dp->fn[NSFLAG] = cf; /* SFN is created */ - - return FR_OK; - - -#else /* Non-LFN configuration */ - BYTE b, c, d, *sfn; - UINT ni, si, i; - const char *p; - - /* Create file name in directory form */ - for (p = *path; *p == '/' || *p == '\\'; p++) ; /* Strip duplicated separator */ - sfn = dp->fn; - mem_set(sfn, ' ', 11); - si = i = b = 0; ni = 8; -#if _FS_RPATH - if (p[si] == '.') { /* Is this a dot entry? */ - for (;;) { - c = (BYTE)p[si++]; - if (c != '.' || si >= 3) break; - sfn[i++] = c; - } - if (c != '/' && c != '\\' && c > ' ') return FR_INVALID_NAME; - *path = &p[si]; /* Return pointer to the next segment */ - sfn[NSFLAG] = (c <= ' ') ? NS_LAST | NS_DOT : NS_DOT; /* Set last segment flag if end of path */ - return FR_OK; - } -#endif - for (;;) { - c = (BYTE)p[si++]; - if (c <= ' ' || c == '/' || c == '\\') break; /* Break on end of segment */ - if (c == '.' || i >= ni) { - if (ni != 8 || c != '.') return FR_INVALID_NAME; - i = 8; ni = 11; - b <<= 2; continue; - } - if (c >= 0x80) { /* Extended character? */ - b |= 3; /* Eliminate NT flag */ -#ifdef _EXCVT - c = ExCvt[c - 0x80]; /* To upper extended characters (SBCS cfg) */ -#else -#if !_DF1S - return FR_INVALID_NAME; /* Reject extended characters (ASCII cfg) */ -#endif -#endif - } - if (IsDBCS1(c)) { /* Check if it is a DBC 1st byte (always false on SBCS cfg) */ - d = (BYTE)p[si++]; /* Get 2nd byte */ - if (!IsDBCS2(d) || i >= ni - 1) /* Reject invalid DBC */ - return FR_INVALID_NAME; - sfn[i++] = c; - sfn[i++] = d; - } else { /* SBC */ - if (chk_chr("\"*+,:;<=>\?[]|\x7F", c)) /* Reject illegal chrs for SFN */ - return FR_INVALID_NAME; - if (IsUpper(c)) { /* ASCII large capital? */ - b |= 2; - } else { - if (IsLower(c)) { /* ASCII small capital? */ - b |= 1; c -= 0x20; - } - } - sfn[i++] = c; - } - } - *path = &p[si]; /* Return pointer to the next segment */ - c = (c <= ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */ - - if (!i) return FR_INVALID_NAME; /* Reject nul string */ - if (sfn[0] == DDEM) sfn[0] = RDDEM; /* When first character collides with DDEM, replace it with RDDEM */ - - if (ni == 8) b <<= 2; - if ((b & 0x03) == 0x01) c |= NS_EXT; /* NT flag (Name extension has only small capital) */ - if ((b & 0x0C) == 0x04) c |= NS_BODY; /* NT flag (Name body has only small capital) */ - - sfn[NSFLAG] = c; /* Store NT flag, File name is created */ - - return FR_OK; -#endif -} - - - - -/*-----------------------------------------------------------------------*/ -/* Follow a file path */ -/*-----------------------------------------------------------------------*/ - -static -FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ - DIR* dp, /* Directory object to return last directory and found object */ - const TCHAR* path /* Full-path string to find a file or directory */ -) -{ - FRESULT res; - BYTE *dir, ns; - - -#if _FS_RPATH - if (*path == '/' || *path == '\\') { /* There is a heading separator */ - path++; dp->sclust = 0; /* Strip it and start from the root directory */ - } else { /* No heading separator */ - dp->sclust = dp->fs->cdir; /* Start from the current directory */ - } -#else - if (*path == '/' || *path == '\\') /* Strip heading separator if exist */ - path++; - dp->sclust = 0; /* Always start from the root directory */ -#endif - - if ((UINT)*path < ' ') { /* Null path name is the origin directory itself */ - res = dir_sdi(dp, 0); - dp->dir = 0; - } else { /* Follow path */ - for (;;) { - res = create_name(dp, &path); /* Get a segment name of the path */ - if (res != FR_OK) break; - res = dir_find(dp); /* Find an object with the sagment name */ - ns = dp->fn[NSFLAG]; - if (res != FR_OK) { /* Failed to find the object */ - if (res == FR_NO_FILE) { /* Object is not found */ - if (_FS_RPATH && (ns & NS_DOT)) { /* If dot entry is not exist, */ - dp->sclust = 0; dp->dir = 0; /* it is the root directory and stay there */ - if (!(ns & NS_LAST)) continue; /* Continue to follow if not last segment */ - res = FR_OK; /* Ended at the root directroy. Function completed. */ - } else { /* Could not find the object */ - if (!(ns & NS_LAST)) res = FR_NO_PATH; /* Adjust error code if not last segment */ - } - } - break; - } - if (ns & NS_LAST) break; /* Last segment matched. Function completed. */ - dir = dp->dir; /* Follow the sub-directory */ - if (!(dir[DIR_Attr] & AM_DIR)) { /* It is not a sub-directory and cannot follow */ - res = FR_NO_PATH; break; - } - dp->sclust = ld_clust(dp->fs, dir); - } - } - - return res; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Get logical drive number from path name */ -/*-----------------------------------------------------------------------*/ - -static -int get_ldnumber ( /* Returns logical drive number (-1:invalid drive) */ - const TCHAR** path /* Pointer to pointer to the path name */ -) -{ - const TCHAR *tp, *tt; - UINT i; - int vol = -1; -#if _STR_VOLUME_ID /* Find string drive id */ - static const char* const str[] = {_VOLUME_STRS}; - const char *sp; - char c; - TCHAR tc; -#endif - - - if (*path) { /* If the pointer is not a null */ - for (tt = *path; (UINT)*tt >= (_USE_LFN ? ' ' : '!') && *tt != ':'; tt++) ; /* Find ':' in the path */ - if (*tt == ':') { /* If a ':' is exist in the path name */ - tp = *path; - i = *tp++ - '0'; - if (i < 10 && tp == tt) { /* Is there a numeric drive id? */ - if (i < _VOLUMES) { /* If a drive id is found, get the value and strip it */ - vol = (int)i; - *path = ++tt; - } - } -#if _STR_VOLUME_ID - else { /* No numeric drive number, find string drive id */ - i = 0; tt++; - do { - sp = str[i]; tp = *path; - do { /* Compare a string drive id with path name */ - c = *sp++; tc = *tp++; - if (IsLower(tc)) tc -= 0x20; - } while (c && (TCHAR)c == tc); - } while ((c || tp != tt) && ++i < _VOLUMES); /* Repeat for each id until pattern match */ - if (i < _VOLUMES) { /* If a drive id is found, get the value and strip it */ - vol = (int)i; - *path = tt; - } - } -#endif - return vol; - } -#if _FS_RPATH && _VOLUMES >= 2 - vol = CurrVol; /* Current drive */ -#else - vol = 0; /* Drive 0 */ -#endif - } - return vol; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Load a sector and check if it is an FAT boot sector */ -/*-----------------------------------------------------------------------*/ - -static -BYTE check_fs ( /* 0:FAT boor sector, 1:Valid boor sector but not FAT, 2:Not a boot sector, 3:Disk error */ - FATFS* fs, /* File system object */ - DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */ -) -{ - fs->wflag = 0; fs->winsect = 0xFFFFFFFF; /* Invaidate window */ - if (move_window(fs, sect) != FR_OK) /* Load boot record */ - return 3; - - if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55) /* Check boot record signature (always placed at offset 510 even if the sector size is >512) */ - return 2; - - if ((LD_DWORD(&fs->win[BS_FilSysType]) & 0xFFFFFF) == 0x544146) /* Check "FAT" string */ - return 0; - if ((LD_DWORD(&fs->win[BS_FilSysType32]) & 0xFFFFFF) == 0x544146) /* Check "FAT" string */ - return 0; - - return 1; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Find logical drive and check if the volume is mounted */ -/*-----------------------------------------------------------------------*/ - -static -FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */ - FATFS** rfs, /* Pointer to pointer to the found file system object */ - const TCHAR** path, /* Pointer to pointer to the path name (drive number) */ - BYTE wmode /* !=0: Check write protection for write access */ -) -{ - BYTE fmt, *pt; - int vol; - DSTATUS stat; - DWORD bsect, fasize, tsect, sysect, nclst, szbfat, br[4]; - WORD nrsv; - FATFS *fs; - UINT i; - - - /* Get logical drive number from the path name */ - *rfs = 0; - vol = get_ldnumber(path); - if (vol < 0) return FR_INVALID_DRIVE; - - /* Check if the file system object is valid or not */ - fs = FatFs[vol]; /* Get pointer to the file system object */ - if (!fs) return FR_NOT_ENABLED; /* Is the file system object available? */ - - ENTER_FF(fs); /* Lock the volume */ - *rfs = fs; /* Return pointer to the file system object */ - - if (fs->fs_type) { /* If the volume has been mounted */ - stat = disk_status(fs->drv); - if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized */ - if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) /* Check write protection if needed */ - return FR_WRITE_PROTECTED; - return FR_OK; /* The file system object is valid */ - } - } - - /* The file system object is not valid. */ - /* Following code attempts to mount the volume. (analyze BPB and initialize the fs object) */ - - fs->fs_type = 0; /* Clear the file system object */ - fs->drv = LD2PD(vol); /* Bind the logical drive and a physical drive */ - stat = disk_initialize(fs->drv); /* Initialize the physical drive */ - if (stat & STA_NOINIT) /* Check if the initialization succeeded */ - return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */ - if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) /* Check disk write protection if needed */ - return FR_WRITE_PROTECTED; -#if _MAX_SS != _MIN_SS /* Get sector size (multiple sector size cfg only) */ - if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK - || SS(fs) < _MIN_SS || SS(fs) > _MAX_SS) return FR_DISK_ERR; -#endif - /* Find an FAT partition on the drive. Supports only generic partitioning, FDISK and SFD. */ - bsect = 0; - fmt = check_fs(fs, bsect); /* Load sector 0 and check if it is an FAT boot sector as SFD */ - if (fmt == 1 || (!fmt && (LD2PT(vol)))) { /* Not an FAT boot sector or forced partition number */ - for (i = 0; i < 4; i++) { /* Get partition offset */ - pt = fs->win + MBR_Table + i * SZ_PTE; - br[i] = pt[4] ? LD_DWORD(&pt[8]) : 0; - } - i = LD2PT(vol); /* Partition number: 0:auto, 1-4:forced */ - if (i) i--; - do { /* Find an FAT volume */ - bsect = br[i]; - fmt = bsect ? check_fs(fs, bsect) : 2; /* Check the partition */ - } while (!LD2PT(vol) && fmt && ++i < 4); - } - if (fmt == 3) return FR_DISK_ERR; /* An error occured in the disk I/O layer */ - if (fmt) return FR_NO_FILESYSTEM; /* No FAT volume is found */ - - /* An FAT volume is found. Following code initializes the file system object */ - - if (LD_WORD(fs->win + BPB_BytsPerSec) != SS(fs)) /* (BPB_BytsPerSec must be equal to the physical sector size) */ - return FR_NO_FILESYSTEM; - - fasize = LD_WORD(fs->win + BPB_FATSz16); /* Number of sectors per FAT */ - if (!fasize) fasize = LD_DWORD(fs->win + BPB_FATSz32); - fs->fsize = fasize; - - fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FAT copies */ - if (fs->n_fats != 1 && fs->n_fats != 2) /* (Must be 1 or 2) */ - return FR_NO_FILESYSTEM; - fasize *= fs->n_fats; /* Number of sectors for FAT area */ - - fs->csize = fs->win[BPB_SecPerClus]; /* Number of sectors per cluster */ - if (!fs->csize || (fs->csize & (fs->csize - 1))) /* (Must be power of 2) */ - return FR_NO_FILESYSTEM; - - fs->n_rootdir = LD_WORD(fs->win + BPB_RootEntCnt); /* Number of root directory entries */ - if (fs->n_rootdir % (SS(fs) / SZ_DIRE)) /* (Must be sector aligned) */ - return FR_NO_FILESYSTEM; - - tsect = LD_WORD(fs->win + BPB_TotSec16); /* Number of sectors on the volume */ - if (!tsect) tsect = LD_DWORD(fs->win + BPB_TotSec32); - - nrsv = LD_WORD(fs->win + BPB_RsvdSecCnt); /* Number of reserved sectors */ - if (!nrsv) return FR_NO_FILESYSTEM; /* (Must not be 0) */ - - /* Determine the FAT sub type */ - sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZ_DIRE); /* RSV + FAT + DIR */ - if (tsect < sysect) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ - nclst = (tsect - sysect) / fs->csize; /* Number of clusters */ - if (!nclst) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ - fmt = FS_FAT12; - if (nclst >= MIN_FAT16) fmt = FS_FAT16; - if (nclst >= MIN_FAT32) fmt = FS_FAT32; - - /* Boundaries and Limits */ - fs->n_fatent = nclst + 2; /* Number of FAT entries */ - fs->volbase = bsect; /* Volume start sector */ - fs->fatbase = bsect + nrsv; /* FAT start sector */ - fs->database = bsect + sysect; /* Data start sector */ - if (fmt == FS_FAT32) { - if (fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */ - fs->dirbase = LD_DWORD(fs->win + BPB_RootClus); /* Root directory start cluster */ - szbfat = fs->n_fatent * 4; /* (Needed FAT size) */ - } else { - if (!fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */ - fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */ - szbfat = (fmt == FS_FAT16) ? /* (Needed FAT size) */ - fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1); - } - if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) /* (BPB_FATSz must not be less than the size needed) */ - return FR_NO_FILESYSTEM; - -#if !_FS_READONLY - /* Initialize cluster allocation information */ - fs->last_clust = fs->free_clust = 0xFFFFFFFF; - - /* Get fsinfo if available */ - fs->fsi_flag = 0x80; -#if (_FS_NOFSINFO & 3) != 3 - if (fmt == FS_FAT32 /* Enable FSINFO only if FAT32 and BPB_FSInfo is 1 */ - && LD_WORD(fs->win + BPB_FSInfo) == 1 - && move_window(fs, bsect + 1) == FR_OK) - { - fs->fsi_flag = 0; - if (LD_WORD(fs->win + BS_55AA) == 0xAA55 /* Load FSINFO data if available */ - && LD_DWORD(fs->win + FSI_LeadSig) == 0x41615252 - && LD_DWORD(fs->win + FSI_StrucSig) == 0x61417272) - { -#if (_FS_NOFSINFO & 1) == 0 - fs->free_clust = LD_DWORD(fs->win + FSI_Free_Count); -#endif -#if (_FS_NOFSINFO & 2) == 0 - fs->last_clust = LD_DWORD(fs->win + FSI_Nxt_Free); -#endif - } - } -#endif -#endif - fs->fs_type = fmt; /* FAT sub-type */ - fs->id = ++Fsid; /* File system mount ID */ -#if _FS_RPATH - fs->cdir = 0; /* Set current directory to root */ -#endif -#if _FS_LOCK /* Clear file lock semaphores */ - clear_lock(fs); -#endif - - return FR_OK; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Check if the file/directory object is valid or not */ -/*-----------------------------------------------------------------------*/ - -static -FRESULT validate ( /* FR_OK(0): The object is valid, !=0: Invalid */ - void* obj /* Pointer to the object FIL/DIR to check validity */ -) -{ - FIL *fil = (FIL*)obj; /* Assuming offset of .fs and .id in the FIL/DIR structure is identical */ - - - if (!fil || !fil->fs || !fil->fs->fs_type || fil->fs->id != fil->id) - return FR_INVALID_OBJECT; - - ENTER_FF(fil->fs); /* Lock file system */ - - if (disk_status(fil->fs->drv) & STA_NOINIT) - return FR_NOT_READY; - - return FR_OK; -} - - - - -/*-------------------------------------------------------------------------- - - Public Functions - ---------------------------------------------------------------------------*/ - - - -/*-----------------------------------------------------------------------*/ -/* Mount/Unmount a Logical Drive */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_mount ( - FATFS* fs, /* Pointer to the file system object (NULL:unmount)*/ - const TCHAR* path, /* Logical drive number to be mounted/unmounted */ - BYTE opt /* 0:Do not mount (delayed mount), 1:Mount immediately */ -) -{ - FATFS *cfs; - int vol; - FRESULT res; - const TCHAR *rp = path; - - - vol = get_ldnumber(&rp); - if (vol < 0) return FR_INVALID_DRIVE; - cfs = FatFs[vol]; /* Pointer to fs object */ - - if (cfs) { -#if _FS_LOCK - clear_lock(cfs); -#endif -#if _FS_REENTRANT /* Discard sync object of the current volume */ - if (!ff_del_syncobj(cfs->sobj)) return FR_INT_ERR; -#endif - cfs->fs_type = 0; /* Clear old fs object */ - } - - if (fs) { - fs->fs_type = 0; /* Clear new fs object */ -#if _FS_REENTRANT /* Create sync object for the new volume */ - if (!ff_cre_syncobj((BYTE)vol, &fs->sobj)) return FR_INT_ERR; -#endif - } - FatFs[vol] = fs; /* Register new fs object */ - - if (!fs || opt != 1) return FR_OK; /* Do not mount now, it will be mounted later */ - - res = find_volume(&fs, &path, 0); /* Force mounted the volume */ - LEAVE_FF(fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Open or Create a File */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_open ( - FIL* fp, /* Pointer to the blank file object */ - const TCHAR* path, /* Pointer to the file name */ - BYTE mode /* Access mode and file open mode flags */ -) -{ - FRESULT res; - DIR dj; - BYTE *dir; - DEFINE_NAMEBUF; -#if !_FS_READONLY - DWORD dw, cl; -#endif - - - if (!fp) return FR_INVALID_OBJECT; - fp->fs = 0; /* Clear file object */ - - /* Get logical drive number */ -#if !_FS_READONLY - mode &= FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW; - res = find_volume(&dj.fs, &path, (BYTE)(mode & ~FA_READ)); -#else - mode &= FA_READ; - res = find_volume(&dj.fs, &path, 0); -#endif - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the file path */ - dir = dj.dir; -#if !_FS_READONLY /* R/W configuration */ - if (res == FR_OK) { - if (!dir) /* Default directory itself */ - res = FR_INVALID_NAME; -#if _FS_LOCK - else - res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0); -#endif - } - /* Create or Open a file */ - if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) { - if (res != FR_OK) { /* No file, create new */ - if (res == FR_NO_FILE) /* There is no file to open, create a new entry */ -#if _FS_LOCK - res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES; -#else - res = dir_register(&dj); -#endif - mode |= FA_CREATE_ALWAYS; /* File is created */ - dir = dj.dir; /* New entry */ - } - else { /* Any object is already existing */ - if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) { /* Cannot overwrite it (R/O or DIR) */ - res = FR_DENIED; - } else { - if (mode & FA_CREATE_NEW) /* Cannot create as new file */ - res = FR_EXIST; - } - } - if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate it if overwrite mode */ - dw = GET_FATTIME(); /* Created time */ - ST_DWORD(dir + DIR_CrtTime, dw); - dir[DIR_Attr] = 0; /* Reset attribute */ - ST_DWORD(dir + DIR_FileSize, 0);/* size = 0 */ - cl = ld_clust(dj.fs, dir); /* Get start cluster */ - st_clust(dir, 0); /* cluster = 0 */ - dj.fs->wflag = 1; - if (cl) { /* Remove the cluster chain if exist */ - dw = dj.fs->winsect; - res = remove_chain(dj.fs, cl); - if (res == FR_OK) { - dj.fs->last_clust = cl - 1; /* Reuse the cluster hole */ - res = move_window(dj.fs, dw); - } - } - } - } - else { /* Open an existing file */ - if (res == FR_OK) { /* Follow succeeded */ - if (dir[DIR_Attr] & AM_DIR) { /* It is a directory */ - res = FR_NO_FILE; - } else { - if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */ - res = FR_DENIED; - } - } - } - if (res == FR_OK) { - if (mode & FA_CREATE_ALWAYS) /* Set file change flag if created or overwritten */ - mode |= FA__WRITTEN; - fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */ - fp->dir_ptr = dir; -#if _FS_LOCK - fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0); - if (!fp->lockid) res = FR_INT_ERR; -#endif - } - -#else /* R/O configuration */ - if (res == FR_OK) { /* Follow succeeded */ - dir = dj.dir; - if (!dir) { /* Current directory itself */ - res = FR_INVALID_NAME; - } else { - if (dir[DIR_Attr] & AM_DIR) /* It is a directory */ - res = FR_NO_FILE; - } - } -#endif - FREE_BUF(); - - if (res == FR_OK) { - fp->flag = mode; /* File access mode */ - fp->err = 0; /* Clear error flag */ - fp->sclust = ld_clust(dj.fs, dir); /* File start cluster */ - fp->fsize = LD_DWORD(dir + DIR_FileSize); /* File size */ - fp->fptr = 0; /* File pointer */ - fp->dsect = 0; -#if _USE_FASTSEEK - fp->cltbl = 0; /* Normal seek mode */ -#endif - fp->fs = dj.fs; /* Validate file object */ - fp->id = fp->fs->id; - } - } - - LEAVE_FF(dj.fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Read File */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_read ( - FIL* fp, /* Pointer to the file object */ - void* buff, /* Pointer to data buffer */ - UINT btr, /* Number of bytes to read */ - UINT* br /* Pointer to number of bytes read */ -) -{ - FRESULT res; - DWORD clst, sect, remain; - UINT rcnt, cc; - BYTE csect, *rbuff = (BYTE*)buff; - - - *br = 0; /* Clear read byte counter */ - - res = validate(fp); /* Check validity */ - if (res != FR_OK) LEAVE_FF(fp->fs, res); - if (fp->err) /* Check error */ - LEAVE_FF(fp->fs, (FRESULT)fp->err); - if (!(fp->flag & FA_READ)) /* Check access mode */ - LEAVE_FF(fp->fs, FR_DENIED); - remain = fp->fsize - fp->fptr; - if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ - - for ( ; btr; /* Repeat until all data read */ - rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) { - if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ - csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ - if (!csect) { /* On the cluster boundary? */ - if (fp->fptr == 0) { /* On the top of the file? */ - clst = fp->sclust; /* Follow from the origin */ - } else { /* Middle or end of the file */ -#if _USE_FASTSEEK - if (fp->cltbl) - clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ - else -#endif - clst = get_fat(fp->fs, fp->clust); /* Follow cluster chain on the FAT */ - } - if (clst < 2) ABORT(fp->fs, FR_INT_ERR); - if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - fp->clust = clst; /* Update current cluster */ - } - sect = clust2sect(fp->fs, fp->clust); /* Get current sector */ - if (!sect) ABORT(fp->fs, FR_INT_ERR); - sect += csect; - cc = btr / SS(fp->fs); /* When remaining bytes >= sector size, */ - if (cc) { /* Read maximum contiguous sectors directly */ - if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */ - cc = fp->fs->csize - csect; - if (disk_read(fp->fs->drv, rbuff, sect, cc) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); -#if !_FS_READONLY && _FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */ -#if _FS_TINY - if (fp->fs->wflag && fp->fs->winsect - sect < cc) - mem_cpy(rbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), fp->fs->win, SS(fp->fs)); -#else - if ((fp->flag & FA__DIRTY) && fp->dsect - sect < cc) - mem_cpy(rbuff + ((fp->dsect - sect) * SS(fp->fs)), fp->buf, SS(fp->fs)); -#endif -#endif - rcnt = SS(fp->fs) * cc; /* Number of bytes transferred */ - continue; - } -#if !_FS_TINY - if (fp->dsect != sect) { /* Load data sector if not in cache */ -#if !_FS_READONLY - if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */ - if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - fp->flag &= ~FA__DIRTY; - } -#endif - if (disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK) /* Fill sector cache */ - ABORT(fp->fs, FR_DISK_ERR); - } -#endif - fp->dsect = sect; - } - rcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs)); /* Get partial sector data from sector buffer */ - if (rcnt > btr) rcnt = btr; -#if _FS_TINY - if (move_window(fp->fs, fp->dsect) != FR_OK) /* Move sector window */ - ABORT(fp->fs, FR_DISK_ERR); - mem_cpy(rbuff, &fp->fs->win[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */ -#else - mem_cpy(rbuff, &fp->buf[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */ -#endif - } - - LEAVE_FF(fp->fs, FR_OK); -} - - - - -#if !_FS_READONLY -/*-----------------------------------------------------------------------*/ -/* Write File */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_write ( - FIL* fp, /* Pointer to the file object */ - const void *buff, /* Pointer to the data to be written */ - UINT btw, /* Number of bytes to write */ - UINT* bw /* Pointer to number of bytes written */ -) -{ - FRESULT res; - DWORD clst, sect; - UINT wcnt, cc; - const BYTE *wbuff = (const BYTE*)buff; - BYTE csect; - - - *bw = 0; /* Clear write byte counter */ - - res = validate(fp); /* Check validity */ - if (res != FR_OK) LEAVE_FF(fp->fs, res); - if (fp->err) /* Check error */ - LEAVE_FF(fp->fs, (FRESULT)fp->err); - if (!(fp->flag & FA_WRITE)) /* Check access mode */ - LEAVE_FF(fp->fs, FR_DENIED); - if (fp->fptr + btw < fp->fptr) btw = 0; /* File size cannot reach 4GB */ - - for ( ; btw; /* Repeat until all data written */ - wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt) { - if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ - csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ - if (!csect) { /* On the cluster boundary? */ - if (fp->fptr == 0) { /* On the top of the file? */ - clst = fp->sclust; /* Follow from the origin */ - if (clst == 0) /* When no cluster is allocated, */ - clst = create_chain(fp->fs, 0); /* Create a new cluster chain */ - } else { /* Middle or end of the file */ -#if _USE_FASTSEEK - if (fp->cltbl) - clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ - else -#endif - clst = create_chain(fp->fs, fp->clust); /* Follow or stretch cluster chain on the FAT */ - } - if (clst == 0) break; /* Could not allocate a new cluster (disk full) */ - if (clst == 1) ABORT(fp->fs, FR_INT_ERR); - if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - fp->clust = clst; /* Update current cluster */ - if (fp->sclust == 0) fp->sclust = clst; /* Set start cluster if the first write */ - } -#if _FS_TINY - if (fp->fs->winsect == fp->dsect && sync_window(fp->fs)) /* Write-back sector cache */ - ABORT(fp->fs, FR_DISK_ERR); -#else - if (fp->flag & FA__DIRTY) { /* Write-back sector cache */ - if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - fp->flag &= ~FA__DIRTY; - } -#endif - sect = clust2sect(fp->fs, fp->clust); /* Get current sector */ - if (!sect) ABORT(fp->fs, FR_INT_ERR); - sect += csect; - cc = btw / SS(fp->fs); /* When remaining bytes >= sector size, */ - if (cc) { /* Write maximum contiguous sectors directly */ - if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */ - cc = fp->fs->csize - csect; - if (disk_write(fp->fs->drv, wbuff, sect, cc) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); -#if _FS_MINIMIZE <= 2 -#if _FS_TINY - if (fp->fs->winsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ - mem_cpy(fp->fs->win, wbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), SS(fp->fs)); - fp->fs->wflag = 0; - } -#else - if (fp->dsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ - mem_cpy(fp->buf, wbuff + ((fp->dsect - sect) * SS(fp->fs)), SS(fp->fs)); - fp->flag &= ~FA__DIRTY; - } -#endif -#endif - wcnt = SS(fp->fs) * cc; /* Number of bytes transferred */ - continue; - } -#if _FS_TINY - if (fp->fptr >= fp->fsize) { /* Avoid silly cache filling at growing edge */ - if (sync_window(fp->fs)) ABORT(fp->fs, FR_DISK_ERR); - fp->fs->winsect = sect; - } -#else - if (fp->dsect != sect) { /* Fill sector cache with file data */ - if (fp->fptr < fp->fsize && - disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - } -#endif - fp->dsect = sect; - } - wcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */ - if (wcnt > btw) wcnt = btw; -#if _FS_TINY - if (move_window(fp->fs, fp->dsect) != FR_OK) /* Move sector window */ - ABORT(fp->fs, FR_DISK_ERR); - mem_cpy(&fp->fs->win[fp->fptr % SS(fp->fs)], wbuff, wcnt); /* Fit partial sector */ - fp->fs->wflag = 1; -#else - mem_cpy(&fp->buf[fp->fptr % SS(fp->fs)], wbuff, wcnt); /* Fit partial sector */ - fp->flag |= FA__DIRTY; -#endif - } - - if (fp->fptr > fp->fsize) fp->fsize = fp->fptr; /* Update file size if needed */ - fp->flag |= FA__WRITTEN; /* Set file change flag */ - - LEAVE_FF(fp->fs, FR_OK); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Synchronize the File */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_sync ( - FIL* fp /* Pointer to the file object */ -) -{ - FRESULT res; - DWORD tm; - BYTE *dir; - - - res = validate(fp); /* Check validity of the object */ - if (res == FR_OK) { - if (fp->flag & FA__WRITTEN) { /* Has the file been written? */ - /* Write-back dirty buffer */ -#if !_FS_TINY - if (fp->flag & FA__DIRTY) { - if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) - LEAVE_FF(fp->fs, FR_DISK_ERR); - fp->flag &= ~FA__DIRTY; - } -#endif - /* Update the directory entry */ - res = move_window(fp->fs, fp->dir_sect); - if (res == FR_OK) { - dir = fp->dir_ptr; - dir[DIR_Attr] |= AM_ARC; /* Set archive bit */ - ST_DWORD(dir + DIR_FileSize, fp->fsize); /* Update file size */ - st_clust(dir, fp->sclust); /* Update start cluster */ - tm = GET_FATTIME(); /* Update updated time */ - ST_DWORD(dir + DIR_WrtTime, tm); - ST_WORD(dir + DIR_LstAccDate, 0); - fp->flag &= ~FA__WRITTEN; - fp->fs->wflag = 1; - res = sync_fs(fp->fs); - } - } - } - - LEAVE_FF(fp->fs, res); -} - -#endif /* !_FS_READONLY */ - - - - -/*-----------------------------------------------------------------------*/ -/* Close File */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_close ( - FIL *fp /* Pointer to the file object to be closed */ -) -{ - FRESULT res; - - -#if !_FS_READONLY - res = f_sync(fp); /* Flush cached data */ - if (res == FR_OK) -#endif - { - res = validate(fp); /* Lock volume */ - if (res == FR_OK) { -#if _FS_REENTRANT - FATFS *fs = fp->fs; -#endif -#if _FS_LOCK - res = dec_lock(fp->lockid); /* Decrement file open counter */ - if (res == FR_OK) -#endif - fp->fs = 0; /* Invalidate file object */ -#if _FS_REENTRANT - unlock_fs(fs, FR_OK); /* Unlock volume */ -#endif - } - } - return res; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Change Current Directory or Current Drive, Get Current Directory */ -/*-----------------------------------------------------------------------*/ - -#if _FS_RPATH >= 1 -#if _VOLUMES >= 2 -FRESULT f_chdrive ( - const TCHAR* path /* Drive number */ -) -{ - int vol; - - - vol = get_ldnumber(&path); - if (vol < 0) return FR_INVALID_DRIVE; - - CurrVol = (BYTE)vol; - - return FR_OK; -} -#endif - - -FRESULT f_chdir ( - const TCHAR* path /* Pointer to the directory path */ -) -{ - FRESULT res; - DIR dj; - DEFINE_NAMEBUF; - - - /* Get logical drive number */ - res = find_volume(&dj.fs, &path, 0); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the path */ - FREE_BUF(); - if (res == FR_OK) { /* Follow completed */ - if (!dj.dir) { - dj.fs->cdir = dj.sclust; /* Start directory itself */ - } else { - if (dj.dir[DIR_Attr] & AM_DIR) /* Reached to the directory */ - dj.fs->cdir = ld_clust(dj.fs, dj.dir); - else - res = FR_NO_PATH; /* Reached but a file */ - } - } - if (res == FR_NO_FILE) res = FR_NO_PATH; - } - - LEAVE_FF(dj.fs, res); -} - - -#if _FS_RPATH >= 2 -FRESULT f_getcwd ( - TCHAR* buff, /* Pointer to the directory path */ - UINT len /* Size of path */ -) -{ - FRESULT res; - DIR dj; - UINT i, n; - DWORD ccl; - TCHAR *tp; - FILINFO fno; - DEFINE_NAMEBUF; - - - *buff = 0; - /* Get logical drive number */ - res = find_volume(&dj.fs, (const TCHAR**)&buff, 0); /* Get current volume */ - if (res == FR_OK) { - INIT_BUF(dj); - i = len; /* Bottom of buffer (directory stack base) */ - dj.sclust = dj.fs->cdir; /* Start to follow upper directory from current directory */ - while ((ccl = dj.sclust) != 0) { /* Repeat while current directory is a sub-directory */ - res = dir_sdi(&dj, 1); /* Get parent directory */ - if (res != FR_OK) break; - res = dir_read(&dj, 0); - if (res != FR_OK) break; - dj.sclust = ld_clust(dj.fs, dj.dir); /* Goto parent directory */ - res = dir_sdi(&dj, 0); - if (res != FR_OK) break; - do { /* Find the entry links to the child directory */ - res = dir_read(&dj, 0); - if (res != FR_OK) break; - if (ccl == ld_clust(dj.fs, dj.dir)) break; /* Found the entry */ - res = dir_next(&dj, 0); - } while (res == FR_OK); - if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */ - if (res != FR_OK) break; -#if _USE_LFN - fno.lfname = buff; - fno.lfsize = i; -#endif - get_fileinfo(&dj, &fno); /* Get the directory name and push it to the buffer */ - tp = fno.fname; -#if _USE_LFN - if (*buff) tp = buff; -#endif - for (n = 0; tp[n]; n++) ; - if (i < n + 3) { - res = FR_NOT_ENOUGH_CORE; break; - } - while (n) buff[--i] = tp[--n]; - buff[--i] = '/'; - } - tp = buff; - if (res == FR_OK) { -#if _VOLUMES >= 2 - *tp++ = '0' + CurrVol; /* Put drive number */ - *tp++ = ':'; -#endif - if (i == len) { /* Root-directory */ - *tp++ = '/'; - } else { /* Sub-directroy */ - do /* Add stacked path str */ - *tp++ = buff[i++]; - while (i < len); - } - } - *tp = 0; - FREE_BUF(); - } - - LEAVE_FF(dj.fs, res); -} -#endif /* _FS_RPATH >= 2 */ -#endif /* _FS_RPATH >= 1 */ - - - -#if _FS_MINIMIZE <= 2 -/*-----------------------------------------------------------------------*/ -/* Seek File R/W Pointer */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_lseek ( - FIL* fp, /* Pointer to the file object */ - DWORD ofs /* File pointer from top of file */ -) -{ - FRESULT res; - DWORD clst, bcs, nsect, ifptr; -#if _USE_FASTSEEK - DWORD cl, pcl, ncl, tcl, dsc, tlen, ulen, *tbl; -#endif - - - res = validate(fp); /* Check validity of the object */ - if (res != FR_OK) LEAVE_FF(fp->fs, res); - if (fp->err) /* Check error */ - LEAVE_FF(fp->fs, (FRESULT)fp->err); - -#if _USE_FASTSEEK - if (fp->cltbl) { /* Fast seek */ - if (ofs == CREATE_LINKMAP) { /* Create CLMT */ - tbl = fp->cltbl; - tlen = *tbl++; ulen = 2; /* Given table size and required table size */ - cl = fp->sclust; /* Top of the chain */ - if (cl) { - do { - /* Get a fragment */ - tcl = cl; ncl = 0; ulen += 2; /* Top, length and used items */ - do { - pcl = cl; ncl++; - cl = get_fat(fp->fs, cl); - if (cl <= 1) ABORT(fp->fs, FR_INT_ERR); - if (cl == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - } while (cl == pcl + 1); - if (ulen <= tlen) { /* Store the length and top of the fragment */ - *tbl++ = ncl; *tbl++ = tcl; - } - } while (cl < fp->fs->n_fatent); /* Repeat until end of chain */ - } - *fp->cltbl = ulen; /* Number of items used */ - if (ulen <= tlen) - *tbl = 0; /* Terminate table */ - else - res = FR_NOT_ENOUGH_CORE; /* Given table size is smaller than required */ - - } else { /* Fast seek */ - if (ofs > fp->fsize) /* Clip offset at the file size */ - ofs = fp->fsize; - fp->fptr = ofs; /* Set file pointer */ - if (ofs) { - fp->clust = clmt_clust(fp, ofs - 1); - dsc = clust2sect(fp->fs, fp->clust); - if (!dsc) ABORT(fp->fs, FR_INT_ERR); - dsc += (ofs - 1) / SS(fp->fs) & (fp->fs->csize - 1); - if (fp->fptr % SS(fp->fs) && dsc != fp->dsect) { /* Refill sector cache if needed */ -#if !_FS_TINY -#if !_FS_READONLY - if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */ - if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - fp->flag &= ~FA__DIRTY; - } -#endif - if (disk_read(fp->fs->drv, fp->buf, dsc, 1) != RES_OK) /* Load current sector */ - ABORT(fp->fs, FR_DISK_ERR); -#endif - fp->dsect = dsc; - } - } - } - } else -#endif - - /* Normal Seek */ - { - if (ofs > fp->fsize /* In read-only mode, clip offset with the file size */ -#if !_FS_READONLY - && !(fp->flag & FA_WRITE) -#endif - ) ofs = fp->fsize; - - ifptr = fp->fptr; - fp->fptr = nsect = 0; - if (ofs) { - bcs = (DWORD)fp->fs->csize * SS(fp->fs); /* Cluster size (byte) */ - if (ifptr > 0 && - (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */ - fp->fptr = (ifptr - 1) & ~(bcs - 1); /* start from the current cluster */ - ofs -= fp->fptr; - clst = fp->clust; - } else { /* When seek to back cluster, */ - clst = fp->sclust; /* start from the first cluster */ -#if !_FS_READONLY - if (clst == 0) { /* If no cluster chain, create a new chain */ - clst = create_chain(fp->fs, 0); - if (clst == 1) ABORT(fp->fs, FR_INT_ERR); - if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - fp->sclust = clst; - } -#endif - fp->clust = clst; - } - if (clst != 0) { - while (ofs > bcs) { /* Cluster following loop */ -#if !_FS_READONLY - if (fp->flag & FA_WRITE) { /* Check if in write mode or not */ - clst = create_chain(fp->fs, clst); /* Force stretch if in write mode */ - if (clst == 0) { /* When disk gets full, clip file size */ - ofs = bcs; break; - } - } else -#endif - clst = get_fat(fp->fs, clst); /* Follow cluster chain if not in write mode */ - if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - if (clst <= 1 || clst >= fp->fs->n_fatent) ABORT(fp->fs, FR_INT_ERR); - fp->clust = clst; - fp->fptr += bcs; - ofs -= bcs; - } - fp->fptr += ofs; - if (ofs % SS(fp->fs)) { - nsect = clust2sect(fp->fs, clst); /* Current sector */ - if (!nsect) ABORT(fp->fs, FR_INT_ERR); - nsect += ofs / SS(fp->fs); - } - } - } - if (fp->fptr % SS(fp->fs) && nsect != fp->dsect) { /* Fill sector cache if needed */ -#if !_FS_TINY -#if !_FS_READONLY - if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */ - if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) - ABORT(fp->fs, FR_DISK_ERR); - fp->flag &= ~FA__DIRTY; - } -#endif - if (disk_read(fp->fs->drv, fp->buf, nsect, 1) != RES_OK) /* Fill sector cache */ - ABORT(fp->fs, FR_DISK_ERR); -#endif - fp->dsect = nsect; - } -#if !_FS_READONLY - if (fp->fptr > fp->fsize) { /* Set file change flag if the file size is extended */ - fp->fsize = fp->fptr; - fp->flag |= FA__WRITTEN; - } -#endif - } - - LEAVE_FF(fp->fs, res); -} - - - -#if _FS_MINIMIZE <= 1 -/*-----------------------------------------------------------------------*/ -/* Create a Directory Object */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_opendir ( - DIR* dp, /* Pointer to directory object to create */ - const TCHAR* path /* Pointer to the directory path */ -) -{ - FRESULT res; - FATFS* fs; - DEFINE_NAMEBUF; - - - if (!dp) return FR_INVALID_OBJECT; - - /* Get logical drive number */ - res = find_volume(&fs, &path, 0); - if (res == FR_OK) { - dp->fs = fs; - INIT_BUF(*dp); - res = follow_path(dp, path); /* Follow the path to the directory */ - FREE_BUF(); - if (res == FR_OK) { /* Follow completed */ - if (dp->dir) { /* It is not the origin directory itself */ - if (dp->dir[DIR_Attr] & AM_DIR) /* The object is a sub directory */ - dp->sclust = ld_clust(fs, dp->dir); - else /* The object is a file */ - res = FR_NO_PATH; - } - if (res == FR_OK) { - dp->id = fs->id; - res = dir_sdi(dp, 0); /* Rewind directory */ -#if _FS_LOCK - if (res == FR_OK) { - if (dp->sclust) { - dp->lockid = inc_lock(dp, 0); /* Lock the sub directory */ - if (!dp->lockid) - res = FR_TOO_MANY_OPEN_FILES; - } else { - dp->lockid = 0; /* Root directory need not to be locked */ - } - } -#endif - } - } - if (res == FR_NO_FILE) res = FR_NO_PATH; - } - if (res != FR_OK) dp->fs = 0; /* Invalidate the directory object if function faild */ - - LEAVE_FF(fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Close Directory */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_closedir ( - DIR *dp /* Pointer to the directory object to be closed */ -) -{ - FRESULT res; - - - res = validate(dp); - if (res == FR_OK) { -#if _FS_REENTRANT - FATFS *fs = dp->fs; -#endif -#if _FS_LOCK - if (dp->lockid) /* Decrement sub-directory open counter */ - res = dec_lock(dp->lockid); - if (res == FR_OK) -#endif - dp->fs = 0; /* Invalidate directory object */ -#if _FS_REENTRANT - unlock_fs(fs, FR_OK); /* Unlock volume */ -#endif - } - return res; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Read Directory Entries in Sequence */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_readdir ( - DIR* dp, /* Pointer to the open directory object */ - FILINFO* fno /* Pointer to file information to return */ -) -{ - FRESULT res; - DEFINE_NAMEBUF; - - - res = validate(dp); /* Check validity of the object */ - if (res == FR_OK) { - if (!fno) { - res = dir_sdi(dp, 0); /* Rewind the directory object */ - } else { - INIT_BUF(*dp); - res = dir_read(dp, 0); /* Read an item */ - if (res == FR_NO_FILE) { /* Reached end of directory */ - dp->sect = 0; - res = FR_OK; - } - if (res == FR_OK) { /* A valid entry is found */ - get_fileinfo(dp, fno); /* Get the object information */ - res = dir_next(dp, 0); /* Increment index for next */ - if (res == FR_NO_FILE) { - dp->sect = 0; - res = FR_OK; - } - } - FREE_BUF(); - } - } - - LEAVE_FF(dp->fs, res); -} - - - -#if _USE_FIND -/*-----------------------------------------------------------------------*/ -/* Find next file */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_findnext ( - DIR* dp, /* Pointer to the open directory object */ - FILINFO* fno /* Pointer to the file information structure */ -) -{ - FRESULT res; - - - for (;;) { - res = f_readdir(dp, fno); /* Get a directory item */ - if (res != FR_OK || !fno || !fno->fname[0]) break; /* Terminate if any error or end of directory */ -#if _USE_LFN - if (fno->lfname && pattern_matching(dp->pat, fno->lfname, 0, 0)) break; /* Test for LFN if exist */ -#endif - if (pattern_matching(dp->pat, fno->fname, 0, 0)) break; /* Test for SFN */ - } - return res; - -} - - - -/*-----------------------------------------------------------------------*/ -/* Find first file */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_findfirst ( - DIR* dp, /* Pointer to the blank directory object */ - FILINFO* fno, /* Pointer to the file information structure */ - const TCHAR* path, /* Pointer to the directory to open */ - const TCHAR* pattern /* Pointer to the matching pattern */ -) -{ - FRESULT res; - - - dp->pat = pattern; /* Save pointer to pattern string */ - res = f_opendir(dp, path); /* Open the target directory */ - if (res == FR_OK) - res = f_findnext(dp, fno); /* Find the first item */ - return res; -} - -#endif /* _USE_FIND */ - - - -#if _FS_MINIMIZE == 0 -/*-----------------------------------------------------------------------*/ -/* Get File Status */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_stat ( - const TCHAR* path, /* Pointer to the file path */ - FILINFO* fno /* Pointer to file information to return */ -) -{ - FRESULT res; - DIR dj; - DEFINE_NAMEBUF; - - - /* Get logical drive number */ - res = find_volume(&dj.fs, &path, 0); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the file path */ - if (res == FR_OK) { /* Follow completed */ - if (dj.dir) { /* Found an object */ - if (fno) get_fileinfo(&dj, fno); - } else { /* It is root directory */ - res = FR_INVALID_NAME; - } - } - FREE_BUF(); - } - - LEAVE_FF(dj.fs, res); -} - - - -#if !_FS_READONLY -/*-----------------------------------------------------------------------*/ -/* Get Number of Free Clusters */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_getfree ( - const TCHAR* path, /* Path name of the logical drive number */ - DWORD* nclst, /* Pointer to a variable to return number of free clusters */ - FATFS** fatfs /* Pointer to return pointer to corresponding file system object */ -) -{ - FRESULT res; - FATFS *fs; - DWORD n, clst, sect, stat; - UINT i; - BYTE fat, *p; - - - /* Get logical drive number */ - res = find_volume(fatfs, &path, 0); - fs = *fatfs; - if (res == FR_OK) { - /* If free_clust is valid, return it without full cluster scan */ - if (fs->free_clust <= fs->n_fatent - 2) { - *nclst = fs->free_clust; - } else { - /* Get number of free clusters */ - fat = fs->fs_type; - n = 0; - if (fat == FS_FAT12) { - clst = 2; - do { - stat = get_fat(fs, clst); - if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } - if (stat == 1) { res = FR_INT_ERR; break; } - if (stat == 0) n++; - } while (++clst < fs->n_fatent); - } else { - clst = fs->n_fatent; - sect = fs->fatbase; - i = 0; p = 0; - do { - if (!i) { - res = move_window(fs, sect++); - if (res != FR_OK) break; - p = fs->win; - i = SS(fs); - } - if (fat == FS_FAT16) { - if (LD_WORD(p) == 0) n++; - p += 2; i -= 2; - } else { - if ((LD_DWORD(p) & 0x0FFFFFFF) == 0) n++; - p += 4; i -= 4; - } - } while (--clst); - } - fs->free_clust = n; - fs->fsi_flag |= 1; - *nclst = n; - } - } - LEAVE_FF(fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Truncate File */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_truncate ( - FIL* fp /* Pointer to the file object */ -) -{ - FRESULT res; - DWORD ncl; - - - res = validate(fp); /* Check validity of the object */ - if (res == FR_OK) { - if (fp->err) { /* Check error */ - res = (FRESULT)fp->err; - } else { - if (!(fp->flag & FA_WRITE)) /* Check access mode */ - res = FR_DENIED; - } - } - if (res == FR_OK) { - if (fp->fsize > fp->fptr) { - fp->fsize = fp->fptr; /* Set file size to current R/W point */ - fp->flag |= FA__WRITTEN; - if (fp->fptr == 0) { /* When set file size to zero, remove entire cluster chain */ - res = remove_chain(fp->fs, fp->sclust); - fp->sclust = 0; - } else { /* When truncate a part of the file, remove remaining clusters */ - ncl = get_fat(fp->fs, fp->clust); - res = FR_OK; - if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR; - if (ncl == 1) res = FR_INT_ERR; - if (res == FR_OK && ncl < fp->fs->n_fatent) { - res = put_fat(fp->fs, fp->clust, 0x0FFFFFFF); - if (res == FR_OK) res = remove_chain(fp->fs, ncl); - } - } -#if !_FS_TINY - if (res == FR_OK && (fp->flag & FA__DIRTY)) { - if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK) - res = FR_DISK_ERR; - else - fp->flag &= ~FA__DIRTY; - } -#endif - } - if (res != FR_OK) fp->err = (FRESULT)res; - } - - LEAVE_FF(fp->fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Delete a File or Directory */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_unlink ( - const TCHAR* path /* Pointer to the file or directory path */ -) -{ - FRESULT res; - DIR dj, sdj; - BYTE *dir; - DWORD dclst = 0; - DEFINE_NAMEBUF; - - - /* Get logical drive number */ - res = find_volume(&dj.fs, &path, 1); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the file path */ - if (_FS_RPATH && res == FR_OK && (dj.fn[NSFLAG] & NS_DOT)) - res = FR_INVALID_NAME; /* Cannot remove dot entry */ -#if _FS_LOCK - if (res == FR_OK) res = chk_lock(&dj, 2); /* Cannot remove open object */ -#endif - if (res == FR_OK) { /* The object is accessible */ - dir = dj.dir; - if (!dir) { - res = FR_INVALID_NAME; /* Cannot remove the origin directory */ - } else { - if (dir[DIR_Attr] & AM_RDO) - res = FR_DENIED; /* Cannot remove R/O object */ - } - if (res == FR_OK) { - dclst = ld_clust(dj.fs, dir); - if (dclst && (dir[DIR_Attr] & AM_DIR)) { /* Is it a sub-directory ? */ -#if _FS_RPATH - if (dclst == dj.fs->cdir) { /* Is it the current directory? */ - res = FR_DENIED; - } else -#endif - { - mem_cpy(&sdj, &dj, sizeof (DIR)); /* Open the sub-directory */ - sdj.sclust = dclst; - res = dir_sdi(&sdj, 2); - if (res == FR_OK) { - res = dir_read(&sdj, 0); /* Read an item (excluding dot entries) */ - if (res == FR_OK) res = FR_DENIED; /* Not empty? (cannot remove) */ - if (res == FR_NO_FILE) res = FR_OK; /* Empty? (can remove) */ - } - } - } - } - if (res == FR_OK) { - res = dir_remove(&dj); /* Remove the directory entry */ - if (res == FR_OK && dclst) /* Remove the cluster chain if exist */ - res = remove_chain(dj.fs, dclst); - if (res == FR_OK) res = sync_fs(dj.fs); - } - } - FREE_BUF(); - } - - LEAVE_FF(dj.fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Create a Directory */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_mkdir ( - const TCHAR* path /* Pointer to the directory path */ -) -{ - FRESULT res; - DIR dj; - BYTE *dir, n; - DWORD dsc, dcl, pcl, tm = GET_FATTIME(); - DEFINE_NAMEBUF; - - - /* Get logical drive number */ - res = find_volume(&dj.fs, &path, 1); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the file path */ - if (res == FR_OK) res = FR_EXIST; /* Any object with same name is already existing */ - if (_FS_RPATH && res == FR_NO_FILE && (dj.fn[NSFLAG] & NS_DOT)) - res = FR_INVALID_NAME; - if (res == FR_NO_FILE) { /* Can create a new directory */ - dcl = create_chain(dj.fs, 0); /* Allocate a cluster for the new directory table */ - res = FR_OK; - if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster */ - if (dcl == 1) res = FR_INT_ERR; - if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR; - if (res == FR_OK) /* Flush FAT */ - res = sync_window(dj.fs); - if (res == FR_OK) { /* Initialize the new directory table */ - dsc = clust2sect(dj.fs, dcl); - dir = dj.fs->win; - mem_set(dir, 0, SS(dj.fs)); - mem_set(dir + DIR_Name, ' ', 11); /* Create "." entry */ - dir[DIR_Name] = '.'; - dir[DIR_Attr] = AM_DIR; - ST_DWORD(dir + DIR_WrtTime, tm); - st_clust(dir, dcl); - mem_cpy(dir + SZ_DIRE, dir, SZ_DIRE); /* Create ".." entry */ - dir[SZ_DIRE + 1] = '.'; pcl = dj.sclust; - if (dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase) - pcl = 0; - st_clust(dir + SZ_DIRE, pcl); - for (n = dj.fs->csize; n; n--) { /* Write dot entries and clear following sectors */ - dj.fs->winsect = dsc++; - dj.fs->wflag = 1; - res = sync_window(dj.fs); - if (res != FR_OK) break; - mem_set(dir, 0, SS(dj.fs)); - } - } - if (res == FR_OK) res = dir_register(&dj); /* Register the object to the directoy */ - if (res != FR_OK) { - remove_chain(dj.fs, dcl); /* Could not register, remove cluster chain */ - } else { - dir = dj.dir; - dir[DIR_Attr] = AM_DIR; /* Attribute */ - ST_DWORD(dir + DIR_WrtTime, tm); /* Created time */ - st_clust(dir, dcl); /* Table start cluster */ - dj.fs->wflag = 1; - res = sync_fs(dj.fs); - } - } - FREE_BUF(); - } - - LEAVE_FF(dj.fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Change Attribute */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_chmod ( - const TCHAR* path, /* Pointer to the file path */ - BYTE attr, /* Attribute bits */ - BYTE mask /* Attribute mask to change */ -) -{ - FRESULT res; - DIR dj; - BYTE *dir; - DEFINE_NAMEBUF; - - - /* Get logical drive number */ - res = find_volume(&dj.fs, &path, 1); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the file path */ - FREE_BUF(); - if (_FS_RPATH && res == FR_OK && (dj.fn[NSFLAG] & NS_DOT)) - res = FR_INVALID_NAME; - if (res == FR_OK) { - dir = dj.dir; - if (!dir) { /* Is it a root directory? */ - res = FR_INVALID_NAME; - } else { /* File or sub directory */ - mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC; /* Valid attribute mask */ - dir[DIR_Attr] = (attr & mask) | (dir[DIR_Attr] & (BYTE)~mask); /* Apply attribute change */ - dj.fs->wflag = 1; - res = sync_fs(dj.fs); - } - } - } - - LEAVE_FF(dj.fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Rename File/Directory */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_rename ( - const TCHAR* path_old, /* Pointer to the object to be renamed */ - const TCHAR* path_new /* Pointer to the new name */ -) -{ - FRESULT res; - DIR djo, djn; - BYTE buf[21], *dir; - DWORD dw; - DEFINE_NAMEBUF; - - - /* Get logical drive number of the source object */ - res = find_volume(&djo.fs, &path_old, 1); - if (res == FR_OK) { - djn.fs = djo.fs; - INIT_BUF(djo); - res = follow_path(&djo, path_old); /* Check old object */ - if (_FS_RPATH && res == FR_OK && (djo.fn[NSFLAG] & NS_DOT)) - res = FR_INVALID_NAME; -#if _FS_LOCK - if (res == FR_OK) res = chk_lock(&djo, 2); -#endif - if (res == FR_OK) { /* Old object is found */ - if (!djo.dir) { /* Is root dir? */ - res = FR_NO_FILE; - } else { - mem_cpy(buf, djo.dir + DIR_Attr, 21); /* Save information about object except name */ - mem_cpy(&djn, &djo, sizeof (DIR)); /* Duplicate the directory object */ - if (get_ldnumber(&path_new) >= 0) /* Snip drive number off and ignore it */ - res = follow_path(&djn, path_new); /* and make sure if new object name is not conflicting */ - else - res = FR_INVALID_DRIVE; - if (res == FR_OK) res = FR_EXIST; /* The new object name is already existing */ - if (res == FR_NO_FILE) { /* It is a valid path and no name collision */ - res = dir_register(&djn); /* Register the new entry */ - if (res == FR_OK) { -/* Start of critical section where any interruption can cause a cross-link */ - dir = djn.dir; /* Copy information about object except name */ - mem_cpy(dir + 13, buf + 2, 19); - dir[DIR_Attr] = buf[0] | AM_ARC; - djo.fs->wflag = 1; - if ((dir[DIR_Attr] & AM_DIR) && djo.sclust != djn.sclust) { /* Update .. entry in the sub-directory if needed */ - dw = clust2sect(djo.fs, ld_clust(djo.fs, dir)); - if (!dw) { - res = FR_INT_ERR; - } else { - res = move_window(djo.fs, dw); - dir = djo.fs->win + SZ_DIRE * 1; /* Ptr to .. entry */ - if (res == FR_OK && dir[1] == '.') { - st_clust(dir, djn.sclust); - djo.fs->wflag = 1; - } - } - } - if (res == FR_OK) { - res = dir_remove(&djo); /* Remove old entry */ - if (res == FR_OK) - res = sync_fs(djo.fs); - } -/* End of critical section */ - } - } - } - } - FREE_BUF(); - } - - LEAVE_FF(djo.fs, res); -} - - - - -/*-----------------------------------------------------------------------*/ -/* Change Timestamp */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_utime ( - const TCHAR* path, /* Pointer to the file/directory name */ - const FILINFO* fno /* Pointer to the time stamp to be set */ -) -{ - FRESULT res; - DIR dj; - BYTE *dir; - DEFINE_NAMEBUF; - - - /* Get logical drive number */ - res = find_volume(&dj.fs, &path, 1); - if (res == FR_OK) { - INIT_BUF(dj); - res = follow_path(&dj, path); /* Follow the file path */ - FREE_BUF(); - if (_FS_RPATH && res == FR_OK && (dj.fn[NSFLAG] & NS_DOT)) - res = FR_INVALID_NAME; - if (res == FR_OK) { - dir = dj.dir; - if (!dir) { /* Root directory */ - res = FR_INVALID_NAME; - } else { /* File or sub-directory */ - ST_WORD(dir + DIR_WrtTime, fno->ftime); - ST_WORD(dir + DIR_WrtDate, fno->fdate); - dj.fs->wflag = 1; - res = sync_fs(dj.fs); - } - } - } - - LEAVE_FF(dj.fs, res); -} - -#endif /* !_FS_READONLY */ -#endif /* _FS_MINIMIZE == 0 */ -#endif /* _FS_MINIMIZE <= 1 */ -#endif /* _FS_MINIMIZE <= 2 */ - - - - -#if _USE_LABEL -/*-----------------------------------------------------------------------*/ -/* Get volume label */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_getlabel ( - const TCHAR* path, /* Path name of the logical drive number */ - TCHAR* label, /* Pointer to a buffer to return the volume label */ - DWORD* vsn /* Pointer to a variable to return the volume serial number */ -) -{ - FRESULT res; - DIR dj; - UINT i, j; -#if _USE_LFN && _LFN_UNICODE - WCHAR w; -#endif - - - /* Get logical drive number */ - res = find_volume(&dj.fs, &path, 0); - - /* Get volume label */ - if (res == FR_OK && label) { - dj.sclust = 0; /* Open root directory */ - res = dir_sdi(&dj, 0); - if (res == FR_OK) { - res = dir_read(&dj, 1); /* Get an entry with AM_VOL */ - if (res == FR_OK) { /* A volume label is exist */ -#if _USE_LFN && _LFN_UNICODE - i = j = 0; - do { - w = (i < 11) ? dj.dir[i++] : ' '; - if (IsDBCS1(w) && i < 11 && IsDBCS2(dj.dir[i])) - w = w << 8 | dj.dir[i++]; - label[j++] = ff_convert(w, 1); /* OEM -> Unicode */ - } while (j < 11); -#else - mem_cpy(label, dj.dir, 11); -#endif - j = 11; - do { - label[j] = 0; - if (!j) break; - } while (label[--j] == ' '); - } - if (res == FR_NO_FILE) { /* No label, return nul string */ - label[0] = 0; - res = FR_OK; - } - } - } - - /* Get volume serial number */ - if (res == FR_OK && vsn) { - res = move_window(dj.fs, dj.fs->volbase); - if (res == FR_OK) { - i = dj.fs->fs_type == FS_FAT32 ? BS_VolID32 : BS_VolID; - *vsn = LD_DWORD(&dj.fs->win[i]); - } - } - - LEAVE_FF(dj.fs, res); -} - - - -#if !_FS_READONLY -/*-----------------------------------------------------------------------*/ -/* Set volume label */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_setlabel ( - const TCHAR* label /* Pointer to the volume label to set */ -) -{ - FRESULT res; - DIR dj; - BYTE vn[11]; - UINT i, j, sl; - WCHAR w; - DWORD tm; - - - /* Get logical drive number */ - res = find_volume(&dj.fs, &label, 1); - if (res) LEAVE_FF(dj.fs, res); - - /* Create a volume label in directory form */ - vn[0] = 0; - for (sl = 0; label[sl]; sl++) ; /* Get name length */ - for ( ; sl && label[sl - 1] == ' '; sl--) ; /* Remove trailing spaces */ - if (sl) { /* Create volume label in directory form */ - i = j = 0; - do { -#if _USE_LFN && _LFN_UNICODE - w = ff_convert(ff_wtoupper(label[i++]), 0); -#else - w = (BYTE)label[i++]; - if (IsDBCS1(w)) - w = (j < 10 && i < sl && IsDBCS2(label[i])) ? w << 8 | (BYTE)label[i++] : 0; -#if _USE_LFN - w = ff_convert(ff_wtoupper(ff_convert(w, 1)), 0); -#else - if (IsLower(w)) w -= 0x20; /* To upper ASCII characters */ -#ifdef _EXCVT - if (w >= 0x80) w = ExCvt[w - 0x80]; /* To upper extended characters (SBCS cfg) */ -#else - if (!_DF1S && w >= 0x80) w = 0; /* Reject extended characters (ASCII cfg) */ -#endif -#endif -#endif - if (!w || chk_chr("\"*+,.:;<=>\?[]|\x7F", w) || j >= (UINT)((w >= 0x100) ? 10 : 11)) /* Reject invalid characters for volume label */ - LEAVE_FF(dj.fs, FR_INVALID_NAME); - if (w >= 0x100) vn[j++] = (BYTE)(w >> 8); - vn[j++] = (BYTE)w; - } while (i < sl); - while (j < 11) vn[j++] = ' '; /* Fill remaining name field */ - if (vn[0] == DDEM) LEAVE_FF(dj.fs, FR_INVALID_NAME); /* Reject illegal name (heading DDEM) */ - } - - /* Set volume label */ - dj.sclust = 0; /* Open root directory */ - res = dir_sdi(&dj, 0); - if (res == FR_OK) { - res = dir_read(&dj, 1); /* Get an entry with AM_VOL */ - if (res == FR_OK) { /* A volume label is found */ - if (vn[0]) { - mem_cpy(dj.dir, vn, 11); /* Change the volume label name */ - tm = GET_FATTIME(); - ST_DWORD(dj.dir + DIR_WrtTime, tm); - } else { - dj.dir[0] = DDEM; /* Remove the volume label */ - } - dj.fs->wflag = 1; - res = sync_fs(dj.fs); - } else { /* No volume label is found or error */ - if (res == FR_NO_FILE) { - res = FR_OK; - if (vn[0]) { /* Create volume label as new */ - res = dir_alloc(&dj, 1); /* Allocate an entry for volume label */ - if (res == FR_OK) { - mem_set(dj.dir, 0, SZ_DIRE); /* Set volume label */ - mem_cpy(dj.dir, vn, 11); - dj.dir[DIR_Attr] = AM_VOL; - tm = GET_FATTIME(); - ST_DWORD(dj.dir + DIR_WrtTime, tm); - dj.fs->wflag = 1; - res = sync_fs(dj.fs); - } - } - } - } - } - - LEAVE_FF(dj.fs, res); -} - -#endif /* !_FS_READONLY */ -#endif /* _USE_LABEL */ - - - -/*-----------------------------------------------------------------------*/ -/* Forward data to the stream directly (available on only tiny cfg) */ -/*-----------------------------------------------------------------------*/ -#if _USE_FORWARD && _FS_TINY - -FRESULT f_forward ( - FIL* fp, /* Pointer to the file object */ - UINT (*func)(const BYTE*,UINT), /* Pointer to the streaming function */ - UINT btf, /* Number of bytes to forward */ - UINT* bf /* Pointer to number of bytes forwarded */ -) -{ - FRESULT res; - DWORD remain, clst, sect; - UINT rcnt; - BYTE csect; - - - *bf = 0; /* Clear transfer byte counter */ - - res = validate(fp); /* Check validity of the object */ - if (res != FR_OK) LEAVE_FF(fp->fs, res); - if (fp->err) /* Check error */ - LEAVE_FF(fp->fs, (FRESULT)fp->err); - if (!(fp->flag & FA_READ)) /* Check access mode */ - LEAVE_FF(fp->fs, FR_DENIED); - - remain = fp->fsize - fp->fptr; - if (btf > remain) btf = (UINT)remain; /* Truncate btf by remaining bytes */ - - for ( ; btf && (*func)(0, 0); /* Repeat until all data transferred or stream becomes busy */ - fp->fptr += rcnt, *bf += rcnt, btf -= rcnt) { - csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */ - if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ - if (!csect) { /* On the cluster boundary? */ - clst = (fp->fptr == 0) ? /* On the top of the file? */ - fp->sclust : get_fat(fp->fs, fp->clust); - if (clst <= 1) ABORT(fp->fs, FR_INT_ERR); - if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); - fp->clust = clst; /* Update current cluster */ - } - } - sect = clust2sect(fp->fs, fp->clust); /* Get current data sector */ - if (!sect) ABORT(fp->fs, FR_INT_ERR); - sect += csect; - if (move_window(fp->fs, sect) != FR_OK) /* Move sector window */ - ABORT(fp->fs, FR_DISK_ERR); - fp->dsect = sect; - rcnt = SS(fp->fs) - (WORD)(fp->fptr % SS(fp->fs)); /* Forward data from sector window */ - if (rcnt > btf) rcnt = btf; - rcnt = (*func)(&fp->fs->win[(WORD)fp->fptr % SS(fp->fs)], rcnt); - if (!rcnt) ABORT(fp->fs, FR_INT_ERR); - } - - LEAVE_FF(fp->fs, FR_OK); -} -#endif /* _USE_FORWARD */ - - - -#if _USE_MKFS && !_FS_READONLY -/*-----------------------------------------------------------------------*/ -/* Create file system on the logical drive */ -/*-----------------------------------------------------------------------*/ -#define N_ROOTDIR 512 /* Number of root directory entries for FAT12/16 */ -#define N_FATS 1 /* Number of FATs (1 or 2) */ - - -FRESULT f_mkfs ( - const TCHAR* path, /* Logical drive number */ - BYTE sfd, /* Partitioning rule 0:FDISK, 1:SFD */ - UINT au /* Size of allocation unit in unit of byte or sector */ -) -{ - static const WORD vst[] = { 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 0}; - static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512}; - int vol; - BYTE fmt, md, sys, *tbl, pdrv, part; - DWORD n_clst, vs, n, wsect; - UINT i; - DWORD b_vol, b_fat, b_dir, b_data; /* LBA */ - DWORD n_vol, n_rsv, n_fat, n_dir; /* Size */ - FATFS *fs; - DSTATUS stat; -#if _USE_TRIM - DWORD eb[2]; -#endif - - - /* Check mounted drive and clear work area */ - if (sfd > 1) return FR_INVALID_PARAMETER; - vol = get_ldnumber(&path); - if (vol < 0) return FR_INVALID_DRIVE; - fs = FatFs[vol]; - if (!fs) return FR_NOT_ENABLED; - fs->fs_type = 0; - pdrv = LD2PD(vol); /* Physical drive */ - part = LD2PT(vol); /* Partition (0:auto detect, 1-4:get from partition table)*/ - - /* Get disk statics */ - stat = disk_initialize(pdrv); - if (stat & STA_NOINIT) return FR_NOT_READY; - if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; -#if _MAX_SS != _MIN_SS /* Get disk sector size */ - if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > _MAX_SS || SS(fs) < _MIN_SS) - return FR_DISK_ERR; -#endif - if (_MULTI_PARTITION && part) { - /* Get partition information from partition table in the MBR */ - if (disk_read(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR; - if (LD_WORD(fs->win + BS_55AA) != 0xAA55) return FR_MKFS_ABORTED; - tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE]; - if (!tbl[4]) return FR_MKFS_ABORTED; /* No partition? */ - b_vol = LD_DWORD(tbl + 8); /* Volume start sector */ - n_vol = LD_DWORD(tbl + 12); /* Volume size */ - } else { - /* Create a partition in this function */ - if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128) - return FR_DISK_ERR; - b_vol = (sfd) ? 0 : 63; /* Volume start sector */ - n_vol -= b_vol; /* Volume size */ - } - - if (au & (au - 1)) au = 0; - if (!au) { /* AU auto selection */ - vs = n_vol / (2000 / (SS(fs) / 512)); - for (i = 0; vs < vst[i]; i++) ; - au = cst[i]; - } - if (au >= _MIN_SS) au /= SS(fs); /* Number of sectors per cluster */ - if (!au) au = 1; - if (au > 128) au = 128; - - /* Pre-compute number of clusters and FAT sub-type */ - n_clst = n_vol / au; - fmt = FS_FAT12; - if (n_clst >= MIN_FAT16) fmt = FS_FAT16; - if (n_clst >= MIN_FAT32) fmt = FS_FAT32; - - /* Determine offset and size of FAT structure */ - if (fmt == FS_FAT32) { - n_fat = ((n_clst * 4) + 8 + SS(fs) - 1) / SS(fs); - n_rsv = 32; - n_dir = 0; - } else { - n_fat = (fmt == FS_FAT12) ? (n_clst * 3 + 1) / 2 + 3 : (n_clst * 2) + 4; - n_fat = (n_fat + SS(fs) - 1) / SS(fs); - n_rsv = 1; - n_dir = (DWORD)N_ROOTDIR * SZ_DIRE / SS(fs); - } - b_fat = b_vol + n_rsv; /* FAT area start sector */ - b_dir = b_fat + n_fat * N_FATS; /* Directory area start sector */ - b_data = b_dir + n_dir; /* Data area start sector */ - if (n_vol < b_data + au - b_vol) return FR_MKFS_ABORTED; /* Too small volume */ - - /* Align data start sector to erase block boundary (for flash memory media) */ - if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1; - n = (b_data + n - 1) & ~(n - 1); /* Next nearest erase block from current data start */ - n = (n - b_data) / N_FATS; - if (fmt == FS_FAT32) { /* FAT32: Move FAT offset */ - n_rsv += n; - b_fat += n; - } else { /* FAT12/16: Expand FAT size */ - n_fat += n; - } - - /* Determine number of clusters and final check of validity of the FAT sub-type */ - n_clst = (n_vol - n_rsv - n_fat * N_FATS - n_dir) / au; - if ( (fmt == FS_FAT16 && n_clst < MIN_FAT16) - || (fmt == FS_FAT32 && n_clst < MIN_FAT32)) - return FR_MKFS_ABORTED; - - /* Determine system ID in the partition table */ - if (fmt == FS_FAT32) { - sys = 0x0C; /* FAT32X */ - } else { - if (fmt == FS_FAT12 && n_vol < 0x10000) { - sys = 0x01; /* FAT12(<65536) */ - } else { - sys = (n_vol < 0x10000) ? 0x04 : 0x06; /* FAT16(<65536) : FAT12/16(>=65536) */ - } - } - - if (_MULTI_PARTITION && part) { - /* Update system ID in the partition table */ - tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE]; - tbl[4] = sys; - if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) /* Write it to teh MBR */ - return FR_DISK_ERR; - md = 0xF8; - } else { - if (sfd) { /* No partition table (SFD) */ - md = 0xF0; - } else { /* Create partition table (FDISK) */ - mem_set(fs->win, 0, SS(fs)); - tbl = fs->win + MBR_Table; /* Create partition table for single partition in the drive */ - tbl[1] = 1; /* Partition start head */ - tbl[2] = 1; /* Partition start sector */ - tbl[3] = 0; /* Partition start cylinder */ - tbl[4] = sys; /* System type */ - tbl[5] = 254; /* Partition end head */ - n = (b_vol + n_vol) / 63 / 255; - tbl[6] = (BYTE)(n >> 2 | 63); /* Partition end sector */ - tbl[7] = (BYTE)n; /* End cylinder */ - ST_DWORD(tbl + 8, 63); /* Partition start in LBA */ - ST_DWORD(tbl + 12, n_vol); /* Partition size in LBA */ - ST_WORD(fs->win + BS_55AA, 0xAA55); /* MBR signature */ - if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) /* Write it to the MBR */ - return FR_DISK_ERR; - md = 0xF8; - } - } - - /* Create BPB in the VBR */ - tbl = fs->win; /* Clear sector */ - mem_set(tbl, 0, SS(fs)); - mem_cpy(tbl, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code, OEM name */ - i = SS(fs); /* Sector size */ - ST_WORD(tbl + BPB_BytsPerSec, i); - tbl[BPB_SecPerClus] = (BYTE)au; /* Sectors per cluster */ - ST_WORD(tbl + BPB_RsvdSecCnt, n_rsv); /* Reserved sectors */ - tbl[BPB_NumFATs] = N_FATS; /* Number of FATs */ - i = (fmt == FS_FAT32) ? 0 : N_ROOTDIR; /* Number of root directory entries */ - ST_WORD(tbl + BPB_RootEntCnt, i); - if (n_vol < 0x10000) { /* Number of total sectors */ - ST_WORD(tbl + BPB_TotSec16, n_vol); - } else { - ST_DWORD(tbl + BPB_TotSec32, n_vol); - } - tbl[BPB_Media] = md; /* Media descriptor */ - ST_WORD(tbl + BPB_SecPerTrk, 63); /* Number of sectors per track */ - ST_WORD(tbl + BPB_NumHeads, 255); /* Number of heads */ - ST_DWORD(tbl + BPB_HiddSec, b_vol); /* Hidden sectors */ - n = GET_FATTIME(); /* Use current time as VSN */ - if (fmt == FS_FAT32) { - ST_DWORD(tbl + BS_VolID32, n); /* VSN */ - ST_DWORD(tbl + BPB_FATSz32, n_fat); /* Number of sectors per FAT */ - ST_DWORD(tbl + BPB_RootClus, 2); /* Root directory start cluster (2) */ - ST_WORD(tbl + BPB_FSInfo, 1); /* FSINFO record offset (VBR + 1) */ - ST_WORD(tbl + BPB_BkBootSec, 6); /* Backup boot record offset (VBR + 6) */ - tbl[BS_DrvNum32] = 0x80; /* Drive number */ - tbl[BS_BootSig32] = 0x29; /* Extended boot signature */ - mem_cpy(tbl + BS_VolLab32, "NO NAME " "FAT32 ", 19); /* Volume label, FAT signature */ - } else { - ST_DWORD(tbl + BS_VolID, n); /* VSN */ - ST_WORD(tbl + BPB_FATSz16, n_fat); /* Number of sectors per FAT */ - tbl[BS_DrvNum] = 0x80; /* Drive number */ - tbl[BS_BootSig] = 0x29; /* Extended boot signature */ - mem_cpy(tbl + BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */ - } - ST_WORD(tbl + BS_55AA, 0xAA55); /* Signature (Offset is fixed here regardless of sector size) */ - if (disk_write(pdrv, tbl, b_vol, 1) != RES_OK) /* Write it to the VBR sector */ - return FR_DISK_ERR; - if (fmt == FS_FAT32) /* Write backup VBR if needed (VBR + 6) */ - disk_write(pdrv, tbl, b_vol + 6, 1); - - /* Initialize FAT area */ - wsect = b_fat; - for (i = 0; i < N_FATS; i++) { /* Initialize each FAT copy */ - mem_set(tbl, 0, SS(fs)); /* 1st sector of the FAT */ - n = md; /* Media descriptor byte */ - if (fmt != FS_FAT32) { - n |= (fmt == FS_FAT12) ? 0x00FFFF00 : 0xFFFFFF00; - ST_DWORD(tbl + 0, n); /* Reserve cluster #0-1 (FAT12/16) */ - } else { - n |= 0xFFFFFF00; - ST_DWORD(tbl + 0, n); /* Reserve cluster #0-1 (FAT32) */ - ST_DWORD(tbl + 4, 0xFFFFFFFF); - ST_DWORD(tbl + 8, 0x0FFFFFFF); /* Reserve cluster #2 for root directory */ - } - if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK) - return FR_DISK_ERR; - mem_set(tbl, 0, SS(fs)); /* Fill following FAT entries with zero */ - for (n = 1; n < n_fat; n++) { /* This loop may take a time on FAT32 volume due to many single sector writes */ - if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK) - return FR_DISK_ERR; - } - } - - /* Initialize root directory */ - i = (fmt == FS_FAT32) ? au : (UINT)n_dir; - do { - if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK) - return FR_DISK_ERR; - } while (--i); - -#if _USE_TRIM /* Erase data area if needed */ - { - eb[0] = wsect; eb[1] = wsect + (n_clst - ((fmt == FS_FAT32) ? 1 : 0)) * au - 1; - disk_ioctl(pdrv, CTRL_TRIM, eb); - } -#endif - - /* Create FSINFO if needed */ - if (fmt == FS_FAT32) { - ST_DWORD(tbl + FSI_LeadSig, 0x41615252); - ST_DWORD(tbl + FSI_StrucSig, 0x61417272); - ST_DWORD(tbl + FSI_Free_Count, n_clst - 1); /* Number of free clusters */ - ST_DWORD(tbl + FSI_Nxt_Free, 2); /* Last allocated cluster# */ - ST_WORD(tbl + BS_55AA, 0xAA55); - disk_write(pdrv, tbl, b_vol + 1, 1); /* Write original (VBR + 1) */ - disk_write(pdrv, tbl, b_vol + 7, 1); /* Write backup (VBR + 7) */ - } - - return (disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR; -} - - - -#if _MULTI_PARTITION -/*-----------------------------------------------------------------------*/ -/* Create partition table on the physical drive */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_fdisk ( - BYTE pdrv, /* Physical drive number */ - const DWORD szt[], /* Pointer to the size table for each partitions */ - void* work /* Pointer to the working buffer */ -) -{ - UINT i, n, sz_cyl, tot_cyl, b_cyl, e_cyl, p_cyl; - BYTE s_hd, e_hd, *p, *buf = (BYTE*)work; - DSTATUS stat; - DWORD sz_disk, sz_part, s_part; - - - stat = disk_initialize(pdrv); - if (stat & STA_NOINIT) return FR_NOT_READY; - if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; - if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR; - - /* Determine CHS in the table regardless of the drive geometry */ - for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ; - if (n == 256) n--; - e_hd = n - 1; - sz_cyl = 63 * n; - tot_cyl = sz_disk / sz_cyl; - - /* Create partition table */ - mem_set(buf, 0, _MAX_SS); - p = buf + MBR_Table; b_cyl = 0; - for (i = 0; i < 4; i++, p += SZ_PTE) { - p_cyl = (szt[i] <= 100U) ? (DWORD)tot_cyl * szt[i] / 100 : szt[i] / sz_cyl; - if (!p_cyl) continue; - s_part = (DWORD)sz_cyl * b_cyl; - sz_part = (DWORD)sz_cyl * p_cyl; - if (i == 0) { /* Exclude first track of cylinder 0 */ - s_hd = 1; - s_part += 63; sz_part -= 63; - } else { - s_hd = 0; - } - e_cyl = b_cyl + p_cyl - 1; - if (e_cyl >= tot_cyl) return FR_INVALID_PARAMETER; - - /* Set partition table */ - p[1] = s_hd; /* Start head */ - p[2] = (BYTE)((b_cyl >> 2) + 1); /* Start sector */ - p[3] = (BYTE)b_cyl; /* Start cylinder */ - p[4] = 0x06; /* System type (temporary setting) */ - p[5] = e_hd; /* End head */ - p[6] = (BYTE)((e_cyl >> 2) + 63); /* End sector */ - p[7] = (BYTE)e_cyl; /* End cylinder */ - ST_DWORD(p + 8, s_part); /* Start sector in LBA */ - ST_DWORD(p + 12, sz_part); /* Partition size */ - - /* Next partition */ - b_cyl += p_cyl; - } - ST_WORD(p, 0xAA55); - - /* Write it to the MBR */ - return (disk_write(pdrv, buf, 0, 1) != RES_OK || disk_ioctl(pdrv, CTRL_SYNC, 0) != RES_OK) ? FR_DISK_ERR : FR_OK; -} - - -#endif /* _MULTI_PARTITION */ -#endif /* _USE_MKFS && !_FS_READONLY */ - - - - -#if _USE_STRFUNC -/*-----------------------------------------------------------------------*/ -/* Get a string from the file */ -/*-----------------------------------------------------------------------*/ - -TCHAR* f_gets ( - TCHAR* buff, /* Pointer to the string buffer to read */ - int len, /* Size of string buffer (characters) */ - FIL* fp /* Pointer to the file object */ -) -{ - int n = 0; - TCHAR c, *p = buff; - BYTE s[2]; - UINT rc; - - - while (n < len - 1) { /* Read characters until buffer gets filled */ -#if _USE_LFN && _LFN_UNICODE -#if _STRF_ENCODE == 3 /* Read a character in UTF-8 */ - f_read(fp, s, 1, &rc); - if (rc != 1) break; - c = s[0]; - if (c >= 0x80) { - if (c < 0xC0) continue; /* Skip stray trailer */ - if (c < 0xE0) { /* Two-byte sequence */ - f_read(fp, s, 1, &rc); - if (rc != 1) break; - c = (c & 0x1F) << 6 | (s[0] & 0x3F); - if (c < 0x80) c = '?'; - } else { - if (c < 0xF0) { /* Three-byte sequence */ - f_read(fp, s, 2, &rc); - if (rc != 2) break; - c = c << 12 | (s[0] & 0x3F) << 6 | (s[1] & 0x3F); - if (c < 0x800) c = '?'; - } else { /* Reject four-byte sequence */ - c = '?'; - } - } - } -#elif _STRF_ENCODE == 2 /* Read a character in UTF-16BE */ - f_read(fp, s, 2, &rc); - if (rc != 2) break; - c = s[1] + (s[0] << 8); -#elif _STRF_ENCODE == 1 /* Read a character in UTF-16LE */ - f_read(fp, s, 2, &rc); - if (rc != 2) break; - c = s[0] + (s[1] << 8); -#else /* Read a character in ANSI/OEM */ - f_read(fp, s, 1, &rc); - if (rc != 1) break; - c = s[0]; - if (IsDBCS1(c)) { - f_read(fp, s, 1, &rc); - if (rc != 1) break; - c = (c << 8) + s[0]; - } - c = ff_convert(c, 1); /* OEM -> Unicode */ - if (!c) c = '?'; -#endif -#else /* Read a character without conversion */ - f_read(fp, s, 1, &rc); - if (rc != 1) break; - c = s[0]; -#endif - if (_USE_STRFUNC == 2 && c == '\r') continue; /* Strip '\r' */ - *p++ = c; - n++; - if (c == '\n') break; /* Break on EOL */ - } - *p = 0; - return n ? buff : 0; /* When no data read (eof or error), return with error. */ -} - - - - -#if !_FS_READONLY -#include -/*-----------------------------------------------------------------------*/ -/* Put a character to the file */ -/*-----------------------------------------------------------------------*/ - -typedef struct { - FIL* fp; - int idx, nchr; - BYTE buf[64]; -} putbuff; - - -static -void putc_bfd ( - putbuff* pb, - TCHAR c -) -{ - UINT bw; - int i; - - - if (_USE_STRFUNC == 2 && c == '\n') /* LF -> CRLF conversion */ - putc_bfd(pb, '\r'); - - i = pb->idx; /* Buffer write index (-1:error) */ - if (i < 0) return; - -#if _USE_LFN && _LFN_UNICODE -#if _STRF_ENCODE == 3 /* Write a character in UTF-8 */ - if (c < 0x80) { /* 7-bit */ - pb->buf[i++] = (BYTE)c; - } else { - if (c < 0x800) { /* 11-bit */ - pb->buf[i++] = (BYTE)(0xC0 | c >> 6); - } else { /* 16-bit */ - pb->buf[i++] = (BYTE)(0xE0 | c >> 12); - pb->buf[i++] = (BYTE)(0x80 | (c >> 6 & 0x3F)); - } - pb->buf[i++] = (BYTE)(0x80 | (c & 0x3F)); - } -#elif _STRF_ENCODE == 2 /* Write a character in UTF-16BE */ - pb->buf[i++] = (BYTE)(c >> 8); - pb->buf[i++] = (BYTE)c; -#elif _STRF_ENCODE == 1 /* Write a character in UTF-16LE */ - pb->buf[i++] = (BYTE)c; - pb->buf[i++] = (BYTE)(c >> 8); -#else /* Write a character in ANSI/OEM */ - c = ff_convert(c, 0); /* Unicode -> OEM */ - if (!c) c = '?'; - if (c >= 0x100) - pb->buf[i++] = (BYTE)(c >> 8); - pb->buf[i++] = (BYTE)c; -#endif -#else /* Write a character without conversion */ - pb->buf[i++] = (BYTE)c; -#endif - - if (i >= (int)(sizeof pb->buf) - 3) { /* Write buffered characters to the file */ - f_write(pb->fp, pb->buf, (UINT)i, &bw); - i = (bw == (UINT)i) ? 0 : -1; - } - pb->idx = i; - pb->nchr++; -} - - - -int f_putc ( - TCHAR c, /* A character to be output */ - FIL* fp /* Pointer to the file object */ -) -{ - putbuff pb; - UINT nw; - - - pb.fp = fp; /* Initialize output buffer */ - pb.nchr = pb.idx = 0; - - putc_bfd(&pb, c); /* Put a character */ - - if ( pb.idx >= 0 /* Flush buffered characters to the file */ - && f_write(pb.fp, pb.buf, (UINT)pb.idx, &nw) == FR_OK - && (UINT)pb.idx == nw) return pb.nchr; - return EOF; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Put a string to the file */ -/*-----------------------------------------------------------------------*/ - -int f_puts ( - const TCHAR* str, /* Pointer to the string to be output */ - FIL* fp /* Pointer to the file object */ -) -{ - putbuff pb; - UINT nw; - - - pb.fp = fp; /* Initialize output buffer */ - pb.nchr = pb.idx = 0; - - while (*str) /* Put the string */ - putc_bfd(&pb, *str++); - - if ( pb.idx >= 0 /* Flush buffered characters to the file */ - && f_write(pb.fp, pb.buf, (UINT)pb.idx, &nw) == FR_OK - && (UINT)pb.idx == nw) return pb.nchr; - return EOF; -} - - - - -/*-----------------------------------------------------------------------*/ -/* Put a formatted string to the file */ -/*-----------------------------------------------------------------------*/ - -int f_printf ( - FIL* fp, /* Pointer to the file object */ - const TCHAR* fmt, /* Pointer to the format string */ - ... /* Optional arguments... */ -) -{ - va_list arp; - BYTE f, r; - UINT nw, i, j, w; - DWORD v; - TCHAR c, d, s[16], *p; - putbuff pb; - - - pb.fp = fp; /* Initialize output buffer */ - pb.nchr = pb.idx = 0; - - va_start(arp, fmt); - - for (;;) { - c = *fmt++; - if (c == 0) break; /* End of string */ - if (c != '%') { /* Non escape character */ - putc_bfd(&pb, c); - continue; - } - w = f = 0; - c = *fmt++; - if (c == '0') { /* Flag: '0' padding */ - f = 1; c = *fmt++; - } else { - if (c == '-') { /* Flag: left justified */ - f = 2; c = *fmt++; - } - } - while (IsDigit(c)) { /* Precision */ - w = w * 10 + c - '0'; - c = *fmt++; - } - if (c == 'l' || c == 'L') { /* Prefix: Size is long int */ - f |= 4; c = *fmt++; - } - if (!c) break; - d = c; - if (IsLower(d)) d -= 0x20; - switch (d) { /* Type is... */ - case 'S' : /* String */ - p = va_arg(arp, TCHAR*); - for (j = 0; p[j]; j++) ; - if (!(f & 2)) { - while (j++ < w) putc_bfd(&pb, ' '); - } - while (*p) putc_bfd(&pb, *p++); - while (j++ < w) putc_bfd(&pb, ' '); - continue; - case 'C' : /* Character */ - putc_bfd(&pb, (TCHAR)va_arg(arp, int)); continue; - case 'B' : /* Binary */ - r = 2; break; - case 'O' : /* Octal */ - r = 8; break; - case 'D' : /* Signed decimal */ - case 'U' : /* Unsigned decimal */ - r = 10; break; - case 'X' : /* Hexdecimal */ - r = 16; break; - default: /* Unknown type (pass-through) */ - putc_bfd(&pb, c); continue; - } - - /* Get an argument and put it in numeral */ - v = (f & 4) ? (DWORD)va_arg(arp, long) : ((d == 'D') ? (DWORD)(long)va_arg(arp, int) : (DWORD)va_arg(arp, unsigned int)); - if (d == 'D' && (v & 0x80000000)) { - v = 0 - v; - f |= 8; - } - i = 0; - do { - d = (TCHAR)(v % r); v /= r; - if (d > 9) d += (c == 'x') ? 0x27 : 0x07; - s[i++] = d + '0'; - } while (v && i < sizeof s / sizeof s[0]); - if (f & 8) s[i++] = '-'; - j = i; d = (f & 1) ? '0' : ' '; - while (!(f & 2) && j++ < w) putc_bfd(&pb, d); - do putc_bfd(&pb, s[--i]); while (i); - while (j++ < w) putc_bfd(&pb, d); - } - - va_end(arp); - - if ( pb.idx >= 0 /* Flush buffered characters to the file */ - && f_write(pb.fp, pb.buf, (UINT)pb.idx, &nw) == FR_OK - && (UINT)pb.idx == nw) return pb.nchr; - return EOF; -} - -#endif /* !_FS_READONLY */ -#endif /* _USE_STRFUNC */ diff --git a/Sming/Arch/Esp8266/Components/fatfs/ff.h b/Sming/Arch/Esp8266/Components/fatfs/ff.h deleted file mode 100644 index 22f1810b27..0000000000 --- a/Sming/Arch/Esp8266/Components/fatfs/ff.h +++ /dev/null @@ -1,350 +0,0 @@ -/*---------------------------------------------------------------------------/ -/ FatFs - FAT file system module include R0.11 (C)ChaN, 2015 -/----------------------------------------------------------------------------/ -/ FatFs module is a free software that opened under license policy of -/ following conditions. -/ -/ Copyright (C) 2015, ChaN, all right reserved. -/ -/ 1. Redistributions of source code must retain the above copyright notice, -/ this condition and the following disclaimer. -/ -/ This software is provided by the copyright holder and contributors "AS IS" -/ and any warranties related to this software are DISCLAIMED. -/ The copyright owner or contributors be NOT LIABLE for any damages caused -/ by use of this software. -/---------------------------------------------------------------------------*/ - - -#ifndef _FATFS -#define _FATFS 32020 /* Revision ID */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "integer.h" /* Basic integer types */ -#include "ffconf.h" /* FatFs configuration options */ -#if _FATFS != _FFCONF -#error Wrong configuration file (ffconf.h). -#endif - - - -/* Definitions of volume management */ - -#if _MULTI_PARTITION /* Multiple partition configuration */ -typedef struct { - BYTE pd; /* Physical drive number */ - BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */ -} PARTITION; -extern PARTITION VolToPart[]; /* Volume - Partition resolution table */ -#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */ -#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */ - -#else /* Single partition configuration */ -#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */ -#define LD2PT(vol) 0 /* Find first valid partition or in SFD */ - -#endif - - - -/* Type of path name strings on FatFs API */ - -#if _LFN_UNICODE /* Unicode string */ -#if !_USE_LFN -#error _LFN_UNICODE must be 0 at non-LFN cfg. -#endif -#ifndef _INC_TCHAR -typedef WCHAR TCHAR; -#define _T(x) L ## x -#define _TEXT(x) L ## x -#endif - -#else /* ANSI/OEM string */ -#ifndef _INC_TCHAR -typedef char TCHAR; -#define _T(x) x -#define _TEXT(x) x -#endif - -#endif - - - -/* File system object structure (FATFS) */ - -typedef struct { - BYTE fs_type; /* FAT sub-type (0:Not mounted) */ - BYTE drv; /* Physical drive number */ - BYTE csize; /* Sectors per cluster (1,2,4...128) */ - BYTE n_fats; /* Number of FAT copies (1 or 2) */ - BYTE wflag; /* win[] flag (b0:dirty) */ - BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */ - WORD id; /* File system mount ID */ - WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ -#if _MAX_SS != _MIN_SS - WORD ssize; /* Bytes per sector (512, 1024, 2048 or 4096) */ -#endif -#if _FS_REENTRANT - _SYNC_t sobj; /* Identifier of sync object */ -#endif -#if !_FS_READONLY - DWORD last_clust; /* Last allocated cluster */ - DWORD free_clust; /* Number of free clusters */ -#endif -#if _FS_RPATH - DWORD cdir; /* Current directory start cluster (0:root) */ -#endif - DWORD n_fatent; /* Number of FAT entries, = number of clusters + 2 */ - DWORD fsize; /* Sectors per FAT */ - DWORD volbase; /* Volume start sector */ - DWORD fatbase; /* FAT start sector */ - DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */ - DWORD database; /* Data start sector */ - DWORD winsect; /* Current sector appearing in the win[] */ - BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */ -} FATFS; - - - -/* File object structure (FIL) */ - -typedef struct { - FATFS* fs; /* Pointer to the related file system object (**do not change order**) */ - WORD id; /* Owner file system mount ID (**do not change order**) */ - BYTE flag; /* Status flags */ - BYTE err; /* Abort flag (error code) */ - DWORD fptr; /* File read/write pointer (Zeroed on file open) */ - DWORD fsize; /* File size */ - DWORD sclust; /* File start cluster (0:no cluster chain, always 0 when fsize is 0) */ - DWORD clust; /* Current cluster of fpter (not valid when fprt is 0) */ - DWORD dsect; /* Sector number appearing in buf[] (0:invalid) */ -#if !_FS_READONLY - DWORD dir_sect; /* Sector number containing the directory entry */ - BYTE* dir_ptr; /* Pointer to the directory entry in the win[] */ -#endif -#if _USE_FASTSEEK - DWORD* cltbl; /* Pointer to the cluster link map table (Nulled on file open) */ -#endif -#if _FS_LOCK - UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */ -#endif -#if !_FS_TINY - BYTE buf[_MAX_SS]; /* File private data read/write window */ -#endif -} FIL; - - - -/* Directory object structure (DIR) */ - -typedef struct { - FATFS* fs; /* Pointer to the owner file system object (**do not change order**) */ - WORD id; /* Owner file system mount ID (**do not change order**) */ - WORD index; /* Current read/write index number */ - DWORD sclust; /* Table start cluster (0:Root dir) */ - DWORD clust; /* Current cluster */ - DWORD sect; /* Current sector */ - BYTE* dir; /* Pointer to the current SFN entry in the win[] */ - BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */ -#if _FS_LOCK - UINT lockid; /* File lock ID (index of file semaphore table Files[]) */ -#endif -#if _USE_LFN - WCHAR* lfn; /* Pointer to the LFN working buffer */ - WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */ -#endif -#if _USE_FIND - const TCHAR* pat; /* Pointer to the name matching pattern */ -#endif -} DIR; - - - -/* File information structure (FILINFO) */ - -typedef struct { - DWORD fsize; /* File size */ - WORD fdate; /* Last modified date */ - WORD ftime; /* Last modified time */ - BYTE fattrib; /* Attribute */ - TCHAR fname[13]; /* Short file name (8.3 format) */ -#if _USE_LFN - TCHAR* lfname; /* Pointer to the LFN buffer */ - UINT lfsize; /* Size of LFN buffer in TCHAR */ -#endif -} FILINFO; - - - -/* File function return code (FRESULT) */ - -typedef enum { - FR_OK = 0, /* (0) Succeeded */ - FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */ - FR_INT_ERR, /* (2) Assertion failed */ - FR_NOT_READY, /* (3) The physical drive cannot work */ - FR_NO_FILE, /* (4) Could not find the file */ - FR_NO_PATH, /* (5) Could not find the path */ - FR_INVALID_NAME, /* (6) The path name format is invalid */ - FR_DENIED, /* (7) Access denied due to prohibited access or directory full */ - FR_EXIST, /* (8) Access denied due to prohibited access */ - FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ - FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ - FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ - FR_NOT_ENABLED, /* (12) The volume has no work area */ - FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ - FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */ - FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ - FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ - FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ - FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */ - FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ -} FRESULT; - - - -/*--------------------------------------------------------------*/ -/* FatFs module application interface */ - -FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */ -FRESULT f_close (FIL* fp); /* Close an open file object */ -FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from a file */ -FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to a file */ -FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */ -FRESULT f_lseek (FIL* fp, DWORD ofs); /* Move file pointer of a file object */ -FRESULT f_truncate (FIL* fp); /* Truncate file */ -FRESULT f_sync (FIL* fp); /* Flush cached data of a writing file */ -FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */ -FRESULT f_closedir (DIR* dp); /* Close an open directory */ -FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */ -FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */ -FRESULT f_findnext (DIR* dp, FILINFO* fno); /* Find next file */ -FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */ -FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */ -FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */ -FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */ -FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of the file/dir */ -FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change times-tamp of the file/dir */ -FRESULT f_chdir (const TCHAR* path); /* Change current directory */ -FRESULT f_chdrive (const TCHAR* path); /* Change current drive */ -FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */ -FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */ -FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */ -FRESULT f_setlabel (const TCHAR* label); /* Set volume label */ -FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */ -FRESULT f_mkfs (const TCHAR* path, BYTE sfd, UINT au); /* Create a file system on the volume */ -FRESULT f_fdisk (BYTE pdrv, const DWORD szt[], void* work); /* Divide a physical drive into some partitions */ -int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */ -int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */ -int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */ -TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */ - -#define f_eof(fp) ((int)((fp)->fptr == (fp)->fsize)) -#define f_error(fp) ((fp)->err) -#define f_tell(fp) ((fp)->fptr) -#define f_size(fp) ((fp)->fsize) -#define f_rewind(fp) f_lseek((fp), 0) -#define f_rewinddir(dp) f_readdir((dp), 0) - -#ifndef EOF -#define EOF (-1) -#endif - - - - -/*--------------------------------------------------------------*/ -/* Additional user defined functions */ - -/* RTC function */ -#if !_FS_READONLY && !_FS_NORTC -DWORD get_fattime (void); -#endif - -/* Unicode support functions */ -#if _USE_LFN /* Unicode - OEM code conversion */ -WCHAR ff_convert (WCHAR chr, UINT dir); /* OEM-Unicode bidirectional conversion */ -WCHAR ff_wtoupper (WCHAR chr); /* Unicode upper-case conversion */ -#if _USE_LFN == 3 /* Memory functions */ -void* ff_memalloc (UINT msize); /* Allocate memory block */ -void ff_memfree (void* mblock); /* Free memory block */ -#endif -#endif - -/* Sync functions */ -#if _FS_REENTRANT -int ff_cre_syncobj (BYTE vol, _SYNC_t* sobj); /* Create a sync object */ -int ff_req_grant (_SYNC_t sobj); /* Lock sync object */ -void ff_rel_grant (_SYNC_t sobj); /* Unlock sync object */ -int ff_del_syncobj (_SYNC_t sobj); /* Delete a sync object */ -#endif - - - - -/*--------------------------------------------------------------*/ -/* Flags and offset address */ - - -/* File access control and file status flags (FIL.flag) */ - -#define FA_READ 0x01 -#define FA_OPEN_EXISTING 0x00 - -#if !_FS_READONLY -#define FA_WRITE 0x02 -#define FA_CREATE_NEW 0x04 -#define FA_CREATE_ALWAYS 0x08 -#define FA_OPEN_ALWAYS 0x10 -#define FA__WRITTEN 0x20 -#define FA__DIRTY 0x40 -#endif - - -/* FAT sub type (FATFS.fs_type) */ - -#define FS_FAT12 1 -#define FS_FAT16 2 -#define FS_FAT32 3 - - -/* File attribute bits for directory entry */ - -#define AM_RDO 0x01 /* Read only */ -#define AM_HID 0x02 /* Hidden */ -#define AM_SYS 0x04 /* System */ -#define AM_VOL 0x08 /* Volume label */ -#define AM_LFN 0x0F /* LFN entry */ -#define AM_DIR 0x10 /* Directory */ -#define AM_ARC 0x20 /* Archive */ -#define AM_MASK 0x3F /* Mask of defined bits */ - - -/* Fast seek feature */ -#define CREATE_LINKMAP 0xFFFFFFFF - - - -/*--------------------------------*/ -/* Multi-byte word access macros */ - -#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */ -#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr)) -#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr)) -#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val) -#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val) -#else /* Use byte-by-byte access to the FAT structure */ -#define LD_WORD(ptr) (WORD)(((WORD)*((BYTE*)(ptr)+1)<<8)|(WORD)*(BYTE*)(ptr)) -#define LD_DWORD(ptr) (DWORD)(((DWORD)*((BYTE*)(ptr)+3)<<24)|((DWORD)*((BYTE*)(ptr)+2)<<16)|((WORD)*((BYTE*)(ptr)+1)<<8)|*(BYTE*)(ptr)) -#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8) -#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8); *((BYTE*)(ptr)+2)=(BYTE)((DWORD)(val)>>16); *((BYTE*)(ptr)+3)=(BYTE)((DWORD)(val)>>24) -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _FATFS */ diff --git a/Sming/Arch/Esp8266/Components/fatfs/ffconf.h b/Sming/Arch/Esp8266/Components/fatfs/ffconf.h deleted file mode 100644 index 9f77061925..0000000000 --- a/Sming/Arch/Esp8266/Components/fatfs/ffconf.h +++ /dev/null @@ -1,266 +0,0 @@ -/*---------------------------------------------------------------------------/ -/ FatFs - FAT file system module configuration file R0.11 (C)ChaN, 2015 -/---------------------------------------------------------------------------*/ - -#define _FFCONF 32020 /* Revision ID */ - -/*---------------------------------------------------------------------------/ -/ Functions and Buffer Configurations -/---------------------------------------------------------------------------*/ - -#define _FS_TINY 1 -/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) -/ At the tiny configuration, size of the file object (FIL) is reduced _MAX_SS -/ bytes. Instead of private sector buffer eliminated from the file object, -/ common sector buffer in the file system object (FATFS) is used for the file -/ data transfer. */ - - -#define _FS_READONLY 0 -/* This option switches read-only configuration. (0:Read/Write or 1:Read-only) -/ Read-only configuration removes writing API functions, f_write(), f_sync(), -/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree() -/ and optional writing functions as well. */ - - -#define _FS_MINIMIZE 0 -/* This option defines minimization level to remove some basic API functions. -/ -/ 0: All basic functions are enabled. -/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_chmod(), f_utime(), -/ f_truncate() and f_rename() function are removed. -/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1. -/ 3: f_lseek() function is removed in addition to 2. */ - - -#define _USE_STRFUNC 1 -/* This option switches string functions, f_gets(), f_putc(), f_puts() and -/ f_printf(). -/ -/ 0: Disable string functions. -/ 1: Enable without LF-CRLF conversion. -/ 2: Enable with LF-CRLF conversion. */ - - -#define _USE_FIND 1 -/* This option switches filtered directory read feature and related functions, -/ f_findfirst() and f_findnext(). (0:Disable or 1:Enable) */ - - -#define _USE_MKFS 0 -/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ - - -#define _USE_FASTSEEK 0 -/* This option switches fast seek feature. (0:Disable or 1:Enable) */ - - -#define _USE_LABEL 0 -/* This option switches volume label functions, f_getlabel() and f_setlabel(). -/ (0:Disable or 1:Enable) */ - - -#define _USE_FORWARD 0 -/* This option switches f_forward() function. (0:Disable or 1:Enable) -/ To enable it, also _FS_TINY need to be set to 1. */ - - -/*---------------------------------------------------------------------------/ -/ Locale and Namespace Configurations -/---------------------------------------------------------------------------*/ - -#define _CODE_PAGE 1 -/* This option specifies the OEM code page to be used on the target system. -/ Incorrect setting of the code page can cause a file open failure. -/ -/ 1 - ASCII (No extended character. Non-LFN cfg. only) -/ 437 - U.S. -/ 720 - Arabic -/ 737 - Greek -/ 775 - Baltic -/ 850 - Multilingual Latin 1 -/ 852 - Latin 2 -/ 855 - Cyrillic -/ 857 - Turkish -/ 858 - Multilingual Latin 1 + Euro -/ 862 - Hebrew -/ 866 - Russian -/ 874 - Thai -/ 932 - Japanese Shift_JIS (DBCS) -/ 936 - Simplified Chinese GBK (DBCS) -/ 949 - Korean (DBCS) -/ 950 - Traditional Chinese Big5 (DBCS) -*/ - - -#define _USE_LFN 0 -#define _MAX_LFN 255 -/* The _USE_LFN option switches the LFN feature. -/ -/ 0: Disable LFN feature. _MAX_LFN has no effect. -/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe. -/ 2: Enable LFN with dynamic working buffer on the STACK. -/ 3: Enable LFN with dynamic working buffer on the HEAP. -/ -/ When enable the LFN feature, Unicode handling functions (option/unicode.c) must -/ be added to the project. The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. -/ When use stack for the working buffer, take care on stack overflow. When use heap -/ memory for the working buffer, memory management functions, ff_memalloc() and -/ ff_memfree(), must be added to the project. */ - - -#define _LFN_UNICODE 0 -/* This option switches character encoding on the API. (0:ANSI/OEM or 1:Unicode) -/ To use Unicode string for the path name, enable LFN feature and set _LFN_UNICODE -/ to 1. This option also affects behavior of string I/O functions. */ - - -#define _STRF_ENCODE 3 -/* When _LFN_UNICODE is 1, this option selects the character encoding on the file to -/ be read/written via string I/O functions, f_gets(), f_putc(), f_puts and f_printf(). -/ -/ 0: ANSI/OEM -/ 1: UTF-16LE -/ 2: UTF-16BE -/ 3: UTF-8 -/ -/ When _LFN_UNICODE is 0, this option has no effect. */ - - -#define _FS_RPATH 0 -/* This option configures relative path feature. -/ -/ 0: Disable relative path feature and remove related functions. -/ 1: Enable relative path feature. f_chdir() and f_chdrive() are available. -/ 2: f_getcwd() function is available in addition to 1. -/ -/ Note that directory items read via f_readdir() are affected by this option. */ - - -/*---------------------------------------------------------------------------/ -/ Drive/Volume Configurations -/---------------------------------------------------------------------------*/ - -#define _VOLUMES 1 -/* Number of volumes (logical drives) to be used. */ - - -#define _STR_VOLUME_ID 0 -#define _VOLUME_STRS "RAM","NAND","CF","SD1","SD2","USB1","USB2","USB3" -/* _STR_VOLUME_ID option switches string volume ID feature. -/ When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive -/ number in the path name. _VOLUME_STRS defines the drive ID strings for each -/ logical drives. Number of items must be equal to _VOLUMES. Valid characters for -/ the drive ID strings are: A-Z and 0-9. */ - - -#define _MULTI_PARTITION 0 -/* This option switches multi-partition feature. By default (0), each logical drive -/ number is bound to the same physical drive number and only an FAT volume found on -/ the physical drive will be mounted. When multi-partition feature is enabled (1), -/ each logical drive number is bound to arbitrary physical drive and partition -/ listed in the VolToPart[]. Also f_fdisk() funciton will be available. */ - - -#define _MIN_SS 512 -#define _MAX_SS 512 -/* These options configure the range of sector size to be supported. (512, 1024, -/ 2048 or 4096) Always set both 512 for most systems, all type of memory cards and -/ harddisk. But a larger value may be required for on-board flash memory and some -/ type of optical media. When _MAX_SS is larger than _MIN_SS, FatFs is configured -/ to variable sector size and GET_SECTOR_SIZE command must be implemented to the -/ disk_ioctl() function. */ - - -#define _USE_TRIM 0 -/* This option switches ATA-TRIM feature. (0:Disable or 1:Enable) -/ To enable Trim feature, also CTRL_TRIM command should be implemented to the -/ disk_ioctl() function. */ - - -#define _FS_NOFSINFO 0 -/* If you need to know correct free space on the FAT32 volume, set bit 0 of this -/ option, and f_getfree() function at first time after volume mount will force -/ a full FAT scan. Bit 1 controls the use of last allocated cluster number. -/ -/ bit0=0: Use free cluster count in the FSINFO if available. -/ bit0=1: Do not trust free cluster count in the FSINFO. -/ bit1=0: Use last allocated cluster number in the FSINFO if available. -/ bit1=1: Do not trust last allocated cluster number in the FSINFO. -*/ - - - -/*---------------------------------------------------------------------------/ -/ System Configurations -/---------------------------------------------------------------------------*/ - -#define _FS_NORTC 1 -#define _NORTC_MON 2 -#define _NORTC_MDAY 1 -#define _NORTC_YEAR 2015 -/* The _FS_NORTC option switches timestamp feature. If the system does not have -/ an RTC function or valid timestamp is not needed, set _FS_NORTC to 1 to disable -/ the timestamp feature. All objects modified by FatFs will have a fixed timestamp -/ defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR. -/ When timestamp feature is enabled (_FS_NORTC == 0), get_fattime() function need -/ to be added to the project to read current time form RTC. _NORTC_MON, -/ _NORTC_MDAY and _NORTC_YEAR have no effect. -/ These options have no effect at read-only configuration (_FS_READONLY == 1). */ - - -#define _FS_LOCK 0 -/* The _FS_LOCK option switches file lock feature to control duplicated file open -/ and illegal operation to open objects. This option must be 0 when _FS_READONLY -/ is 1. -/ -/ 0: Disable file lock feature. To avoid volume corruption, application program -/ should avoid illegal open, remove and rename to the open objects. -/ >0: Enable file lock feature. The value defines how many files/sub-directories -/ can be opened simultaneously under file lock control. Note that the file -/ lock feature is independent of re-entrancy. */ - - -#define _FS_REENTRANT 0 -#define _FS_TIMEOUT 1000 -#define _SYNC_t HANDLE -/* The _FS_REENTRANT option switches the re-entrancy (thread safe) of the FatFs -/ module itself. Note that regardless of this option, file access to different -/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs() -/ and f_fdisk() function, are always not re-entrant. Only file/directory access -/ to the same volume is under control of this feature. -/ -/ 0: Disable re-entrancy. _FS_TIMEOUT and _SYNC_t have no effect. -/ 1: Enable re-entrancy. Also user provided synchronization handlers, -/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj() -/ function, must be added to the project. Samples are available in -/ option/syscall.c. -/ -/ The _FS_TIMEOUT defines timeout period in unit of time tick. -/ The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*, -/ SemaphoreHandle_t and etc.. */ - - -#define _WORD_ACCESS 0 -/* The _WORD_ACCESS option is an only platform dependent option. It defines -/ which access method is used to the word data on the FAT volume. -/ -/ 0: Byte-by-byte access. Always compatible with all platforms. -/ 1: Word access. Do not choose this unless under both the following conditions. -/ -/ * Address misaligned memory access is always allowed to ALL instructions. -/ * Byte order on the memory is little-endian. -/ -/ If it is the case, _WORD_ACCESS can also be set to 1 to reduce code size. -/ Following table shows allowable settings of some processor types. -/ -/ ARM7TDMI 0 ColdFire 0 V850E 0 -/ Cortex-M3 0 Z80 0/1 V850ES 0/1 -/ Cortex-M0 0 x86 0/1 TLCS-870 0/1 -/ AVR 0/1 RX600(LE) 0/1 TLCS-900 0/1 -/ AVR32 0 RL78 0 R32C 0 -/ PIC18 0/1 SH-2 0 M16C 0/1 -/ PIC24 0 H8S 0 MSP430 0 -/ PIC32 0 H8/300H 0 8051 0/1 -*/ - diff --git a/Sming/Arch/Esp8266/Components/fatfs/integer.h b/Sming/Arch/Esp8266/Components/fatfs/integer.h deleted file mode 100644 index 16ad408233..0000000000 --- a/Sming/Arch/Esp8266/Components/fatfs/integer.h +++ /dev/null @@ -1,37 +0,0 @@ -/*-------------------------------------------*/ -/* Integer type definitions for FatFs module */ -/*-------------------------------------------*/ - -#ifndef _INTEGER -#define _INTEGER - -#ifdef _WIN32 /* FatFs development platform */ - -#include -#include - -#else /* Embedded platform */ - -/* These types must be 16-bit, 32-bit or larger integer */ -typedef int INT; -typedef unsigned int UINT; - -/* These types must be 8-bit integer */ -typedef char CHAR; -typedef unsigned char UCHAR; -typedef unsigned char BYTE; - -/* These types must be 16-bit integer */ -typedef short SHORT; -typedef unsigned short USHORT; -typedef unsigned short WORD; -typedef unsigned short WCHAR; - -/* These types must be 32-bit integer */ -typedef long LONG; -typedef unsigned long ULONG; -typedef unsigned long DWORD; - -#endif - -#endif diff --git a/Sming/Arch/Esp8266/Components/gdbstub/README.rst b/Sming/Arch/Esp8266/Components/gdbstub/README.rst index 5d31aa46f7..6ca13e1e46 100644 --- a/Sming/Arch/Esp8266/Components/gdbstub/README.rst +++ b/Sming/Arch/Esp8266/Components/gdbstub/README.rst @@ -26,7 +26,7 @@ Note that ``target`` refers to the application being debugged, and ``host`` the development system running the GDB program. Refer to the official -`GDB documention `__ +`GDB documentation `__ for further details. GDB diff --git a/Sming/Arch/Esp8266/Components/gdbstub/appcode/gdb_hooks.cpp b/Sming/Arch/Esp8266/Components/gdbstub/appcode/gdb_hooks.cpp index 0aa256f4b0..8301718ba1 100644 --- a/Sming/Arch/Esp8266/Components/gdbstub/appcode/gdb_hooks.cpp +++ b/Sming/Arch/Esp8266/Components/gdbstub/appcode/gdb_hooks.cpp @@ -140,7 +140,7 @@ void dumpExceptionInfo() } // Main exception handler code -static void __attribute__((noinline)) gdbstub_exception_handler_flash(UserFrame* frame) +static void __noinline gdbstub_exception_handler_flash(UserFrame* frame) { // Copy registers the Xtensa HAL did save to gdbstub_savedRegs memcpy(&gdbstub_savedRegs, frame, 5 * 4); diff --git a/Sming/Arch/Esp8266/Components/gdbstub/gdbstub-cfg.h b/Sming/Arch/Esp8266/Components/gdbstub/gdbstub-cfg.h index 949998239e..01888975a1 100644 --- a/Sming/Arch/Esp8266/Components/gdbstub/gdbstub-cfg.h +++ b/Sming/Arch/Esp8266/Components/gdbstub/gdbstub-cfg.h @@ -152,7 +152,7 @@ #endif /** - * Some commands are not required by GDB, so if neccessary can be disabled to save memory. + * Some commands are not required by GDB, so if necessary can be disabled to save memory. */ // Read/write individual registers #ifndef GDBSTUB_CMDENABLE_P diff --git a/Sming/Arch/Esp8266/Components/gdbstub/gdbstub.cpp b/Sming/Arch/Esp8266/Components/gdbstub/gdbstub.cpp index 8e44b6ee06..b563af1e06 100644 --- a/Sming/Arch/Esp8266/Components/gdbstub/gdbstub.cpp +++ b/Sming/Arch/Esp8266/Components/gdbstub/gdbstub.cpp @@ -532,7 +532,7 @@ static GdbResult ATTR_GDBEXTERNFN handleCommand(unsigned cmdLen) * Single-step instruction * * Single-stepping can go wrong if an interrupt is pending, especially when it is e.g. a task switch: - * the ICOUNT register will overflow in the task switch code. That is why we disable interupts when + * the ICOUNT register will overflow in the task switch code. That is why we disable interrupts when * doing single-instruction stepping. */ case 's': @@ -811,7 +811,7 @@ static void ATTR_GDBEXTERNFN emulLdSt() } // Main exception handler -static void __attribute__((noinline)) gdbstub_handle_debug_exception_flash() +static void __noinline gdbstub_handle_debug_exception_flash() { debug_i(">> DBG 0x%02x, PC = %p", gdb_state.flags, gdbstub_savedRegs.pc); diff --git a/Sming/Arch/Esp8266/Components/heap/Kconfig b/Sming/Arch/Esp8266/Components/heap/Kconfig new file mode 100644 index 0000000000..b78223f531 --- /dev/null +++ b/Sming/Arch/Esp8266/Components/heap/Kconfig @@ -0,0 +1,20 @@ +menu "Heap" + config ENABLE_CUSTOM_HEAP + bool "Enable custom heap using UMM Malloc" + + if ENABLE_CUSTOM_HEAP + + config UMM_POISON_CHECK + bool "UMM Poison Check" + help + Add heap integrity checks + + config UMM_FUNC_IRAM + bool "Store custom heap functions in IRAM" + default y + help + Custom heap functions are stored in IRAM by default for performance reasons. + If you need the IRAM (about 1.5K bytes) then disable this option. + + endif +endmenu diff --git a/Sming/Arch/Esp8266/Components/lwip2/component.mk b/Sming/Arch/Esp8266/Components/lwip2/component.mk index 71746ac75d..20fb20b408 100644 --- a/Sming/Arch/Esp8266/Components/lwip2/component.mk +++ b/Sming/Arch/Esp8266/Components/lwip2/component.mk @@ -15,9 +15,8 @@ ENABLE_ESPCONN ?= 0 EXTRA_CFLAGS_LWIP := \ -I$(SMING_HOME)/System/include \ - -I$(ARCH_SYS)/include \ -I$(ARCH_COMPONENTS)/esp8266/include \ - -I$(SMING_HOME)/Wiring + -I$(ARCH_COMPONENTS)/libc/include ifeq ($(ENABLE_LWIPDEBUG), 1) EXTRA_CFLAGS_LWIP += -DLWIP_DEBUG diff --git a/Sming/Arch/Esp8266/Components/lwip2/lwip2 b/Sming/Arch/Esp8266/Components/lwip2/lwip2 index 8bd8607b4e..cfe476dfa2 160000 --- a/Sming/Arch/Esp8266/Components/lwip2/lwip2 +++ b/Sming/Arch/Esp8266/Components/lwip2/lwip2 @@ -1 +1 @@ -Subproject commit 8bd8607b4ed3b81cf656a72729aa70a09b5f4d6e +Subproject commit cfe476dfa2793025660b8698d993258f4a598f8d diff --git a/Sming/Arch/Esp8266/Components/lwip2/lwip2.patch b/Sming/Arch/Esp8266/Components/lwip2/lwip2.patch deleted file mode 100644 index 5032837ed2..0000000000 --- a/Sming/Arch/Esp8266/Components/lwip2/lwip2.patch +++ /dev/null @@ -1,164 +0,0 @@ -diff --git a/Makefile.sming b/Makefile.sming -index 842f4fe..31e4b62 100644 ---- a/Makefile.sming -+++ b/Makefile.sming -@@ -4,12 +4,15 @@ - USER_LIBDIR ?= tweaked- - LWIP_LIB_RELEASE=$(USER_LIBDIR)liblwip2.a - LWIP_INCLUDES_RELEASE=include -+SDK_BASE ?= $(ESP_HOME)/sdk -+SDK_INTERNAL ?= 0 - - all: install - - %: - @make -f makefiles/Makefile.build-lwip2 \ -- SDK=$(ESP_HOME)/sdk \ -+ SDK=$(SDK_BASE) \ -+ SDK_INTERNAL=$(SDK_INTERNAL) \ - LWIP_LIB=liblwip2.a \ - LWIP_LIB_RELEASE=$(LWIP_LIB_RELEASE) \ - LWIP_INCLUDES_RELEASE=$(LWIP_INCLUDES_RELEASE) \ -diff --git a/glue-esp/include-esp/arch/cc.h b/glue-esp/include-esp/arch/cc.h -index 735e700..47413e5 100644 ---- a/glue-esp/include-esp/arch/cc.h -+++ b/glue-esp/include-esp/arch/cc.h -@@ -59,6 +59,7 @@ typedef signed short s16_t; - typedef unsigned long u32_t; - typedef signed long s32_t; - typedef unsigned long mem_ptr_t; -+typedef signed short sint16_t; - - #define S16_F "d" - #define U16_F "d" -diff --git a/glue-lwip/arch/cc.h b/glue-lwip/arch/cc.h -index 63cd72d..5f100eb 100644 ---- a/glue-lwip/arch/cc.h -+++ b/glue-lwip/arch/cc.h -@@ -34,6 +34,8 @@ author: d. gauchard - - #include "stdint.h" - -+typedef signed short sint16_t; -+ - #ifdef LWIP_BUILD - - // define LWIP_BUILD only when building LWIP -diff --git a/glue/esp-missing.h b/glue/esp-missing.h -index 0e42073..2846506 100644 ---- a/glue/esp-missing.h -+++ b/glue/esp-missing.h -@@ -9,9 +9,13 @@ - - uint32_t r_rand (void); - --void* pvPortZalloc (size_t, const char*, int); --void* pvPortMalloc (size_t xWantedSize, const char* file, int line) __attribute__((malloc, alloc_size(1))); --void vPortFree (void *ptr, const char* file, int line); -+#if !SDK_INTERNAL -+ -+void* pvPortZalloc (size_t, const char*, unsigned line); -+void* pvPortMalloc (size_t xWantedSize, const char* file, unsigned line) __attribute__((malloc, alloc_size(1))); -+void vPortFree (void *ptr, const char* file, unsigned line); -+ -+#endif - - struct netif* eagle_lwip_getif (int netif_index); - -@@ -27,10 +31,10 @@ int ets_memcmp (const void*, const void*, size_t n); - void *ets_memset (void *s, int c, size_t n); - void *ets_memcpy (void *dest, const void *src, size_t n); - --typedef void ETSTimerFunc(void *timer_arg); --void ets_timer_disarm (ETSTimer *a); --void ets_timer_arm_new (ETSTimer *a, int b, int c, int isMstimer); --void ets_timer_setfn (ETSTimer *t, ETSTimerFunc *fn, void *parg); -+//typedef void ETSTimerFunc(void *timer_arg); -+//void ets_timer_disarm (ETSTimer *a); -+//void ets_timer_arm_new (ETSTimer *a, int b, int c, int isMstimer); -+//void ets_timer_setfn (ETSTimer *t, ETSTimerFunc *fn, void *parg); - - struct ip_addr; - void wifi_softap_set_station_info (uint8_t* mac, struct ip_addr*); -diff --git a/makefiles/Makefile.build-lwip2 b/makefiles/Makefile.build-lwip2 -index 928bb63..ccdbca7 100644 ---- a/makefiles/Makefile.build-lwip2 -+++ b/makefiles/Makefile.build-lwip2 -@@ -14,24 +14,25 @@ IRAM += sys_timeout_LWIP2 - IRAM += sntp_time_inc sntp_get_current_timestamp - #################################### - -+LWIP_LIB_BUILD = $(BUILD)/$(LWIP_LIB) -+ - all: $(LWIP_LIB_RELEASE) - --$(LWIP_LIB_RELEASE): $(LWIP_LIB) -+$(LWIP_LIB_RELEASE): $(LWIP_LIB_BUILD) - @# according to eagle.app.v6.common.ld: - @# putting symbols into .gnu.linkonce.literal.* instead of (default:).text.* - @# will eventually move them in iram: section .text.* instead of .irom0.text.* - @# check this with xtensa-lx106-elf-objdump -t | grep -- @( [ ! -r $(LWIP_LIB_RELEASE) ] || [ $(LWIP_LIB) -nt $(LWIP_LIB_RELEASE) ] ) && cp $(LWIP_LIB) $(LWIP_LIB_RELEASE) && for i in $(IRAM); do \ -+ @( [ ! -r $@ ] || [ $< -nt $@ ] ) && cp $< $@ && for i in $(IRAM); do \ - echo "---- moving $$i in IRAM"; \ -- $(OC) --rename-section .text.$$i=.gnu.linkonce.literal.$$i $(LWIP_LIB_RELEASE); \ -+ $(OC) --rename-section .text.$$i=.gnu.linkonce.literal.$$i $@; \ - true; \ - done || true - --.PHONY: $(LWIP_LIB) --$(LWIP_LIB): -- make -f makefiles/Makefile.glue-esp -- make -f makefiles/Makefile.glue -- make -C lwip2-src/src -f ../../makefiles/Makefile.lwip2 BUILD=../../$(BUILD) LWIP_LIB=../../$(LWIP_LIB) -+$(LWIP_LIB_BUILD): -+ make -f makefiles/Makefile.glue-esp SDK_INTERNAL=$(SDK_INTERNAL) LWIP_LIB=$@ -+ make -f makefiles/Makefile.glue SDK_INTERNAL=$(SDK_INTERNAL) LWIP_LIB=$@ -+ make -C lwip2-src/src -f ../../makefiles/Makefile.lwip2 LWIP_LIB=$@ SDK_INTERNAL=$(SDK_INTERNAL) - - section-show: - @for i in $(IRAM); do \ -@@ -53,4 +54,4 @@ install: $(LWIP_LIB_RELEASE) - touch $(LWIP_INCLUDES_RELEASE)/espconn.h - - clean: -- rm -rf build $(LWIP_LIB) -+ rm -rf $(BUILD) -diff --git a/makefiles/Makefile.defs b/makefiles/Makefile.defs -index 7ab4f87..025a23c 100644 ---- a/makefiles/Makefile.defs -+++ b/makefiles/Makefile.defs -@@ -4,7 +4,9 @@ AR = $(TOOLS)ar - OC = $(TOOLS)objcopy - OD = $(TOOLS)objdump - --BUILD = build -+SDK_INTERNAL ?= 0 -+ -+BUILD ?= build - BUILD_FLAGS = -Wall -Wextra -std=c99 -c -Os -g -Wpointer-arith -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99 -ffunction-sections -fdata-sections --BUILD_DEFINES = -D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ -DLWIP_OPEN_SRC -DLWIP_BUILD -DUSE_OPTIMIZE_PRINTF -+BUILD_DEFINES = -D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ -DLWIP_OPEN_SRC -DLWIP_BUILD -DUSE_OPTIMIZE_PRINTF -DSDK_INTERNAL=$(SDK_INTERNAL) - -diff --git a/glue-esp/include-esp/lwip/ip_addr.h b/glue-esp/include-esp/lwip/ip_addr.h -index cfc10f8..8a32ef0 100644 ---- a/glue-esp/include-esp/lwip/ip_addr.h -+++ b/glue-esp/include-esp/lwip/ip_addr.h -@@ -232,10 +232,14 @@ u8_t ip4_addr_netmask_valid(u32_t netmask)ICACHE_FLASH_ATTR; - #define ip_ntoa(ipaddr) ipaddr_ntoa(ipaddr) - - u32_t ipaddr_addr(const char *cp)ICACHE_FLASH_ATTR; --int ipaddr_aton(const char *cp, ip_addr_t *addr)ICACHE_FLASH_ATTR; -+int ip4addr_aton(const char *cp, ip_addr_t *addr)ICACHE_FLASH_ATTR; - /** returns ptr to static buffer; not reentrant! */ --char *ipaddr_ntoa(const ip_addr_t *addr)ICACHE_FLASH_ATTR; --char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen)ICACHE_FLASH_ATTR; -+char *ip4addr_ntoa(const ip_addr_t *addr)ICACHE_FLASH_ATTR; -+char *ip4addr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen)ICACHE_FLASH_ATTR; -+ -+#define ipaddr_aton(CP, ADDR) ip4addr_aton(CP,ADDR); -+#define ipaddr_ntoa(ADDR) ip4addr_ntoa(ADDR) -+#define ipaddr_ntoa_r(ADDR, CP, LEN) ip4addr_ntoa_r(ADDR, CP, LEN) - - #define IP2STR(ipaddr) ip4_addr1_16(ipaddr), \ - ip4_addr2_16(ipaddr), \ diff --git a/Sming/Arch/Esp8266/Components/sming-arch/component.mk b/Sming/Arch/Esp8266/Components/sming-arch/component.mk index ba606f85aa..cbbb3528a7 100644 --- a/Sming/Arch/Esp8266/Components/sming-arch/component.mk +++ b/Sming/Arch/Esp8266/Components/sming-arch/component.mk @@ -1,13 +1,11 @@ COMPONENT_SRCDIRS := \ $(ARCH_CORE) $(call ListAllSubDirs,$(ARCH_CORE)) \ - $(ARCH_SYS) \ $(ARCH_BASE)/Platform \ $(ARCH_BASE)/Services/Profiling COMPONENT_INCDIRS := \ $(ARCH_BASE) \ $(ARCH_CORE) \ - $(ARCH_SYS)/include \ $(ARCH_COMPONENTS) COMPONENT_DEPENDS := \ @@ -17,7 +15,6 @@ COMPONENT_DEPENDS := \ esp8266 \ driver \ esptool \ - fatfs \ gdbstub \ spi_flash diff --git a/Sming/Arch/Esp8266/Components/spi_flash/flashmem.c b/Sming/Arch/Esp8266/Components/spi_flash/flashmem.c index 8d06db8a8d..2c4c54de01 100644 --- a/Sming/Arch/Esp8266/Components/spi_flash/flashmem.c +++ b/Sming/Arch/Esp8266/Components/spi_flash/flashmem.c @@ -16,6 +16,7 @@ ****/ #include "include/esp_spi_flash.h" +#include extern char _flash_code_end[]; diff --git a/Sming/Arch/Esp8266/Components/spi_flash/include/esp_spi_flash.h b/Sming/Arch/Esp8266/Components/spi_flash/include/esp_spi_flash.h index 9e3ba7e840..51904f8a58 100644 --- a/Sming/Arch/Esp8266/Components/spi_flash/include/esp_spi_flash.h +++ b/Sming/Arch/Esp8266/Components/spi_flash/include/esp_spi_flash.h @@ -15,7 +15,8 @@ extern "C" { #endif -#include +#include +#include /** * @defgroup flash Flash Memory Support @@ -36,7 +37,7 @@ extern "C" { #define INTERNAL_FLASH_SECTOR_SIZE SPI_FLASH_SEC_SIZE #define INTERNAL_FLASH_SIZE ((FLASH_WORK_SEC_COUNT)*INTERNAL_FLASH_SECTOR_SIZE) -#define INTERNAL_FLASH_START_ADDRESS FLASH_BASE +#define INTERNAL_FLASH_START_ADDRESS 0x40200000 typedef enum { MODE_QIO = 0, diff --git a/Sming/Arch/Esp8266/Components/spi_flash/include/flashmem.h b/Sming/Arch/Esp8266/Components/spi_flash/include/flashmem.h deleted file mode 100644 index f1d8fa7a80..0000000000 --- a/Sming/Arch/Esp8266/Components/spi_flash/include/flashmem.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -#pragma GCC warning "Please update to #include " -#include "esp_spi_flash.h" diff --git a/Sming/Arch/Esp8266/Core/Digital.cpp b/Sming/Arch/Esp8266/Core/Digital.cpp index 68a81dbccd..1f6d31604d 100644 --- a/Sming/Arch/Esp8266/Core/Digital.cpp +++ b/Sming/Arch/Esp8266/Core/Digital.cpp @@ -10,8 +10,9 @@ #include #include "ESP8266EX.h" - -const unsigned int A0 = 17; // Single ESP8266EX analog input pin (TOUT) 10 bit, 0..1v +#include +#include +#include // Prototype declared in esp8266-peri.h const uint8_t esp8266_gpioToFn[16] = {0x34, 0x18, 0x38, 0x14, 0x3C, 0x40, 0x1C, 0x20, diff --git a/Sming/Arch/Esp8266/Core/ESP8266EX.cpp b/Sming/Arch/Esp8266/Core/ESP8266EX.cpp index 1f454f6aa2..59e8bd4250 100644 --- a/Sming/Arch/Esp8266/Core/ESP8266EX.cpp +++ b/Sming/Arch/Esp8266/Core/ESP8266EX.cpp @@ -11,6 +11,7 @@ #include "Digital.h" #include "ESP8266EX.h" #include "Digital.h" +#include const EspDigitalPin EspDigitalPins[] = { {0, PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0}, // FLASH diff --git a/Sming/Arch/Esp8266/Core/ESP8266EX.h b/Sming/Arch/Esp8266/Core/ESP8266EX.h index 7d8f5ef34b..6d83620d37 100644 --- a/Sming/Arch/Esp8266/Core/ESP8266EX.h +++ b/Sming/Arch/Esp8266/Core/ESP8266EX.h @@ -10,7 +10,7 @@ #pragma once -#include "user_config.h" +#include #define TOTAL_PINS 16 #define NUM_DIGITAL_PINS TOTAL_PINS diff --git a/Sming/Arch/Esp8266/Core/HardwarePWM.cpp b/Sming/Arch/Esp8266/Core/HardwarePWM.cpp index fc5e832147..a1cbb10689 100644 --- a/Sming/Arch/Esp8266/Core/HardwarePWM.cpp +++ b/Sming/Arch/Esp8266/Core/HardwarePWM.cpp @@ -15,7 +15,7 @@ * Calculate the max duty as per the formulae give in ESP8266 SDK * Max Duty = (Period * 1000) / 45 * - * PWM can be generated on upto 8 pins (ie All pins except pin 16) + * PWM can be generated on up to 8 pins (ie All pins except pin 16) * Created on August 17, 2015, 2:27 PM * * See also ESP8266 Technical Reference, Chapter 12: @@ -25,17 +25,18 @@ #include #include "ESP8266EX.h" +#include #include #define PERIOD_TO_MAX_DUTY(x) (x * 25) -HardwarePWM::HardwarePWM(uint8* pins, uint8 no_of_pins) : channel_count(no_of_pins) +HardwarePWM::HardwarePWM(uint8_t* pins, uint8_t no_of_pins) : channel_count(no_of_pins) { if(no_of_pins > 0) { - uint32 io_info[PWM_CHANNEL_NUM_MAX][3]; // pin information - uint32 pwm_duty_init[PWM_CHANNEL_NUM_MAX]; // pwm duty - for(uint8 i = 0; i < no_of_pins; i++) { + uint32_t io_info[PWM_CHANNEL_NUM_MAX][3]; // pin information + uint32_t pwm_duty_init[PWM_CHANNEL_NUM_MAX]; // pwm duty + for(uint8_t i = 0; i < no_of_pins; i++) { io_info[i][0] = EspDigitalPins[pins[i]].mux; io_info[i][1] = EspDigitalPins[pins[i]].gpioFunc; io_info[i][2] = EspDigitalPins[pins[i]].id; @@ -58,9 +59,9 @@ HardwarePWM::~HardwarePWM() * Description: This function is used to get channel number for given pin * Parameters: pin - Esp8266 pin number */ -uint8 HardwarePWM::getChannel(uint8 pin) +uint8_t HardwarePWM::getChannel(uint8_t pin) { - for(uint8 i = 0; i < channel_count; i++) { + for(uint8_t i = 0; i < channel_count; i++) { if(channels[i] == pin) { //debugf("getChannel %d is %d", pin, i); return i; @@ -74,7 +75,7 @@ uint8 HardwarePWM::getChannel(uint8 pin) * Description: This function is used to get the duty cycle number for a given channel * Parameters: chan -Esp8266 channel number */ -uint32 HardwarePWM::getDutyChan(uint8 chan) +uint32_t HardwarePWM::getDutyChan(uint8_t chan) { if(chan == PWM_BAD_CHANNEL) { return 0; @@ -90,7 +91,7 @@ uint32 HardwarePWM::getDutyChan(uint8 chan) * duty - duty cycle value * update - update PWM output */ -bool HardwarePWM::setDutyChan(uint8 chan, uint32 duty, bool update) +bool HardwarePWM::setDutyChan(uint8_t chan, uint32_t duty, bool update) { if(chan == PWM_BAD_CHANNEL) { return false; @@ -111,7 +112,7 @@ bool HardwarePWM::setDutyChan(uint8 chan, uint32 duty, bool update) * Period / frequency will remain same for all pins. * */ -uint32 HardwarePWM::getPeriod() +uint32_t HardwarePWM::getPeriod() { return pwm_get_period(); } @@ -120,7 +121,7 @@ uint32 HardwarePWM::getPeriod() * Description: This function is used to set Period of PWM. * Period / frequency will remain same for all pins. */ -void HardwarePWM::setPeriod(uint32 period) +void HardwarePWM::setPeriod(uint32_t period) { maxduty = PERIOD_TO_MAX_DUTY(period); pwm_set_period(period); diff --git a/Sming/Arch/Esp8266/Core/esp8266_peri.h b/Sming/Arch/Esp8266/Core/esp8266_peri.h index 86bdac4134..e8fc69ca5c 100644 --- a/Sming/Arch/Esp8266/Core/esp8266_peri.h +++ b/Sming/Arch/Esp8266/Core/esp8266_peri.h @@ -165,7 +165,7 @@ extern const uint8_t esp8266_gpioToFn[16]; #define TCIS 8 //Interrupt Status #define TCTE 7 //Timer Enable #define TCAR 6 //AutoReload (restart timer when condition is reached) -#define TCPD 2 //Prescale Devider (2bit) 0:1(12.5ns/tick), 1:16(0.2us/tick), 2/3:256(3.2us/tick) +#define TCPD 2 //Prescale Divider (2bit) 0:1(12.5ns/tick), 1:16(0.2us/tick), 2/3:256(3.2us/tick) #define TCIT 0 //Interrupt Type 0:edge, 1:level //RTC Registers @@ -273,7 +273,7 @@ extern const uint8_t esp8266_gpioToFn[16]; #define UCRXI 19 //Invert RX #define UCTXRST 18 //Reset TX FIFO #define UCRXRST 17 //Reset RX FIFO -#define UCTXHFE 15 //TX Harware Flow Enable +#define UCTXHFE 15 //TX Hardware Flow Enable #define UCLBE 14 //LoopBack Enable #define UCBRK 8 //Send Break on the TX line #define UCSWDTR 7 //Set this bit to assert DTR @@ -285,11 +285,11 @@ extern const uint8_t esp8266_gpioToFn[16]; //UART CONF1 Registers Bits #define UCTOE 31 //RX TimeOut Enable -#define UCTOT 24 //RX TimeOut Treshold (7bit) -#define UCRXHFE 23 //RX Harware Flow Enable -#define UCRXHFT 16 //RX Harware Flow Treshold (7bit) -#define UCFET 8 //TX FIFO Empty Treshold (7bit) -#define UCFFT 0 //RX FIFO Full Treshold (7bit) +#define UCTOT 24 //RX TimeOut Threshold (7bit) +#define UCRXHFE 23 //RX Hardware Flow Enable +#define UCRXHFT 16 //RX Hardware Flow Threshold (7bit) +#define UCFET 8 //TX FIFO Empty Threshold (7bit) +#define UCFFT 0 //RX FIFO Full Threshold (7bit) //SPI_READY #define SPIRDY ESP8266_DREG(0x0C) @@ -370,7 +370,7 @@ extern const uint8_t esp8266_gpioToFn[16]; #define SPI1E3 ESP8266_REG(0x1FC) #define SPI1W(p) ESP8266_REG(0x140 + ((p & 0xF) * 4)) -//SPI0, SPI1 & I2S Interupt Register +//SPI0, SPI1 & I2S Interrupt Register #define SPIIR ESP8266_DREG(0x20) #define SPII0 4 //SPI0 Interrupt #define SPII1 7 //SPI1 Interrupt diff --git a/Sming/Arch/Esp8266/Core/pins_arduino.h b/Sming/Arch/Esp8266/Core/pins_arduino.h index 9174b01d7a..0ea26ed83a 100644 --- a/Sming/Arch/Esp8266/Core/pins_arduino.h +++ b/Sming/Arch/Esp8266/Core/pins_arduino.h @@ -14,16 +14,12 @@ #include "esp8266_peri.h" -extern const unsigned int A0; // Single ESP8266EX analog input pin (TOUT) 10 bit, 0..1v +constexpr uint8_t A0{17}; // Single ESP8266EX analog input pin (TOUT) 10 bit, 0..1v #define NOT_A_PIN 0 #define NOT_A_PORT 0 #define NOT_ON_TIMER 0 -#define PA 1 -#define PB 2 -#define PC 3 - #define GPIO_REG_TYPE uint32_t // We use maximum compatibility to standard Arduino logic. diff --git a/Sming/Arch/Esp8266/Core/twi_arch.h b/Sming/Arch/Esp8266/Core/twi_arch.h index 5a690fc466..12fd95a0d7 100644 --- a/Sming/Arch/Esp8266/Core/twi_arch.h +++ b/Sming/Arch/Esp8266/Core/twi_arch.h @@ -15,3 +15,6 @@ #define SCL_LOW() (GPES = (1 << twi_scl)) #define SCL_HIGH() (GPEC = (1 << twi_scl)) #define SCL_READ() ((GPI & (1 << twi_scl)) != 0) + +#define DEFAULT_SDA_PIN 2 +#define DEFAULT_SCL_PIN 0 diff --git a/Sming/Arch/Esp8266/Tools/ci/build.run.cmd b/Sming/Arch/Esp8266/Tools/ci/build.run.cmd index e0c217d5f0..4f73d92532 100644 --- a/Sming/Arch/Esp8266/Tools/ci/build.run.cmd +++ b/Sming/Arch/Esp8266/Tools/ci/build.run.cmd @@ -6,6 +6,7 @@ REM %MAKE_PARALLEL% samples || goto :error make clean samples-clean %MAKE_PARALLEL% Basic_Blink ENABLE_CUSTOM_HEAP=1 DEBUG_VERBOSE_LEVEL=3 || goto :error %MAKE_PARALLEL% HttpServer_ConfigNetwork ENABLE_CUSTOM_LWIP=2 STRICT=1 || goto :error +%MAKE_PARALLEL% Basic_Templates || goto :error goto :EOF diff --git a/Sming/Arch/Esp8266/Tools/ci/build.run.sh b/Sming/Arch/Esp8266/Tools/ci/build.run.sh index 9ffe3edc5f..091d398754 100755 --- a/Sming/Arch/Esp8266/Tools/ci/build.run.sh +++ b/Sming/Arch/Esp8266/Tools/ci/build.run.sh @@ -1,3 +1,5 @@ +#!/bin/bash +# # Esp8266 build.run.sh $MAKE_PARALLEL samples @@ -5,7 +7,4 @@ make clean samples-clean $MAKE_PARALLEL Basic_Blink ENABLE_CUSTOM_HEAP=1 DEBUG_VERBOSE_LEVEL=3 $MAKE_PARALLEL HttpServer_ConfigNetwork ENABLE_CUSTOM_LWIP=2 STRICT=1 -# Some samples (UPnP, for example) require more recent compiler -if [ "$BUILD_COMPILER" == "eqt" ]; then - $MAKE_PARALLEL component-samples -fi +$MAKE_PARALLEL component-samples diff --git a/Sming/Arch/Esp8266/Tools/ci/build.setup.sh b/Sming/Arch/Esp8266/Tools/ci/build.setup.sh index 941d5df444..fee356b4ac 100755 --- a/Sming/Arch/Esp8266/Tools/ci/build.setup.sh +++ b/Sming/Arch/Esp8266/Tools/ci/build.setup.sh @@ -1,3 +1,5 @@ +#!/bin/bash +# # Esp8266 build.setup.sh unset SPIFFY diff --git a/Sming/Arch/Esp8266/Tools/ci/install.cmd b/Sming/Arch/Esp8266/Tools/ci/install.cmd deleted file mode 100644 index e7525a4b2a..0000000000 --- a/Sming/Arch/Esp8266/Tools/ci/install.cmd +++ /dev/null @@ -1,11 +0,0 @@ -REM Esp8266 install.cmd - -call :install "%UDK_ROOT%" esp-udk-win32.7z -call :install "%EQT_ROOT%" x86_64-w64-mingw32.xtensa-lx106-elf-e6a192b.201211.zip -goto :EOF - -:install -if "%1"=="" goto :EOF -mkdir %1 -curl -LO %SMINGTOOLS%/%2 -7z -o%1 x %2 diff --git a/Sming/Arch/Esp8266/Tools/decode-stacktrace.py b/Sming/Arch/Esp8266/Tools/decode-stacktrace.py index 91d61460a9..d464c7d410 100644 --- a/Sming/Arch/Esp8266/Tools/decode-stacktrace.py +++ b/Sming/Arch/Esp8266/Tools/decode-stacktrace.py @@ -49,4 +49,3 @@ def extractAddresses(data): pipe.stdin.write(line.encode('ascii')) pipe.stdin.flush() - diff --git a/Sming/Arch/Esp8266/Tools/install.cmd b/Sming/Arch/Esp8266/Tools/install.cmd new file mode 100644 index 0000000000..33ec662a42 --- /dev/null +++ b/Sming/Arch/Esp8266/Tools/install.cmd @@ -0,0 +1,9 @@ +REM Esp8266 install.cmd + +call :install "%ESP_HOME%" x86_64-w64-mingw32.xtensa-lx106-elf-e6a192b.201211.zip +goto :EOF + +:install +mkdir %1 +curl -Lo %DOWNLOADS%/%2 %SMINGTOOLS%/%2 +7z -o%1 x %DOWNLOADS%/%2 diff --git a/Sming/Arch/Esp8266/Tools/install.sh b/Sming/Arch/Esp8266/Tools/install.sh old mode 100644 new mode 100755 index 039b999a6d..3d84d83659 --- a/Sming/Arch/Esp8266/Tools/install.sh +++ b/Sming/Arch/Esp8266/Tools/install.sh @@ -1,27 +1,12 @@ +#!/bin/bash +# # Esp8266 install.sh -# Old toolchain -if [ -n "$UDK_ROOT" ]; then - if [ -d "$UDK_ROOT" ]; then - printf "\n\n** Skipping Esp8266 tools installation: '$UDK_ROOT' exists\n\n" - else - TOOLCHAIN=esp-open-sdk-linux-x86_64.tar.gz - $WGET $SMINGTOOLS/$TOOLCHAIN -O $DOWNLOADS/$TOOLCHAIN - mkdir -p $UDK_ROOT - tar -zxf $DOWNLOADS/$TOOLCHAIN -C $UDK_ROOT --totals - mv $UDK_ROOT/esp-open-sdk/* $UDK_ROOT - rmdir $UDK_ROOT/esp-open-sdk - fi -fi - -# New toolchain -if [ -n "$EQT_ROOT" ]; then - if [ -d "$EQT_ROOT" ]; then - printf "\n\n** Skipping Esp8266 tools installation: '$EQT_ROOT' exists\n\n" - else - TOOLCHAIN=x86_64-linux-gnu.xtensa-lx106-elf-e6a192b.201211.tar.gz - $WGET $SMINGTOOLS/$TOOLCHAIN -O $DOWNLOADS/$TOOLCHAIN - mkdir -p $EQT_ROOT - tar -zxf $DOWNLOADS/$TOOLCHAIN -C $EQT_ROOT --totals - fi +if [ -d "$ESP_HOME" ]; then + printf "\n\n** Skipping Esp8266 tools installation: '$ESP_HOME' exists\n\n" +else + TOOLCHAIN=x86_64-linux-gnu.xtensa-lx106-elf-e6a192b.201211.tar.gz + $WGET "$SMINGTOOLS/$TOOLCHAIN" -O "$DOWNLOADS/$TOOLCHAIN" + mkdir -p "$ESP_HOME" + tar -zxf "$DOWNLOADS/$TOOLCHAIN" -C "$ESP_HOME" --totals fi diff --git a/Sming/Arch/Esp8266/Tools/travis/install.sh b/Sming/Arch/Esp8266/Tools/travis/install.sh old mode 100755 new mode 100644 diff --git a/Sming/Arch/Esp8266/app.mk b/Sming/Arch/Esp8266/app.mk index 96ad91ec04..0ce2887fb5 100644 --- a/Sming/Arch/Esp8266/app.mk +++ b/Sming/Arch/Esp8266/app.mk @@ -45,25 +45,8 @@ endef $(TARGET_OUT_0): $(COMPONENTS_AR) $(LIBMAIN_DST) $(call LinkTarget,$(RBOOT_LD_0)) - - $(Q) $(MEMANALYZER) $@ > $(FW_MEMINFO_NEW) - - $(Q) if [ -f "$(FW_MEMINFO_NEW)" -a -f "$(FW_MEMINFO_OLD)" ]; then \ - $(AWK) -F "|" ' \ - FILENAME == "$(FW_MEMINFO_OLD)" { \ - arr[$$1]=$$5 \ - } \ - FILENAME == "$(FW_MEMINFO_NEW)" { \ - if (arr[$$1] != $$5) { \ - printf "%s%s%+d%s", substr($$0, 1, length($$0) - 1)," (",$$5 - arr[$$1],")\n" \ - } else { \ - print $$0 \ - } \ - }' $(FW_MEMINFO_OLD) $(FW_MEMINFO_NEW); \ - elif [ -f "$(FW_MEMINFO_NEW)" ]; then \ - cat $(FW_MEMINFO_NEW); \ - fi - + $(Q) $(MEMANALYZER) $@ > $(FW_MEMINFO) + $(Q) cat $(FW_MEMINFO) $(TARGET_OUT_1): $(COMPONENTS_AR) $(LIBMAIN_DST) $(call LinkTarget,$(RBOOT_LD_1)) diff --git a/Sming/Arch/Esp8266/build.mk b/Sming/Arch/Esp8266/build.mk index d3497ba66d..707eb8483e 100644 --- a/Sming/Arch/Esp8266/build.mk +++ b/Sming/Arch/Esp8266/build.mk @@ -9,12 +9,7 @@ override ESP_VARIANT := endif CPPFLAGS += -DARCH_ESP8266 -CXXFLAGS += -fno-rtti -fno-exceptions -fno-threadsafe-statics - -# Required to access peripheral registers using structs -# e.g. `uint32_t value: 8` sitting at a byte or word boundary will be 'optimised' to -# an 8-bit fetch/store instruction which will not work; it must be a full 32-bit access. -CXXFLAGS += -fstrict-volatile-bitfields +CXXFLAGS += -fno-threadsafe-statics ## ESP_HOME sets the path where ESP tools and SDK are located. DEBUG_VARS += ESP_HOME @@ -41,6 +36,7 @@ AR := $(TOOLSPEC)ar LD := $(TOOLSPEC)gcc OBJCOPY := $(TOOLSPEC)objcopy OBJDUMP := $(TOOLSPEC)objdump +NM := $(TOOLSPEC)nm GDB := $(TOOLSPEC)gdb GCC_UPGRADE_URL := https://sming.readthedocs.io/en/latest/arch/esp8266/getting-started/eqt.html @@ -54,7 +50,8 @@ CPPFLAGS += \ -D__ets__ \ -DICACHE_FLASH \ -DUSE_OPTIMIZE_PRINTF \ - -DESP8266 + -DESP8266 \ + -D__ESP8266_EX__ ifeq (,$(wildcard $(XTENSA_TOOLS_ROOT))) $(error ESP_HOME not set correctly: "$(ESP_HOME)") diff --git a/Sming/Arch/Esp8266/esp8266-soc.json b/Sming/Arch/Esp8266/esp8266-soc.json new file mode 100644 index 0000000000..9e1d975039 --- /dev/null +++ b/Sming/Arch/Esp8266/esp8266-soc.json @@ -0,0 +1,4 @@ +{ + "variant": "esp8266", + "name": "ESP8266EX" +} \ No newline at end of file diff --git a/Sming/Arch/Host/Components/SerialLib/SerialLib.h b/Sming/Arch/Host/Components/SerialLib/SerialLib.h index 6f57aed795..258b6697b5 100644 --- a/Sming/Arch/Host/Components/SerialLib/SerialLib.h +++ b/Sming/Arch/Host/Components/SerialLib/SerialLib.h @@ -1,5 +1,8 @@ #pragma once +#include +#undef interface + #include "seriallib/lib/serialib.h" class SerialDevice : public serialib diff --git a/Sming/Arch/Host/Components/driver/hw_timer.cpp b/Sming/Arch/Host/Components/driver/hw_timer.cpp index 6e8abc7172..c5d045355f 100644 --- a/Sming/Arch/Host/Components/driver/hw_timer.cpp +++ b/Sming/Arch/Host/Components/driver/hw_timer.cpp @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include @@ -44,7 +44,7 @@ class CTimerThread : public CThread void attach_interrupt(hw_timer_source_type_t source_type, hw_timer_callback_t callback, void* arg) { stop(); - source_type = source_type; + this->source_type = source_type; this->callback.func = callback; this->callback.arg = arg; } diff --git a/Sming/Arch/Host/Components/driver/os_timer.cpp b/Sming/Arch/Host/Components/driver/os_timer.cpp index 97779d0a53..5eddbb2900 100644 --- a/Sming/Arch/Host/Components/driver/os_timer.cpp +++ b/Sming/Arch/Host/Components/driver/os_timer.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include static os_timer_t* timer_list; static CMutex mutex; diff --git a/Sming/Arch/Host/Components/driver/uart.cpp b/Sming/Arch/Host/Components/driver/uart.cpp index ff71fbd890..bde5e7dfdd 100644 --- a/Sming/Arch/Host/Components/driver/uart.cpp +++ b/Sming/Arch/Host/Components/driver/uart.cpp @@ -28,6 +28,8 @@ #include #include #include +#include +#include /* * Parameters relating to RX FIFO and buffer thresholds @@ -502,19 +504,9 @@ bool smg_uart_set_pins(smg_uart_t* uart, int tx_pin, int rx_pin) return true; } -void smg_uart_debug_putc(char c) -{ - smg_uart_t* uart = smg_uart_get_uart(s_uart_debug_nr); - if(uart != nullptr) { - smg_uart_write_char(uart, c); - } -} - void smg_uart_set_debug(int uart_nr) { s_uart_debug_nr = uart_nr; - system_set_os_print(uart_nr >= 0); - ets_install_putc1(smg_uart_debug_putc); } int smg_uart_get_debug() diff --git a/Sming/Arch/Host/Components/driver/uart_server.cpp b/Sming/Arch/Host/Components/driver/uart_server.cpp index 2b0e5ad0a5..552216b298 100644 --- a/Sming/Arch/Host/Components/driver/uart_server.cpp +++ b/Sming/Arch/Host/Components/driver/uart_server.cpp @@ -23,6 +23,7 @@ #include #include #include +#include namespace UartServer { @@ -209,7 +210,7 @@ void CUart::onNotify(smg_uart_t* uart, smg_uart_notify_code_t code) break; case UART_NOTIFY_AFTER_WRITE: { - if(uart != nullptr) { + if(this->uart != nullptr) { // Kick the thread to send now txsem.post(); } else { diff --git a/Sming/Arch/Host/Components/esp_hal/include/esp_libc.h b/Sming/Arch/Host/Components/esp_hal/include/esp_libc.h deleted file mode 100644 index 9050c06492..0000000000 --- a/Sming/Arch/Host/Components/esp_hal/include/esp_libc.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -uint32_t os_random(void); -int os_get_random(uint8_t* buf, size_t len); - -void ets_install_putc1(void (*p)(char c)); -void system_set_os_print(bool onoff); - -#define ets_memcpy(dest, src, n) memcpy(dest, src, n) - -#ifdef __cplusplus -} -#endif diff --git a/Sming/Arch/Host/Components/esp_hal/include/esp_system.h b/Sming/Arch/Host/Components/esp_hal/include/esp_system.h index 97ba0feecc..e3e22bcc25 100644 --- a/Sming/Arch/Host/Components/esp_hal/include/esp_system.h +++ b/Sming/Arch/Host/Components/esp_hal/include/esp_system.h @@ -11,6 +11,9 @@ void system_soft_wdt_stop(void); void system_soft_wdt_restart(void); void system_soft_wdt_feed(void); +uint32_t os_random(void); +int os_get_random(uint8_t* buf, size_t len); + /* Arch/Esp8266/Components/spiffs/spiffs_sming.c */ #define ETS_INTR_LOCK() ets_intr_lock() #define ETS_INTR_UNLOCK() ets_intr_unlock() diff --git a/Sming/Arch/Host/Components/esp_hal/include/esp_systemapi.h b/Sming/Arch/Host/Components/esp_hal/include/esp_systemapi.h index fd4aa83712..8190300af3 100644 --- a/Sming/Arch/Host/Components/esp_hal/include/esp_systemapi.h +++ b/Sming/Arch/Host/Components/esp_hal/include/esp_systemapi.h @@ -17,7 +17,6 @@ #include #include #include "esp_clk.h" -#include "esp_libc.h" #include "esp_tasks.h" #include #include "esp_system.h" @@ -54,5 +53,3 @@ __forceinline void restoreInterrupts(unsigned level) (void)level; interrupts(); } - -#define BIT(nr) (1UL << (nr)) diff --git a/Sming/Arch/Host/Components/esp_hal/libc.c b/Sming/Arch/Host/Components/esp_hal/libc.c deleted file mode 100644 index 18922899b0..0000000000 --- a/Sming/Arch/Host/Components/esp_hal/libc.c +++ /dev/null @@ -1,15 +0,0 @@ - -#include "include/esp_libc.h" - -/* Misc */ - -void ets_install_putc1(void (*p)(char c)) -{ - // -} - -void system_set_os_print(bool onoff) -{ - // -} - diff --git a/Sming/Arch/Host/Components/esp_hal/random.cpp b/Sming/Arch/Host/Components/esp_hal/random.cpp index 9224f90a38..58ce15ffb1 100644 --- a/Sming/Arch/Host/Components/esp_hal/random.cpp +++ b/Sming/Arch/Host/Components/esp_hal/random.cpp @@ -15,10 +15,10 @@ * ****/ -#include "include/esp_libc.h" +#include "include/esp_system.h" #include #include -#include +#include // See https://codeforces.com/blog/entry/61587 std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count()); diff --git a/Sming/Arch/Host/Components/fatfs/README.rst b/Sming/Arch/Host/Components/fatfs/README.rst deleted file mode 100644 index e53896fe5f..0000000000 --- a/Sming/Arch/Host/Components/fatfs/README.rst +++ /dev/null @@ -1,4 +0,0 @@ -fatfs -===== - -This Component is required to allow some samples to compile for the Host, however it doesn't provide any functionality at present. diff --git a/Sming/Arch/Host/Components/hostlib/README.rst b/Sming/Arch/Host/Components/hostlib/README.rst index a8108d8f35..93f296b454 100644 --- a/Sming/Arch/Host/Components/hostlib/README.rst +++ b/Sming/Arch/Host/Components/hostlib/README.rst @@ -21,7 +21,7 @@ Initialises :component-host:`spi_flash`, Uart server (in :component-host:`driver networking, then enters the main task loop. This loop services LWIP plus the task and timer queues (implemented in :component-host:`esp_hal`). The ``Ctrl+C`` keypress is trapped to provide an orderly exit. If the system has become stuck in a loop or is otherwise -unresponsive, subsquent Ctrl+C presses will force a process termination. +unresponsive, subsequent Ctrl+C presses will force a process termination. Threads and Interrupts ---------------------- @@ -30,12 +30,12 @@ The emulator uses Posix threads (pthread library) to perform background processi be done in hardware or which is outside of the framework. Ideally we'd use SCHED_FIFO to disable time-slicing and more closely resemble how interrupts work -on a single-core CPU. However, this mode isn't supported in Windows, and Linux requires priviledged +on a single-core CPU. However, this mode isn't supported in Windows, and Linux requires privileged access and can potentially crash the system. Best avoided, I think. All ESP code runs at a specific interrupt level, where 0 represents regular code. When an interrupt occurs, the level is raised according to the priority of that interrupt. Until that code has finished, -only interrupts of a higher priority will pre-empt it. +only interrupts of a higher priority will preempt it. The ``set_interrupt_level`` function is used to ensure that threads running at different interrupt levels do not pre-empty each other, as this would introduce problems that do not exist on real hardware. diff --git a/Sming/Arch/Host/Components/hostlib/component.mk b/Sming/Arch/Host/Components/hostlib/component.mk index 551f63afe4..36956894c0 100644 --- a/Sming/Arch/Host/Components/hostlib/component.mk +++ b/Sming/Arch/Host/Components/hostlib/component.mk @@ -14,6 +14,9 @@ COMPONENT_DEPENDS += \ lwip endif +# Build a variant depending on network support +COMPONENT_RELINK_VARS := DISABLE_NETWORK + COMPONENT_INCDIRS := include COMPONENT_SRCDIRS := . COMPONENT_DOXYGEN_INPUT := include/hostlib diff --git a/Sming/Arch/Host/Components/hostlib/include/hostlib/CommandLine.h b/Sming/Arch/Host/Components/hostlib/include/hostlib/CommandLine.h index 37ba325dbe..858624e3bb 100644 --- a/Sming/Arch/Host/Components/hostlib/include/hostlib/CommandLine.h +++ b/Sming/Arch/Host/Components/hostlib/include/hostlib/CommandLine.h @@ -1,4 +1,4 @@ -/** +/**** * CommandLine.h - Provides access to command-line parameters * * Copyright 2020 mikee47 diff --git a/Sming/Arch/Host/Components/hostlib/include/hostlib/hostlib.h b/Sming/Arch/Host/Components/hostlib/include/hostlib/hostlib.h index b30b0cec12..8dc8f9d2b3 100644 --- a/Sming/Arch/Host/Components/hostlib/include/hostlib/hostlib.h +++ b/Sming/Arch/Host/Components/hostlib/include/hostlib/hostlib.h @@ -1,4 +1,4 @@ -/** +/**** * hostlib.h * * Copyright 2019 mikee47 diff --git a/Sming/Arch/Host/Components/hostlib/include/hostlib/init.h b/Sming/Arch/Host/Components/hostlib/include/hostlib/init.h index 76c1f9defe..6b73b8afbc 100644 --- a/Sming/Arch/Host/Components/hostlib/include/hostlib/init.h +++ b/Sming/Arch/Host/Components/hostlib/include/hostlib/init.h @@ -1,4 +1,4 @@ -/** +/**** * hostlib.h * * Copyright 2019 mikee47 diff --git a/Sming/Arch/Host/Components/hostlib/options.h b/Sming/Arch/Host/Components/hostlib/options.h index 9634e0b2fa..45e7603d4e 100644 --- a/Sming/Arch/Host/Components/hostlib/options.h +++ b/Sming/Arch/Host/Components/hostlib/options.h @@ -32,9 +32,9 @@ XX(uart, required_argument, "Enable UART server", "PORT", "Which UART number to enable", \ "e.g. --uart=0 --uart=1 enable servers for UART0, UART1\0") \ XX(device, required_argument, "Set device for uart", "DEVICE", "Optionally map uart to device", \ - "e.g. --uart=0 --device=/dev/ttyUSB0") \ + "e.g. --uart=0 --device=/dev/ttyUSB0\0") \ XX(baud, required_argument, "Set baud rate for UART", "BAUD", "Requires --device argument", \ - "e.g. --uart=0 --device=/dev/ttyUSB0 --baud=115200") \ + "e.g. --uart=0 --device=/dev/ttyUSB0 --baud=115200\0") \ XX(portbase, required_argument, "Specify base port number for UART socket servers", "PORT", "IP port number", \ nullptr) \ XX(ifname, required_argument, "Specify network interface", "NAME", "Network interface to use (e.g. tap0)", \ @@ -52,6 +52,8 @@ XX(flashsize, required_argument, "Change default flash size if file doesn't exist", "SIZE", \ "Size of flash in bytes (e.g. 512K, 524288, 0x80000)", nullptr) \ XX(initonly, no_argument, "Initialise only, do not start Sming", nullptr, nullptr, nullptr) \ + XX(loopcount, required_argument, "Run Sming loop a fixed number of times then exit", nullptr, nullptr, \ + "Useful for running samples in CI\0") \ XX(nonet, no_argument, "Skip network initialisation", nullptr, nullptr, nullptr) \ XX(debug, required_argument, "Set debug verbosity", "LEVEL", "Maximum debug message level to print", \ "0 = errors only, 1 = +warnings, 2 = +info\0") diff --git a/Sming/Arch/Host/Components/hostlib/startup.cpp b/Sming/Arch/Host/Components/hostlib/startup.cpp index 71ccab74f4..b36e89f342 100644 --- a/Sming/Arch/Host/Components/hostlib/startup.cpp +++ b/Sming/Arch/Host/Components/hostlib/startup.cpp @@ -134,6 +134,7 @@ int main(int argc, char* argv[]) int pause; int exitpause; bool initonly; + int loopcount; bool enable_network; UartServer::Config uart; FlashmemConfig flash; @@ -244,6 +245,10 @@ int main(int argc, char* argv[]) config.initonly = true; break; + case opt_loopcount: + config.loopcount = atoi(arg); + break; + case opt_nonet: config.enable_network = false; break; @@ -309,6 +314,14 @@ int main(int argc, char* argv[]) #endif while(!done) { host_main_loop(); + if(config.loopcount == 0) { + continue; + } + --config.loopcount; + if(config.loopcount == 0) { + host_debug_i("Reached requested loop count limit: exiting"); + break; + } } host_debug_i(">> Normal Exit <<\n"); diff --git a/Sming/Arch/Host/Components/hostlib/threads.h b/Sming/Arch/Host/Components/hostlib/threads.h index 2bb57111ca..9409c5fe6a 100644 --- a/Sming/Arch/Host/Components/hostlib/threads.h +++ b/Sming/Arch/Host/Components/hostlib/threads.h @@ -1,5 +1,5 @@ /** - * threads.h - C++ support for threads and related sychronisation primitives using pthread library + * threads.h - C++ support for threads and related synchronisation primitives using pthread library * * Copyright 2019 mikee47 * diff --git a/Sming/Arch/Host/Components/lwip/README.rst b/Sming/Arch/Host/Components/lwip/README.rst index 80fc728cf8..4c62031d10 100644 --- a/Sming/Arch/Host/Components/lwip/README.rst +++ b/Sming/Arch/Host/Components/lwip/README.rst @@ -32,7 +32,7 @@ Linux Support is provided via TAP network interface (a virtual network layer operating at the ethernet frame level). A TAP interface must be created -first, and requires root priviledge:: +first, and requires root privilege:: sudo ip tuntap add dev tap0 mode tap user `whoami` sudo ip a a dev tap0 192.168.13.1/24 diff --git a/Sming/Arch/Host/Components/lwip/component.mk b/Sming/Arch/Host/Components/lwip/component.mk index ae5981140d..a92eaaa254 100644 --- a/Sming/Arch/Host/Components/lwip/component.mk +++ b/Sming/Arch/Host/Components/lwip/component.mk @@ -32,6 +32,7 @@ else endif CMAKE_OPTIONS += -DLWIP_LIBNAME=$(COMPONENT_VARIANT) +CMAKE_OPTIONS += -DCMAKE_C_COMPILER=$(CC) $(COMPONENT_RULE)$(COMPONENT_LIBPATH): $(Q) $(CMAKE) -DUSER_LIBDIR=$(COMPONENT_LIBDIR) $(CMAKE_OPTIONS) $(COMPONENT_PATH)/$(UNAME) diff --git a/Sming/Arch/Host/Components/lwip/lwipopts.h b/Sming/Arch/Host/Components/lwip/lwipopts.h index 229eea94b4..f700e25a03 100644 --- a/Sming/Arch/Host/Components/lwip/lwipopts.h +++ b/Sming/Arch/Host/Components/lwip/lwipopts.h @@ -364,7 +364,7 @@ /** * PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. The default is - * designed to accomodate single full size TCP frame in one pbuf, including + * designed to accommodate single full size TCP frame in one pbuf, including * TCP_MSS, IP header, and link header. * */ diff --git a/Sming/Arch/Host/Components/sming-arch/component.mk b/Sming/Arch/Host/Components/sming-arch/component.mk index 4ff9dec5c8..af6aa02b8a 100644 --- a/Sming/Arch/Host/Components/sming-arch/component.mk +++ b/Sming/Arch/Host/Components/sming-arch/component.mk @@ -16,14 +16,12 @@ export ESP8266_COMPONENTS COMPONENT_SRCDIRS := \ $(ARCH_CORE) $(call ListAllSubDirs,$(ARCH_CORE)) \ - $(ARCH_SYS) \ $(ARCH_BASE)/Platform \ $(ARCH_BASE)/Services/Profiling COMPONENT_INCDIRS := \ $(ARCH_BASE) \ $(ARCH_CORE) \ - $(ARCH_SYS)/include \ $(ARCH_COMPONENTS) COMPONENT_DEPENDS := \ diff --git a/Sming/Arch/Host/Components/spi_flash/flashmem.cpp b/Sming/Arch/Host/Components/spi_flash/flashmem.cpp index 0e8f0bc0bd..18a01c2b6e 100644 --- a/Sming/Arch/Host/Components/spi_flash/flashmem.cpp +++ b/Sming/Arch/Host/Components/spi_flash/flashmem.cpp @@ -22,6 +22,7 @@ #include #include #include +#include namespace { diff --git a/Sming/Arch/Host/Core/Data/Stream/HostFileStream.h b/Sming/Arch/Host/Core/Data/Stream/HostFileStream.h index 381e955812..328eb30500 100644 --- a/Sming/Arch/Host/Core/Data/Stream/HostFileStream.h +++ b/Sming/Arch/Host/Core/Data/Stream/HostFileStream.h @@ -11,6 +11,7 @@ #pragma once #include +#include /** * @brief Host File stream class diff --git a/Sming/Arch/Host/Core/HardwarePWM.cpp b/Sming/Arch/Host/Core/HardwarePWM.cpp index 876e6f2fee..d2eaf908f7 100644 --- a/Sming/Arch/Host/Core/HardwarePWM.cpp +++ b/Sming/Arch/Host/Core/HardwarePWM.cpp @@ -15,7 +15,7 @@ * Calculate the max duty as per the formulae give in ESP8266 SDK * Max Duty = (Period * 1000) / 45 * - * PWM can be generated on upto 8 pins (ie All pins except pin 16) + * PWM can be generated on up to 8 pins (ie All pins except pin 16) * Created on August 17, 2015, 2:27 PM * * See also ESP8266 Technical Reference, Chapter 12: diff --git a/Sming/Arch/Host/Core/SPI.cpp b/Sming/Arch/Host/Core/SPI.cpp index 22edc86773..104f2b2821 100644 --- a/Sming/Arch/Host/Core/SPI.cpp +++ b/Sming/Arch/Host/Core/SPI.cpp @@ -1,5 +1,7 @@ #include "SPI.h" +SPIClass SPI; + bool SPIClass::begin() { return false; diff --git a/Sming/Arch/Host/Core/twi_arch.h b/Sming/Arch/Host/Core/twi_arch.h index 10bfae27b9..018514d34d 100644 --- a/Sming/Arch/Host/Core/twi_arch.h +++ b/Sming/Arch/Host/Core/twi_arch.h @@ -15,3 +15,6 @@ #define SCL_LOW() #define SCL_HIGH() #define SCL_READ() 1 + +#define DEFAULT_SDA_PIN 4 +#define DEFAULT_SCL_PIN 5 diff --git a/Sming/Arch/Host/System/include/user_config.h b/Sming/Arch/Host/System/include/user_config.h deleted file mode 100644 index 586fe2f944..0000000000 --- a/Sming/Arch/Host/System/include/user_config.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef __USER_CONFIG_H__ -#define __USER_CONFIG_H__ - -// UART config -#define SERIAL_BAUD_RATE COM_SPEED_SERIAL - -#include - -// Extended string conversion for compatibility -#include - -// Network base API -#ifndef DISABLE_NETWORK -#include -#include -#include -#include -#include -#include -#endif - -#endif /* __USER_CONFIG_H__ */ diff --git a/Sming/Arch/Host/Tools/ci/build.run.cmd b/Sming/Arch/Host/Tools/ci/build.run.cmd index 55174dc850..726534f998 100644 --- a/Sming/Arch/Host/Tools/ci/build.run.cmd +++ b/Sming/Arch/Host/Tools/ci/build.run.cmd @@ -1,7 +1,7 @@ REM Host build.run.cmd REM Build a couple of basic applications -%MAKE_PARALLEL% Basic_Serial Basic_ProgMem Basic_IFS STRICT=1 V=1 || goto :error +%MAKE_PARALLEL% Basic_Serial Basic_ProgMem Basic_IFS STRICT=1 || goto :error REM Run basic tests %MAKE_PARALLEL% tests || goto :error diff --git a/Sming/Arch/Host/Tools/ci/build.run.sh b/Sming/Arch/Host/Tools/ci/build.run.sh index ada35bb8fb..708f349153 100755 --- a/Sming/Arch/Host/Tools/ci/build.run.sh +++ b/Sming/Arch/Host/Tools/ci/build.run.sh @@ -1,3 +1,5 @@ +#!/bin/bash +# # Host build.run.sh SOURCE="${BASH_SOURCE[0]}" @@ -9,9 +11,9 @@ done DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" if [[ $CHECK_SCA -eq 1 ]]; then - $DIR/coverity-scan.sh + "$DIR/coverity-scan.sh" else - $MAKE_PARALLEL Basic_Blink Basic_DateTime Basic_Delegates Basic_Interrupts Basic_ProgMem Basic_Serial Basic_Servo Basic_Ssl LiveDebug DEBUG_VERBOSE_LEVEL=3 + $MAKE_PARALLEL samples DEBUG_VERBOSE_LEVEL=3 fi # Build and run tests diff --git a/Sming/Arch/Host/Tools/ci/build.setup.cmd b/Sming/Arch/Host/Tools/ci/build.setup.cmd index 27b7b02d62..c6d0b91d9f 100644 --- a/Sming/Arch/Host/Tools/ci/build.setup.cmd +++ b/Sming/Arch/Host/Tools/ci/build.setup.cmd @@ -1,10 +1 @@ REM Host build.setup.cmd - -REM Build documentation -make -C %SMING_HOME% docs || goto :error - -goto :EOF - -:error -echo Failed with error #%errorlevel%. -exit /b %errorlevel% diff --git a/Sming/Arch/Host/Tools/ci/build.setup.sh b/Sming/Arch/Host/Tools/ci/build.setup.sh index a2370b039b..8018890bf4 100755 --- a/Sming/Arch/Host/Tools/ci/build.setup.sh +++ b/Sming/Arch/Host/Tools/ci/build.setup.sh @@ -1,3 +1,5 @@ +#!/bin/bash +# # Host build.setup.sh # Check coding style @@ -13,16 +15,15 @@ fi # Make deployment keys, etc. available set +x if [ -n "$SMING_SECRET" ]; then - openssl aes-256-cbc -d -a -iter 100 -in $CI_BUILD_DIR/Tools/ci/secrets.sh.enc -out /tmp/secrets.sh -pass pass:$SMING_SECRET + openssl aes-256-cbc -d -a -iter 100 -in "$CI_BUILD_DIR/Tools/ci/secrets.sh.enc" -out /tmp/secrets.sh -pass "pass:$SMING_SECRET" source /tmp/secrets.sh unset SMING_SECRET fi set -x # Setup networking +set +e sudo ip tuntap add dev tap0 mode tap user $(whoami) sudo ip a a dev tap0 192.168.13.1/24 sudo ip link set tap0 up - -# Build documentation -make -C $SMING_HOME docs +set -e diff --git a/Sming/Arch/Host/Tools/ci/coverity-scan.sh b/Sming/Arch/Host/Tools/ci/coverity-scan.sh index 984660af48..e2d3e6f88c 100755 --- a/Sming/Arch/Host/Tools/ci/coverity-scan.sh +++ b/Sming/Arch/Host/Tools/ci/coverity-scan.sh @@ -35,11 +35,11 @@ if [ "$AUTH_RES" = "Access denied" ]; then echo -e "\033[33;1mCoverity Scan API access denied. Check COVERITY_SCAN_PROJECT_NAME and COVERITY_SCAN_TOKEN.\033[0m" exit 1 else - AUTH=$(echo $AUTH_RES | ruby -e "require 'rubygems'; require 'json'; puts JSON[STDIN.read]['upload_permitted']") + AUTH=$(echo "$AUTH_RES" | ruby -e "require 'rubygems'; require 'json'; puts JSON[STDIN.read]['upload_permitted']") if [ "$AUTH" = "true" ]; then echo -e "\033[33;1mCoverity Scan analysis authorized per quota.\033[0m" else - WHEN=$(echo $AUTH_RES | ruby -e "require 'rubygems'; require 'json'; puts JSON[STDIN.read]['next_upload_permitted_at']") + WHEN=$(echo "$AUTH_RES" | ruby -e "require 'rubygems'; require 'json'; puts JSON[STDIN.read]['next_upload_permitted_at']") echo -e "\033[33;1mOops!Coverity Scan analysis engine NOT authorized until $WHEN.\033[0m" permit=false fi @@ -50,7 +50,7 @@ if [ ! -d $TOOL_BASE ]; then # Download Coverity Scan Analysis Tool if [ ! -e $TOOL_ARCHIVE ]; then echo -e "\033[33;1mDownloading Coverity Scan Analysis Tool...\033[0m" - wget -nv -O $TOOL_ARCHIVE $TOOL_URL --post-data "project=$COVERITY_SCAN_PROJECT_NAME&token=$COVERITY_SCAN_TOKEN" + wget -nv -O "$TOOL_ARCHIVE" "$TOOL_URL" --post-data "project=$COVERITY_SCAN_PROJECT_NAME&token=$COVERITY_SCAN_TOKEN" fi # Extract Coverity Scan Analysis Tool @@ -65,6 +65,9 @@ fi TOOL_DIR=$(find $TOOL_BASE -type d -name 'cov-analysis*') export PATH=$TOOL_DIR/bin:$PATH +# Clean-up +make -C $SMING_HOME dist-clean + # Build echo -e "\033[33;1mRunning Coverity Scan Analysis Tool...\033[0m" COV_BUILD_OPTIONS="" diff --git a/Sming/Arch/Host/Tools/ci/install.cmd b/Sming/Arch/Host/Tools/ci/install.cmd deleted file mode 100644 index b1218913be..0000000000 --- a/Sming/Arch/Host/Tools/ci/install.cmd +++ /dev/null @@ -1,18 +0,0 @@ -REM Host install.cmd - -call :install "c:\tools\doxygen" doxygen-1.9.1.windows.bin.zip -call :install "c:\tools" stable_windows_10_msbuild_Release_Win32_graphviz-2.46.1-win32.zip - -python -m pip install --upgrade pip wheel - -python -m pip install -r %SMING_HOME%/../docs/requirements.txt - -python -m pip uninstall -y xcffib - -goto :EOF - -:install -if "%~1"=="" goto :EOF -mkdir %1 -curl -LO %SMINGTOOLS%/%2 -7z -o%1 -y x %2 diff --git a/Sming/Arch/Host/Tools/install.cmd b/Sming/Arch/Host/Tools/install.cmd new file mode 100644 index 0000000000..1972448930 --- /dev/null +++ b/Sming/Arch/Host/Tools/install.cmd @@ -0,0 +1,3 @@ +REM Host install.cmd + +echo. diff --git a/Sming/Arch/Host/Tools/install.sh b/Sming/Arch/Host/Tools/install.sh index 4b21178d6b..6417bdbc4a 100755 --- a/Sming/Arch/Host/Tools/install.sh +++ b/Sming/Arch/Host/Tools/install.sh @@ -1,3 +1,5 @@ +#!/bin/bash +# # Host install.sh # Required by deployment script diff --git a/Sming/Arch/Host/Tools/setup-network-linux.sh b/Sming/Arch/Host/Tools/setup-network-linux.sh index 7f5b7c2df8..e654790ff8 100755 --- a/Sming/Arch/Host/Tools/setup-network-linux.sh +++ b/Sming/Arch/Host/Tools/setup-network-linux.sh @@ -24,8 +24,8 @@ sudo sysctl net.ipv4.ip_forward=1 sudo sysctl net.ipv6.conf.default.forwarding=1 sudo sysctl net.ipv6.conf.all.forwarding=1 -sudo iptables -t nat -A POSTROUTING -o $INTERNET_IF -j MASQUERADE +sudo iptables -t nat -A POSTROUTING -o "$INTERNET_IF" -j MASQUERADE sudo iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -sudo iptables -A FORWARD -i tap0 -o $INTERNET_IF -j ACCEPT +sudo iptables -A FORWARD -i tap0 -o "$INTERNET_IF" -j ACCEPT exit 0 \ No newline at end of file diff --git a/Sming/Arch/Host/app.mk b/Sming/Arch/Host/app.mk index 0e5c61c07e..9a7bcac527 100644 --- a/Sming/Arch/Host/app.mk +++ b/Sming/Arch/Host/app.mk @@ -26,8 +26,8 @@ $(TARGET_OUT_0): $(COMPONENTS_AR) $(info $(notdir $(PROJECT_DIR)): Linking $@) $(Q) $(LD) $(addprefix -L,$(LIBDIRS)) $(LDFLAGS) -Wl,--start-group $(COMPONENTS_AR) $(addprefix -l,$(LIBS)) -Wl,--end-group -o $@ $(Q) $(call WriteFirmwareConfigFile,$@) - $(Q) $(MEMANALYZER) $@ > $(FW_MEMINFO_NEW) - $(Q) cat $(FW_MEMINFO_NEW) + $(Q) $(MEMANALYZER) $@ > $(FW_MEMINFO) + $(Q) cat $(FW_MEMINFO) ##@Tools .PHONY: valgrind diff --git a/Sming/Arch/Host/build.mk b/Sming/Arch/Host/build.mk index 0f98412d23..90b27d0569 100644 --- a/Sming/Arch/Host/build.mk +++ b/Sming/Arch/Host/build.mk @@ -17,6 +17,7 @@ CC := $(TOOLSPEC)gcc CXX := $(TOOLSPEC)g++ AR := $(TOOLSPEC)ar LD := $(TOOLSPEC)g++ +NM := $(TOOLSPEC)nm OBJCOPY := $(TOOLSPEC)objcopy OBJDUMP := $(TOOLSPEC)objdump GDB := $(TOOLSPEC)gdb @@ -33,11 +34,3 @@ MEMANALYZER = size # Command-line options passed to executable - Components add their own settings to this CLI_TARGET_OPTIONS = - -# Run a command in a new terminal window -# $1 -> Command to execute -ifeq ($(UNAME),Windows) -DetachCommand = start $1 -else -DetachCommand = gnome-terminal -- bash -c "sleep 1; $1" -endif diff --git a/Sming/Arch/Host/host-soc.json b/Sming/Arch/Host/host-soc.json new file mode 100644 index 0000000000..f813fd1cb3 --- /dev/null +++ b/Sming/Arch/Host/host-soc.json @@ -0,0 +1,4 @@ +{ + "variant": "host", + "name": "Host Emulator" +} \ No newline at end of file diff --git a/Sming/Arch/Host/standard.hw b/Sming/Arch/Host/standard.hw index 287e348737..7244be0578 100644 --- a/Sming/Arch/Host/standard.hw +++ b/Sming/Arch/Host/standard.hw @@ -3,12 +3,7 @@ "arch": "Host", "bootloader_size": "0x2000", "partition_table_offset": "0x2000", - "devices": { - "spiFlash": { - "type": "flash", - "size": "4M" - } - }, + "options": ["4m"], "partitions": { "rom0": { "address": "0x008000", diff --git a/Sming/Arch/Rp2040/Components/driver/Kconfig b/Sming/Arch/Rp2040/Components/driver/Kconfig new file mode 100644 index 0000000000..566932a5af --- /dev/null +++ b/Sming/Arch/Rp2040/Components/driver/Kconfig @@ -0,0 +1,22 @@ +menu "Drivers" + config USE_US_TIMER + bool "Enable microsecond precision for software timers (Timer2)" + help + The following functions depend on Timer2: + - NOW() return value, the Timer2 tick count + - Software timers + - System time + + Software timers are driven by Timer2, which by default uses a /256 prescale + providing a resolution of 3.2us and a range of 1' 54". + + Enabling this setting increases the resolution to 200ns but reduces the maximum + software timer to 7" 9.5s. + + config ENABLE_CUSTOM_PWM + bool "Use the *New PWM* driver" + default y + help + New PWM is a drop-in replacement for the version provided in the Espressif SDK. + +endmenu diff --git a/Sming/Arch/Rp2040/Components/driver/README.rst b/Sming/Arch/Rp2040/Components/driver/README.rst new file mode 100644 index 0000000000..720bb0c5d5 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/driver/README.rst @@ -0,0 +1,10 @@ +RP2040 Drivers +============== + +Provides low-level peripheral drivers. + +.. toctree:: + :glob: + :maxdepth: 1 + + * diff --git a/Sming/Arch/Rp2040/Components/driver/component.mk b/Sming/Arch/Rp2040/Components/driver/component.mk new file mode 100644 index 0000000000..42cf5d38a5 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/driver/component.mk @@ -0,0 +1,8 @@ +COMPONENT_DEPENDS := rp2040 arch_driver + +COMPONENT_SRCDIRS := . +COMPONENT_INCDIRS := include + +COMPONENT_DOXYGEN_INPUT := include/driver + +COMPONENT_RELINK_VARS := PICO_BOARD diff --git a/Sming/Arch/Rp2040/Components/driver/gpio.rst b/Sming/Arch/Rp2040/Components/driver/gpio.rst new file mode 100644 index 0000000000..b1193c2738 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/driver/gpio.rst @@ -0,0 +1,8 @@ +GPIO: General-Purpose I/O +========================= + +SDK definitions for GPIO. + +.. doxygengroup:: gpio_driver + :content-only: + :members: diff --git a/Sming/Arch/Rp2040/Components/driver/hw_timer.cpp b/Sming/Arch/Rp2040/Components/driver/hw_timer.cpp new file mode 100644 index 0000000000..aa1dad346f --- /dev/null +++ b/Sming/Arch/Rp2040/Components/driver/hw_timer.cpp @@ -0,0 +1,63 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * hw_timer.cpp + * + ****/ + +#include +#include +#include + +hw_timer_private_t hw_timer_private; + +namespace +{ +void IRAM_ATTR timer1_isr() +{ + hw_clear_bits(&timer_hw->intr, BIT(0)); + auto& p = hw_timer_private; + if(p.timer1_callback != nullptr) { + p.timer1_callback(p.timer1_arg); + } + if(p.timer1_autoload) { + timer_hw->alarm[0] += p.timer1_ticks; + } +} + +} // namespace + +void hw_timer1_attach_interrupt(hw_timer_source_type_t source_type, hw_timer_callback_t callback, void* arg) +{ + (void)source_type; + auto& p = hw_timer_private; + irq_set_enabled(TIMER_IRQ_0, false); + p.timer1_callback = callback; + p.timer1_arg = arg; + irq_set_exclusive_handler(TIMER_IRQ_0, timer1_isr); + hw_set_bits(&timer_hw->inte, BIT(0)); + irq_set_enabled(TIMER_IRQ_0, true); +} + +void hw_timer1_detach_interrupt() +{ + hw_clear_bits(&timer_hw->inte, BIT(0)); + irq_set_enabled(TIMER_IRQ_0, false); + irq_remove_handler(TIMER_IRQ_0, timer1_isr); +} + +void IRAM_ATTR hw_timer1_enable(hw_timer_clkdiv_t div, hw_timer_intr_type_t intr_type, bool auto_load) +{ + (void)intr_type; + auto& p = hw_timer_private; + p.timer1_clkdiv = div; + p.timer1_autoload = auto_load; +} + +void hw_timer_init() +{ + // hardware_alarm_claim(0); +} diff --git a/Sming/Arch/Rp2040/Components/driver/hw_timer.rst b/Sming/Arch/Rp2040/Components/driver/hw_timer.rst new file mode 100644 index 0000000000..a496f7c24c --- /dev/null +++ b/Sming/Arch/Rp2040/Components/driver/hw_timer.rst @@ -0,0 +1,12 @@ +hw_timer: Hardware Timers +========================= + +Driver for hardware timers. + + +API Documentation +----------------- + +.. doxygengroup:: hw_timer + :content-only: + :members: diff --git a/Sming/Arch/Rp2040/Components/driver/include/driver/gpio.h b/Sming/Arch/Rp2040/Components/driver/include/driver/gpio.h new file mode 100644 index 0000000000..70dbfef08a --- /dev/null +++ b/Sming/Arch/Rp2040/Components/driver/include/driver/gpio.h @@ -0,0 +1,28 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * gpio.h + * + ****/ + +#pragma once + +#include + +/** + * @defgroup gpio_driver GPIO driver + * @ingroup drivers + * @{ + */ + +enum GPIO_INT_TYPE { + GPIO_PIN_INTR_DISABLE = 0, + GPIO_PIN_INTR_POSEDGE = GPIO_IRQ_EDGE_RISE, + GPIO_PIN_INTR_NEGEDGE = GPIO_IRQ_EDGE_FALL, + GPIO_PIN_INTR_ANYEDGE = GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, + GPIO_PIN_INTR_LOLEVEL = GPIO_IRQ_LEVEL_LOW, + GPIO_PIN_INTR_HILEVEL = GPIO_IRQ_LEVEL_HIGH, +}; diff --git a/Sming/Arch/Rp2040/Components/driver/include/driver/hw_timer.h b/Sming/Arch/Rp2040/Components/driver/include/driver/hw_timer.h new file mode 100644 index 0000000000..2d2270ec9e --- /dev/null +++ b/Sming/Arch/Rp2040/Components/driver/include/driver/hw_timer.h @@ -0,0 +1,156 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * hw_timer.h + * + ****/ + +#pragma once + +#include +#include + +#define HW_TIMER_BASE_CLK 1000000U + +/** + * @defgroup hw_timer Hardware Timer Driver + * @ingroup drivers + * + * @note Timers are 64-bit but for compatibility limit to 31 bits + * @{ + */ + +/** + * @brief Fetch 32-bit microsecond count + * + * All timers reference from a single 64-bit counter. + * We use only the lower 32 bits here as it provides lowest latency + * and compatibility with existing API. + */ +__forceinline uint32_t IRAM_ATTR hw_timer_ticks() +{ + return timer_hw->timerawl; +} + +/************************************* + * + * Timer1 (countdown alarm) + * + *************************************/ + +/** + * @brief Maximum timer interval in ticks + */ +#define MAX_HW_TIMER1_INTERVAL 0x7fffffff + +/** + * @brief Minimum hardware interval in microseconds + * @note Attempting to use repetitive interrupts below this level can lead + * to system instabliity and lockups, due to the software overhead in servicing + * the interrupts. + */ +#define MIN_HW_TIMER1_INTERVAL_US 50U + +typedef void (*hw_timer_callback_t)(void* arg); + +typedef enum { + TIMER_CLKDIV_1, + TIMER_CLKDIV_16, + TIMER_CLKDIV_256, +} hw_timer_clkdiv_t; + +typedef enum { + TIMER_EDGE_INT, // edge interrupt + TIMER_LEVEL_INT, // level interrupt +} hw_timer_intr_type_t; + +typedef enum { + TIMER_FRC1_SOURCE, + TIMER_NMI_SOURCE, +} hw_timer_source_type_t; + +// Internal data +struct hw_timer_private_t { + hw_timer_clkdiv_t timer1_clkdiv; + hw_timer_callback_t timer1_callback; + uint32_t timer1_ticks; + bool timer1_autoload; + void* timer1_arg; +}; + +extern hw_timer_private_t hw_timer_private; + +/** + * @brief Attach an interrupt for the timer + * @param source_type + * @param callback Callback function invoked via timer interrupt + * @param arg Passed to callback function + */ +void IRAM_ATTR hw_timer1_attach_interrupt(hw_timer_source_type_t source_type, hw_timer_callback_t callback, void* arg); + +/** + * @brief Detach interrupt from the timer + */ +void hw_timer1_detach_interrupt(); + +/** + * @brief Enable the timer + * @param div + * @param intr_type + * @param auto_load + */ +void IRAM_ATTR hw_timer1_enable(hw_timer_clkdiv_t div, hw_timer_intr_type_t intr_type, bool auto_load); + +/** + * @brief Set the timer interval and arm + * @param ticks + */ +__forceinline void IRAM_ATTR hw_timer1_write(uint32_t ticks) +{ + ticks <<= hw_timer_private.timer1_clkdiv; + hw_timer_private.timer1_ticks = ticks; + timer_hw->alarm[0] = hw_timer_ticks() + ticks; +} + +/** + * @brief Disable the timer + */ +__forceinline void IRAM_ATTR hw_timer1_disable() +{ + timer_hw->armed = BIT(0); +} + +/** + * @brief Get timer1 count + * @retval uint32_t Current count value, counts from initial value down to 0 + */ +__forceinline uint32_t hw_timer1_read() +{ + int time = hw_timer_ticks() - timer_hw->alarm[0]; + return (time > 0) ? (time >> hw_timer_private.timer1_clkdiv) : 0; +} + +/************************************* + * + * FRC2 timer + * + * This is a 32-bit count-up timer. + * Used for software timers - see os_timer.h + * + *************************************/ + +constexpr uint32_t HW_TIMER2_CLK = HW_TIMER_BASE_CLK; + +/** + * @brief Read current timer2 value + * @retval uint32_t + */ +__forceinline uint32_t hw_timer2_read() +{ + return hw_timer_ticks(); +} + +/** @} */ diff --git a/Sming/Arch/Rp2040/Components/driver/include/driver/os_timer.h b/Sming/Arch/Rp2040/Components/driver/include/driver/os_timer.h new file mode 100644 index 0000000000..d634865d0a --- /dev/null +++ b/Sming/Arch/Rp2040/Components/driver/include/driver/os_timer.h @@ -0,0 +1,57 @@ +/* + * This implementation mimics the behaviour of the ESP8266 Non-OS SDK timers, + * using Timer2 as the reference (which is _not_ in microseconds!) + * + * The ESP32 IDF contains more sophisticated timer implementations, but also + * this same API which it refers to as the 'legacy' timer API. + */ + +#pragma once + +#include + +// Disarmed +#define OS_TIMER_DEFAULT() \ + { \ + .timer_next = (os_timer_t*)-1, \ + } + +typedef void os_timer_func_t(void* timer_arg); + +/** + * @brief This is the structure used by the Espressif timer API + * @note This is used as an element in a linked list + * The Espressif implementation orders the list according to next expiry time. + * os_timer_setfn and os_timer_disarm set timer_next to -1 + * When expired, timer_next is 0 + */ +struct os_timer_t { + /// If disarmed, set to -1, otherwise points to the next queued timer (or NULL if last in the list) + struct os_timer_t* timer_next; + /// Set to the next Timer2 count value when the timer will expire + uint32_t timer_expire; + /// 0 if this is a one-shot timer, otherwise defines the interval in Timer2 ticks + uint32_t timer_period; + /// User-provided callback function pointer + os_timer_func_t* timer_func; + /// Argument passed to the callback function + void* timer_arg; +}; + +void os_timer_arm_ticks(os_timer_t* ptimer, uint32_t ticks, bool repeat_flag); + +void os_timer_arm(os_timer_t* ptimer, uint32_t time, bool repeat_flag); +void os_timer_arm_us(os_timer_t* ptimer, uint32_t time, bool repeat_flag); + +void os_timer_disarm(os_timer_t* ptimer); +void os_timer_setfn(os_timer_t* ptimer, os_timer_func_t* pfunction, void* parg); + +static inline uint64_t os_timer_expire(const os_timer_t* ptimer) +{ + if(ptimer == nullptr || int(ptimer->timer_next) == -1) { + return 0; + } + return ptimer->timer_expire; +} + +void os_timer_done(os_timer_t* ptimer); diff --git a/Sming/Arch/Rp2040/Components/driver/include/driver/pwm.h b/Sming/Arch/Rp2040/Components/driver/include/driver/pwm.h new file mode 100644 index 0000000000..8eb9f2560e --- /dev/null +++ b/Sming/Arch/Rp2040/Components/driver/include/driver/pwm.h @@ -0,0 +1,88 @@ +#pragma once + +#if defined(__cplusplus) +extern "C" { +#endif + +// #include + +#define PWM_CHANNEL_NUM_MAX 16 + +/** + * @defgroup pwm_driver PWM driver + * @ingroup drivers + * @{ + */ + +/** + * @fn void pwm_init(uint32 period, uint32 *duty,uint32 pwm_channel_num,uint32 (*pin_info_list)[3]) + * @brief Initialize PWM function, including GPIO selection, period and duty cycle + * @param period PWM period + * @param duty duty cycle of each output + * @param pwm_channel_num PWM channel number + * @param pin_info_list Array containing an entry for each channel giving + * @note This API can be called only once. + * + * Example: + * + * uint32 io_info[][3] = { + * {PWM_0_OUT_IO_MUX, PWM_0_OUT_IO_FUNC, PWM_0_OUT_IO_NUM}, + * {PWM_1_OUT_IO_MUX, PWM_1_OUT_IO_FUNC, PWM_1_OUT_IO_NUM}, + * {PWM_2_OUT_IO_MUX, PWM_2_OUT_IO_FUNC, PWM_2_OUT_IO_NUM} + * }; + * + * pwm_init(light_param.pwm_period, light_param.pwm_duty, 3, io_info); + * + */ + +/** + * @fn void pwm_start(void) + * @brief Starts PWM + * + * This function needs to be called after PWM configuration is changed. + */ + +/** + * @fn void pwm_set_duty(uint32 duty, uint8 channel) + * @brief Sets duty cycle of a PWM output + * @param duty The time that high-level single will last, duty cycle will be (duty*45)/(period*1000) + * @param channel PWM channel, which depends on how many PWM channels are used + * + * Set the time that high-level signal will last. + * The range of duty depends on PWM period. Its maximum value of which can be Period * 1000 / 45. + * + * For example, for 1-KHz PWM, the duty range is 0 ~ 22222. + */ + +/** + * @fn uint32 pwm_get_duty(uint8 channel) + * @brief Get duty cycle of PWM output + * @param channel PWM channel, which depends on how many PWM channels are used + * @retval uint32 Duty cycle of PWM output + * + * Duty cycle will be (duty*45) / (period*1000). + */ + +/** + * @fn void pwm_set_period(uint32 period) + * @brief Set PWM period + * @param period PWM period in us. For example, 1-KHz PWM period = 1000us. + */ + +/** + * @fn uint32 pwm_get_period(void) + * @brief Get PWM period + * @retval uint32 Return PWM period in us. + */ + +/** + * @fn uint32 get_pwm_version(void) + * @brief Get version information of PWM + * @retval uint32 PWM version + */ + +/** @} */ + +#if defined(__cplusplus) +} +#endif diff --git a/Sming/Arch/Rp2040/Components/driver/include/driver/uart.h b/Sming/Arch/Rp2040/Components/driver/include/driver/uart.h new file mode 100644 index 0000000000..a789636242 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/driver/include/driver/uart.h @@ -0,0 +1,7 @@ +#pragma once + +#define UART0 0 +#define UART1 1 +#define UART_COUNT 2 ///< Number of UARTs on the system, virtual or otherwise + +#include_next diff --git a/Sming/Arch/Rp2040/Components/driver/os_timer.cpp b/Sming/Arch/Rp2040/Components/driver/os_timer.cpp new file mode 100644 index 0000000000..f1d4d31e8b --- /dev/null +++ b/Sming/Arch/Rp2040/Components/driver/os_timer.cpp @@ -0,0 +1,199 @@ +#include +#include +#include +#include +#include +#include + +#ifdef ENABLE_OSTIMER_DEBUG +#define debug_tmr(fmt, ...) m_printf("%u [TMR] " fmt "\r\n", hw_timer2_read(), ##__VA_ARGS__) + +#else +#define debug_tmr(fmt, ...) \ + do { \ + } while(0) +#endif + +namespace +{ +os_timer_t* timer_list; + +/** + * @brief Protect certain code blocks which are callable from interrupt context + */ +class CriticalLock +{ +public: + CriticalLock() + { + level = save_and_disable_interrupts(); + } + + ~CriticalLock() + { + restore_interrupts(level); + } + +private: + uint32_t level; +}; + +static void IRAM_ATTR timer_insert(uint32_t expire, os_timer_t* ptimer) +{ + debug_tmr("insert %p %u", ptimer, expire); + + os_timer_t* t_prev = nullptr; + auto t = timer_list; + while(t != nullptr) { + if(int(t->timer_expire - expire) > 0) { + break; + } + t_prev = t; + t = t->timer_next; + } + if(t_prev == nullptr) { + timer_list = ptimer; + } else { + t_prev->timer_next = ptimer; + } + ptimer->timer_next = t; + ptimer->timer_expire = expire; + +#ifdef ENABLE_OSTIMER_DEBUG + t = timer_list; + while(t != nullptr) { + debug_tmr("%p @ %u", t, t->timer_expire); + t = t->timer_next; + } +#endif +} + +// Schedule next timer, if there is one +void IRAM_ATTR timer_schedule() +{ + // Schedule next timer, if there is one + if(timer_list == nullptr) { + debug_tmr("cancel"); + // Cancel hardware timer + timer_hw->armed = BIT(1); + return; + } + + constexpr int TIMER2_MIN_US{50}; + auto now = hw_timer2_read(); + if(int(timer_list->timer_expire - now) < TIMER2_MIN_US) { + timer_hw->alarm[1] = now + TIMER2_MIN_US; + } else { + timer_hw->alarm[1] = timer_list->timer_expire; + } +} + +os_timer_t* find_expired_timer() +{ + if(timer_list == nullptr) { + return nullptr; + } + + // Using Timer2 hardware to schedule software timers + if(timer_hw->armed & BIT(1)) { + return nullptr; + } + + CriticalLock lock; + + // Pop timer from head of queue + auto t = timer_list; + timer_list = t->timer_next; + t->timer_next = reinterpret_cast(-1); + + debug_tmr("fired %p", t); + + // Repeating timer? + if(t->timer_period != 0) { + timer_insert(t->timer_expire + t->timer_period, t); + } + + timer_schedule(); + + return t; +} + +} // namespace + +void IRAM_ATTR os_timer_arm_ticks(os_timer_t* ptimer, uint32_t ticks, bool repeat_flag) +{ + if(ptimer == nullptr) { + return; + } + + os_timer_disarm(ptimer); + ptimer->timer_period = repeat_flag ? ticks : 0; + + CriticalLock lock; + timer_insert(hw_timer2_read() + ticks, ptimer); + timer_schedule(); +} + +void IRAM_ATTR os_timer_arm(struct os_timer_t* ptimer, uint32_t time, bool repeat_flag) +{ + using R = std::ratio; + auto ticks = muldiv(time); + os_timer_arm_ticks(ptimer, ticks, repeat_flag); +} + +void IRAM_ATTR os_timer_arm_us(struct os_timer_t* ptimer, uint32_t time, bool repeat_flag) +{ + using R = std::ratio; + auto ticks = muldiv(time); + os_timer_arm_ticks(ptimer, ticks, repeat_flag); +} + +void IRAM_ATTR os_timer_disarm(struct os_timer_t* ptimer) +{ + if(ptimer == nullptr || timer_list == nullptr || int(ptimer->timer_next) == -1) { + return; // not armed + } + + CriticalLock lock; + + // Remove timer from list + if(ptimer == timer_list) { + timer_list = ptimer->timer_next; + timer_schedule(); + } else { + for(auto t = timer_list; t->timer_next != nullptr; t = t->timer_next) { + if(t->timer_next == ptimer) { + t->timer_next = ptimer->timer_next; + break; + } + } + } + ptimer->timer_next = reinterpret_cast(-1); +} + +void os_timer_setfn(struct os_timer_t* ptimer, os_timer_func_t* pfunction, void* parg) +{ + if(ptimer != nullptr) { + ptimer->timer_func = pfunction; + ptimer->timer_arg = parg; + ptimer->timer_next = reinterpret_cast(-1); + } +} + +void os_timer_done(struct os_timer_t* ptimer) +{ + os_timer_disarm(ptimer); +} + +void system_init_timers() +{ + // hardware_alarm_claim(1); +} + +void system_service_timers() +{ + auto t = find_expired_timer(); + if(t != nullptr && t->timer_func != nullptr) { + t->timer_func(t->timer_arg); + } +} diff --git a/Sming/Arch/Rp2040/Components/driver/os_timer.rst b/Sming/Arch/Rp2040/Components/driver/os_timer.rst new file mode 100644 index 0000000000..cdce8b181c --- /dev/null +++ b/Sming/Arch/Rp2040/Components/driver/os_timer.rst @@ -0,0 +1,8 @@ +OS Timer +======== + +Driver for software timer queues + +.. doxygengroup:: os_timer + :content-only: + :members: diff --git a/Sming/Arch/Rp2040/Components/driver/pwm.rst b/Sming/Arch/Rp2040/Components/driver/pwm.rst new file mode 100644 index 0000000000..b6d9372e8b --- /dev/null +++ b/Sming/Arch/Rp2040/Components/driver/pwm.rst @@ -0,0 +1,9 @@ +PWM: Pulse-Width Modulation +=========================== + +API Documentation +----------------- + +.. doxygengroup:: pwm_driver + :content-only: + :members: diff --git a/Sming/Arch/Rp2040/Components/driver/uart.cpp b/Sming/Arch/Rp2040/Components/driver/uart.cpp new file mode 100644 index 0000000000..03e99c0bdf --- /dev/null +++ b/Sming/Arch/Rp2040/Components/driver/uart.cpp @@ -0,0 +1,846 @@ +/* + uart.cpp - RP2040 UART driver + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ +using uart_dev_t = uart_hw_t; + +int s_uart_debug_nr = UART_NO; + +// Keep track of interrupt enable state for each UART +uint8_t isrMask; + +struct smg_uart_pins_t { + uint8_t tx; + uint8_t rx; +}; + +#define UART0_PIN_DEFAULT PICO_DEFAULT_UART_TX_PIN, PICO_DEFAULT_UART_RX_PIN +#define UART1_PIN_DEFAULT 4, 5 + +constexpr smg_uart_pins_t defaultPins[UART_COUNT] = { + {UART0_PIN_DEFAULT}, + {UART1_PIN_DEFAULT}, +}; + +uart_dev_t* IRAM_ATTR getDevice(uint8_t uart_nr) +{ + if(uart_nr == 0) { + return uart0_hw; + } + if(uart_nr == 1) { + return uart1_hw; + } + assert(false); + return nullptr; +} + +// Keep a reference to all created UARTS +struct smg_uart_instance_t { + smg_uart_t* uart; + smg_uart_notify_callback_t callback; +}; + +smg_uart_instance_t uartInstances[UART_COUNT]; + +// Return true if transmit FIFO is full +__forceinline bool uart_txfifo_full(uart_dev_t* dev) +{ + return !!(dev->fr & UART_UARTFR_TXFF_BITS); +} + +// Return true if transmit FIFO is empty +__forceinline bool uart_txfifo_empty(uart_dev_t* dev) +{ + return !!(dev->fr & UART_UARTFR_TXFE_BITS); +} + +// Return true if receive FIFO is empty +__forceinline bool uart_rxfifo_empty(uart_dev_t* dev) +{ + return !!(dev->fr & UART_UARTFR_RXFE_BITS); +} + +/** @brief Invoke a port callback, if one has been registered + * @param uart + * @param code + */ +void notify(smg_uart_t* uart, smg_uart_notify_code_t code) +{ + auto callback = uartInstances[uart->uart_nr].callback; + if(callback != nullptr) { + callback(uart, code); + } +} + +__forceinline void uart_disable_isr(uint8_t nr) +{ + irq_set_enabled(UART0_IRQ + nr, false); +} + +__forceinline void uart_enable_isr(uint8_t nr) +{ + irq_set_enabled(UART0_IRQ + nr, true); +} + +bool realloc_buffer(SerialBuffer*& buffer, size_t new_size) +{ + if(buffer != nullptr) { + if(new_size == 0) { + delete buffer; + buffer = nullptr; + return true; + } + + return buffer->resize(new_size) == new_size; + } + + if(new_size == 0) { + return true; + } + + auto new_buf = new SerialBuffer; + if(new_buf != nullptr && new_buf->resize(new_size) == new_size) { + buffer = new_buf; + return true; + } + + delete new_buf; + return false; +} + +void IRAM_ATTR handleInterrupt(smg_uart_t* uart, uart_dev_t* dev) +{ + auto mis = dev->mis; + + // If status is clear there's no interrupt to service on this UART + if(mis == 0) { + return; + } + + // Value to be passed to callback + auto user_is = mis; + + // Deal with the event, unless we're in raw mode + if(!bitRead(uart->options, UART_OPT_CALLBACK_RAW)) { + // Rx FIFO full, timeout or receive overflow + auto rxfifo_full = mis & UART_UARTMIS_RXMIS_BITS; + auto rxfifo_tout = mis & UART_UARTMIS_RTMIS_BITS; + auto rxfifo_ovf = mis & UART_UARTMIS_OEMIS_BITS; + if(rxfifo_full || rxfifo_tout || rxfifo_ovf) { + bool read{false}; + + // Read as much data as possible from the RX FIFO into buffer + if(uart->rx_buffer != nullptr) { + size_t space = uart->rx_buffer->getFreeSpace(); + while(space != 0 && !uart_rxfifo_empty(dev)) { + uint8_t c = dev->dr; + uart->rx_buffer->writeChar(c); + --space; + read = true; + } + + // Don't call back until buffer is (almost) full + if(space > uart->rx_headroom) { + user_is &= ~UART_UARTMIS_RXMIS_BITS; + } + } + + /* + * If the FIFO is full and we didn't read any of the data then need to mask the interrupt out or it'll recur. + * The interrupt gets re-enabled by a call to uart_read() or uart_flush() + */ + if(rxfifo_ovf) { + hw_clear_bits(&dev->imsc, UART_UARTIMSC_OEIM_BITS); + } else if(read == 0) { + hw_set_bits(&dev->imsc, UART_UARTIMSC_RXIM_BITS | UART_UARTIMSC_RTIM_BITS); + } + } + + // Unless we replenish TX FIFO, disable after handling interrupt + auto txfifo_empty = mis & UART_UARTMIS_TXMIS_BITS; + if(txfifo_empty) { + // Dump as much data as we can from buffer into the TX FIFO + if(uart->tx_buffer != nullptr) { + size_t avail = uart->tx_buffer->available(); + while(avail-- && !uart_txfifo_full(dev)) { + uint8_t c = uart->tx_buffer->readChar(); + dev->dr = c; + } + } + + // If TX FIFO remains empty then we must disable TX FIFO EMPTY interrupt to stop it recurring. + if(uart_txfifo_empty(dev)) { + // The interrupt gets re-enabled by uart_write() + hw_clear_bits(&dev->imsc, UART_UARTIMSC_TXIM_BITS); + } else { + // We've topped up TX FIFO so defer callback until next time + user_is &= ~UART_UARTMIS_TXMIS_BITS; + } + } + } + + // Translate interrupt status flag bits into API values + uint32_t status{0}; + if(user_is & UART_UARTMIS_RXMIS_BITS) { + status |= UART_STATUS_RXFIFO_FULL; + } + if(user_is & UART_UARTMIS_RTMIS_BITS) { + status |= UART_STATUS_RXFIFO_TOUT; + } + if(user_is & UART_UARTMIS_OEMIS_BITS) { + status |= UART_STATUS_RXFIFO_OVF; + } + if(user_is & UART_UARTMIS_TXMIS_BITS) { + status |= UART_STATUS_TXFIFO_EMPTY; + } + if(user_is & UART_UARTMIS_BEMIS_BITS) { + status |= UART_STATUS_BRK_DET; + } + if(user_is & UART_UARTMIS_FEMIS_BITS) { + status |= UART_STATUS_FRM_ERR; + } + + // Keep a note of persistent flags - cleared via uart_get_status() + uart->status |= status; + + if(status != 0 && uart->callback != nullptr) { + uart->callback(uart, status); + } + + // Final step is to clear status flags + dev->icr = mis; +} + +void IRAM_ATTR uart0_isr() +{ + handleInterrupt(uartInstances[0].uart, uart0_hw); +} + +void IRAM_ATTR uart1_isr() +{ + handleInterrupt(uartInstances[1].uart, uart1_hw); +} + +} // namespace + +smg_uart_t* smg_uart_get_uart(uint8_t uart_nr) +{ + return (uart_nr < UART_COUNT) ? uartInstances[uart_nr].uart : nullptr; +} + +uint8_t smg_uart_disable_interrupts() +{ + if(isrMask & BIT(0)) { + irq_set_enabled(UART0_IRQ, false); + } + if(isrMask & BIT(1)) { + irq_set_enabled(UART1_IRQ, false); + } + return isrMask; +} + +void smg_uart_restore_interrupts() +{ + if(isrMask & BIT(0)) { + irq_set_enabled(UART0_IRQ, true); + } + if(isrMask & BIT(1)) { + irq_set_enabled(UART1_IRQ, true); + } +} + +bool smg_uart_set_notify(unsigned uart_nr, smg_uart_notify_callback_t callback) +{ + if(uart_nr >= UART_COUNT) { + return false; + } + + uartInstances[uart_nr].callback = callback; + return true; +} + +void smg_uart_set_callback(smg_uart_t* uart, smg_uart_callback_t callback, void* param) +{ + if(uart != nullptr) { + uart->callback = nullptr; // In case interrupt fires between setting param and callback + uart->param = param; + uart->callback = callback; + } +} + +size_t smg_uart_resize_rx_buffer(smg_uart_t* uart, size_t new_size) +{ + if(smg_uart_rx_enabled(uart)) { + uart_disable_isr(uart->uart_nr); + realloc_buffer(uart->rx_buffer, new_size); + uart_enable_isr(uart->uart_nr); + } + return smg_uart_rx_buffer_size(uart); +} + +size_t smg_uart_rx_buffer_size(smg_uart_t* uart) +{ + return uart != nullptr && uart->rx_buffer != nullptr ? uart->rx_buffer->getSize() : 0; +} + +size_t smg_uart_resize_tx_buffer(smg_uart_t* uart, size_t new_size) +{ + if(smg_uart_tx_enabled(uart)) { + uart_disable_isr(uart->uart_nr); + realloc_buffer(uart->tx_buffer, new_size); + uart_enable_isr(uart->uart_nr); + } + return smg_uart_tx_buffer_size(uart); +} + +size_t smg_uart_tx_buffer_size(smg_uart_t* uart) +{ + return uart != nullptr && uart->tx_buffer != nullptr ? uart->tx_buffer->getSize() : 0; +} + +int smg_uart_peek_char(smg_uart_t* uart) +{ + return uart != nullptr && uart->rx_buffer ? uart->rx_buffer->peekChar() : -1; +} + +int smg_uart_rx_find(smg_uart_t* uart, char c) +{ + if(uart == nullptr || uart->rx_buffer == nullptr) { + return -1; + } + + return uart->rx_buffer->find(c); +} + +int smg_uart_peek_last_char(smg_uart_t* uart) +{ + return uart != nullptr && uart->rx_buffer != nullptr ? uart->rx_buffer->peekLastChar() : -1; +} + +size_t smg_uart_read(smg_uart_t* uart, void* buffer, size_t size) +{ + if(!smg_uart_rx_enabled(uart) || buffer == nullptr || size == 0) { + return 0; + } + + notify(uart, UART_NOTIFY_BEFORE_READ); + + size_t read = 0; + + auto buf = static_cast(buffer); + + // First read data from RX buffer if in use + if(uart->rx_buffer != nullptr) { + while(read < size && !uart->rx_buffer->isEmpty()) + buf[read++] = uart->rx_buffer->readChar(); + } + + // Top up from hardware FIFO + auto dev = getDevice(uart->uart_nr); + while(read < size && !uart_rxfifo_empty(dev)) { + uint8_t c = dev->dr; + buf[read++] = c; + } + + // FIFO full may have been disabled if buffer overflowed, re-enabled it now + dev->icr = UART_UARTMIS_RXMIS_BITS | UART_UARTMIS_RTMIS_BITS | UART_UARTMIS_OEMIS_BITS; + hw_set_bits(&dev->imsc, UART_UARTIMSC_RXIM_BITS | UART_UARTIMSC_RTIM_BITS | UART_UARTIMSC_OEIM_BITS); + + return read; +} + +size_t smg_uart_rx_available(smg_uart_t* uart) +{ + return uart->rx_buffer ? uart->rx_buffer->available() : 0; +} + +void smg_uart_start_isr(smg_uart_t* uart) +{ + uint32_t int_ena{0}; + uint32_t fifo_level_select{0}; + + auto dev = getDevice(uart->uart_nr); + + if(smg_uart_rx_enabled(uart)) { + // Trigger at >= 7/8 full + fifo_level_select |= 5 << UART_UARTIFLS_RXIFLSEL_LSB; + + /* + * There is little benefit in generating interrupts on errors, instead these + * should be cleared at the start of a transaction and checked at the end. + * See uart_get_status(). + */ + int_ena |= UART_UARTIMSC_RXIM_BITS // rxfifo_full + | UART_UARTIMSC_RTIM_BITS // rxfifo_tout + | UART_UARTIMSC_OEIM_BITS // rxfifo_ovf + | UART_UARTIMSC_BEIM_BITS // brk_det + | UART_UARTIMSC_PEIM_BITS // parity error + | UART_UARTIMSC_FEIM_BITS // framing error + ; + } + + if(smg_uart_tx_enabled(uart)) { + /* + * We can interrupt when TX FIFO is empty; at 1Mbit that gives us 800 CPU + * cycles before the last character has actually gone over the wire. Even if + * a gap occurs it is unlike to cause any problems. It also makes the callback + * more useful, for example if using it for RS485 we'd then want to reverse + * transfer direction and begin waiting for a response. + */ + + // TX FIFO empty interrupt only gets enabled via uart_write function() + + // Trigger at <= 1/8 full + fifo_level_select |= 0 << UART_UARTIFLS_TXIFLSEL_LSB; + } + + dev->ifls = fifo_level_select; + + // Clear and enable required UART interrupts + dev->icr = UART_UARTICR_BITS; + dev->imsc = int_ena; + + // Enable interrupt handler + auto irq = UART0_IRQ + uart->uart_nr; + irq_set_exclusive_handler(irq, (uart->uart_nr == 0) ? uart0_isr : uart1_isr); + irq_set_enabled(irq, true); + bitSet(isrMask, uart->uart_nr); +} + +size_t smg_uart_write(smg_uart_t* uart, const void* buffer, size_t size) +{ + if(!smg_uart_tx_enabled(uart) || buffer == nullptr || size == 0) { + return 0; + } + + size_t written = 0; + + auto buf = static_cast(buffer); + + while(written < size) { + // If TX buffer not in use or it's empty then write directly to hardware FIFO + if(uart->tx_buffer == nullptr || uart->tx_buffer->isEmpty()) { + auto dev = getDevice(uart->uart_nr); + while(written < size && !uart_txfifo_full(dev)) { + dev->dr = buf[written++]; + } + + // Enable TX FIFO EMPTY interrupt + dev->icr = UART_UARTMIS_TXMIS_BITS; + hw_set_bits(&dev->imsc, UART_UARTIMSC_TXIM_BITS); + } + + // Write any remaining data into transmit buffer + if(uart->tx_buffer != nullptr) { + while(written < size && uart->tx_buffer->writeChar(buf[written])) { + ++written; + } + } + + notify(uart, UART_NOTIFY_AFTER_WRITE); + + if(!bitRead(uart->options, UART_OPT_TXWAIT)) { + break; + } + } + + return written; +} + +size_t smg_uart_tx_free(smg_uart_t* uart) +{ + return uart->tx_buffer ? uart->tx_buffer->getFreeSpace() : 0; +} + +void smg_uart_wait_tx_empty(smg_uart_t* uart) +{ + if(!smg_uart_tx_enabled(uart)) { + return; + } + + notify(uart, UART_NOTIFY_WAIT_TX); + + if(uart->tx_buffer != nullptr) { + while(!uart->tx_buffer->isEmpty()) { + } + } + + auto dev = getDevice(uart->uart_nr); + while((dev->fr & UART_UARTFR_TXFE_BITS) != 0) { + } +} + +void smg_uart_set_break(smg_uart_t* uart, bool state) +{ + if(uart == nullptr) { + return; + } + + auto dev = getDevice(uart->uart_nr); + if(state) { + hw_set_bits(&dev->lcr_h, UART_UARTLCR_H_BRK_BITS); + } else { + hw_clear_bits(&dev->lcr_h, UART_UARTLCR_H_BRK_BITS); + } +} + +uint8_t smg_uart_get_status(smg_uart_t* uart) +{ + if(uart == nullptr) { + return 0; + } + + uart_disable_isr(uart->uart_nr); + auto dev = getDevice(uart->uart_nr); + // Get and clear break/overflow flags from uart + auto rsr = dev->rsr & (UART_UARTRSR_BE_BITS | UART_UARTRSR_OE_BITS | UART_UARTRSR_PE_BITS); + dev->rsr = rsr; // Clear errors + // Read raw status directly from uart, masking out non-error bits + auto raw = dev->ris & (UART_UARTRIS_OERIS_BITS | UART_UARTRIS_BERIS_BITS | UART_UARTRIS_FERIS_BITS); + dev->icr = raw; // clear errors + // Fetch latched status and clear it + auto status = uart->status; + uart->status = 0; + uart_enable_isr(uart->uart_nr); + + // Now translate hardware flags into API values + if(rsr & UART_UARTRSR_BE_BITS) { + status |= UART_STATUS_BRK_DET; + } + if(rsr & UART_UARTRSR_OE_BITS) { + status |= UART_STATUS_RXFIFO_OVF; + } + if(rsr & UART_UARTRSR_PE_BITS) { + status |= UART_STATUS_PARITY_ERR; + } + if(raw & UART_UARTRIS_OERIS_BITS) { + status |= UART_STATUS_RXFIFO_OVF; + } + if(raw & UART_UARTRIS_BERIS_BITS) { + status |= UART_STATUS_BRK_DET; + } + if(raw & UART_UARTRIS_FERIS_BITS) { + status |= UART_STATUS_FRM_ERR; + } + + return status; +} + +void smg_uart_flush(smg_uart_t* uart, smg_uart_mode_t mode) +{ + if(uart == nullptr) { + return; + } + + bool flushRx = mode == UART_FULL || mode == UART_RX_ONLY; + bool flushTx = mode == UART_FULL || mode == UART_TX_ONLY; + + uart_disable_isr(uart->uart_nr); + if(flushRx && uart->rx_buffer != nullptr) { + uart->rx_buffer->clear(); + } + + if(flushTx && uart->tx_buffer != nullptr) { + uart->tx_buffer->clear(); + } + + auto dev = getDevice(uart->uart_nr); + + if(flushTx) { + // Prevent TX FIFO EMPTY interrupts - don't need them until uart_write is called again + hw_clear_bits(&dev->imsc, UART_UARTIMSC_TXIM_BITS); + while(!uart_txfifo_empty(dev)) { + // + } + } + + // If receive overflow occurred then these interrupts will be masked + if(flushRx) { + while(!uart_rxfifo_empty(dev)) { + uint8_t c = dev->dr; + (void)c; + } + + // Clear all receive flag bits + dev->icr = UART_UARTICR_RXIC_BITS // rxfifo_full + | UART_UARTICR_RTIC_BITS // rxfifo_tout + | UART_UARTICR_OEIC_BITS // rxfifo_ovf + ; + + hw_set_bits(&dev->imsc, UART_UARTIMSC_RXIM_BITS // rxfifo_full + | UART_UARTIMSC_RTIM_BITS // rxfifo_tout + | UART_UARTIMSC_OEIM_BITS // rxfifo_ovf + ); + } + + uart_enable_isr(uart->uart_nr); +} + +uint32_t smg_uart_set_baudrate_reg(int uart_nr, uint32_t baud_rate) +{ + if(baud_rate == 0) { + return 0; + } + + auto clock_hz = clock_get_hz(clk_peri); + uint32_t baud_rate_div = 8 * clock_hz / baud_rate; + uint32_t baud_ibrd = baud_rate_div >> 7; + uint32_t baud_fbrd{0}; + + if(baud_ibrd == 0) { + baud_ibrd = 1; + } else if(baud_ibrd >= 0xffff) { + baud_ibrd = 0xffff; + } else { + baud_fbrd = ((baud_rate_div & 0x7f) + 1) / 2; + } + + // Load PL011's baud divisor registers + auto dev = getDevice(uart_nr); + dev->ibrd = baud_ibrd; + dev->fbrd = baud_fbrd; + + // PL011 needs a (dummy) line control register write to latch in the + // divisors. We don't want to actually change LCR contents here. + hw_set_bits(&dev->lcr_h, 0); + + // Return the actual baud rate in use + return 4 * clock_hz / ((64 * baud_ibrd) + baud_fbrd); +} + +uint32_t smg_uart_set_baudrate(smg_uart_t* uart, uint32_t baud_rate) +{ + baud_rate = smg_uart_set_baudrate_reg(uart->uart_nr, baud_rate); + // Store the actual baud rate in use + uart->baud_rate = baud_rate; + return baud_rate; +} + +uint32_t smg_uart_get_baudrate(smg_uart_t* uart) +{ + return uart ? uart->baud_rate : 0; +} + +smg_uart_t* smg_uart_init_ex(const smg_uart_config_t& cfg) +{ + // Already initialised? + if(cfg.uart_nr >= UART_COUNT || uartInstances[cfg.uart_nr].uart != nullptr) { + return nullptr; + } + + auto uart = new smg_uart_t{}; + if(uart == nullptr) { + return nullptr; + } + + uart->uart_nr = cfg.uart_nr; + uart->mode = cfg.mode; + uart->options = cfg.options; + uart->tx_pin = uart->rx_pin = UART_PIN_DEFAULT; + uart->rx_headroom = 16; + + int tx_pin = cfg.tx_pin; + int rx_pin = cfg.rx_pin; + + auto rxBufferSize = cfg.rx_size; + auto txBufferSize = cfg.tx_size; + + if(smg_uart_rx_enabled(uart)) { + if(!realloc_buffer(uart->rx_buffer, rxBufferSize)) { + delete uart; + return nullptr; + } + rx_pin = (cfg.rx_pin == UART_PIN_DEFAULT) ? defaultPins[cfg.uart_nr].rx : cfg.rx_pin; + } else { + rx_pin = UART_PIN_NO_CHANGE; + } + + if(smg_uart_tx_enabled(uart)) { + if(!realloc_buffer(uart->tx_buffer, txBufferSize)) { + delete uart->rx_buffer; + delete uart; + return nullptr; + } + tx_pin = (tx_pin == UART_PIN_DEFAULT) ? defaultPins[cfg.uart_nr].tx : cfg.tx_pin; + } else { + tx_pin = UART_PIN_NO_CHANGE; + } + + // OK, buffers allocated so setup hardware + auto reset_bits = (uart->uart_nr == 1) ? RESETS_RESET_UART1_BITS : RESETS_RESET_UART0_BITS; + reset_block(reset_bits); + unreset_block_wait(reset_bits); + + smg_uart_detach(cfg.uart_nr); + smg_uart_set_baudrate(uart, cfg.baudrate); + + auto dev = getDevice(cfg.uart_nr); + + // Setup line control register + smg_uart_config_format_t fmt; + fmt.val = cfg.config; + uint32_t lcr{0}; + lcr |= fmt.bits << UART_UARTLCR_H_WLEN_LSB; // data bits + if(fmt.stop_bits != UART_NB_STOP_BIT_1) { // stop bits + lcr |= UART_UARTLCR_H_STP2_BITS; + } + lcr |= fmt.parity << UART_UARTLCR_H_PEN_LSB; // parity + lcr |= UART_UARTLCR_H_FEN_BITS; // Enable FIFOs + dev->lcr_h = lcr; + + // Enable the UART + if(uart->mode == UART_TX_ONLY) { + dev->cr = UART_UARTCR_UARTEN_BITS | UART_UARTCR_TXE_BITS; + } else if(uart->mode == UART_RX_ONLY) { + dev->cr = UART_UARTCR_UARTEN_BITS | UART_UARTCR_RXE_BITS; + } else { + dev->cr = UART_UARTCR_UARTEN_BITS | UART_UARTCR_TXE_BITS | UART_UARTCR_RXE_BITS; + } + + // Always enable DREQ signals -- no harm in this if DMA is not listening + dev->dmacr = UART_UARTDMACR_TXDMAE_BITS | UART_UARTDMACR_RXDMAE_BITS; + + smg_uart_set_pins(uart, tx_pin, rx_pin); + + smg_uart_flush(uart); + uartInstances[cfg.uart_nr].uart = uart; + smg_uart_start_isr(uart); + + notify(uart, UART_NOTIFY_AFTER_OPEN); + + return uart; +} + +void smg_uart_uninit(smg_uart_t* uart) +{ + if(uart == nullptr) { + return; + } + + notify(uart, UART_NOTIFY_BEFORE_CLOSE); + + smg_uart_stop_isr(uart); + // If debug output being sent to this UART, disable it + if(uart->uart_nr == s_uart_debug_nr) { + smg_uart_set_debug(UART_NO); + } + + auto reset_bits = (uart->uart_nr == 1) ? RESETS_RESET_UART1_BITS : RESETS_RESET_UART0_BITS; + reset_block(reset_bits); + + uartInstances[uart->uart_nr].uart = nullptr; + delete uart->rx_buffer; + delete uart->tx_buffer; + delete uart; +} + +smg_uart_t* smg_uart_init(uint8_t uart_nr, uint32_t baudrate, uint32_t config, smg_uart_mode_t mode, uint8_t tx_pin, + size_t rx_size, size_t tx_size) +{ + smg_uart_config_t cfg = {.uart_nr = uart_nr, + .tx_pin = tx_pin, + .rx_pin = UART_PIN_DEFAULT, + .mode = mode, + .options = _BV(UART_OPT_TXWAIT), + .baudrate = baudrate, + .config = config, + .rx_size = rx_size, + .tx_size = tx_size}; + return smg_uart_init_ex(cfg); +} + +void smg_uart_swap(smg_uart_t* uart, int tx_pin) +{ + // Not implemented +} + +bool smg_uart_set_tx(smg_uart_t* uart, int tx_pin) +{ + return uart == nullptr ? false : smg_uart_set_pins(uart, tx_pin, -1); +} + +bool smg_uart_set_pins(smg_uart_t* uart, int tx_pin, int rx_pin) +{ + if(uart == nullptr) { + return false; + } + + // Valid GPIO for UART TX function + auto is_tx_pin = [&](uint8_t pin) -> bool { + const uint8_t uart_tx_pins[2][4] = { + {0, 12, 16, 28}, + {4, 8, 20, 24}, + }; + auto& txpins = uart_tx_pins[uart->uart_nr]; + return pin == txpins[0] || pin == txpins[1] || pin == txpins[2] || pin == txpins[3]; + }; + // UART pins are in groups, RX pins follow TX + auto is_rx_pin = [&](uint8_t pin) -> bool { return is_tx_pin(pin - 1); }; + + if(tx_pin != UART_PIN_NO_CHANGE && !is_tx_pin(tx_pin)) { + return false; + } + if(rx_pin != UART_PIN_NO_CHANGE && !is_rx_pin(rx_pin)) { + return false; + } + + if(tx_pin != UART_PIN_NO_CHANGE) { + if(uart->tx_pin != UART_PIN_DEFAULT) { + gpio_set_function(uart->tx_pin, GPIO_FUNC_NULL); + } + gpio_set_function(tx_pin, GPIO_FUNC_UART); + uart->tx_pin = tx_pin; + } + + if(rx_pin != UART_PIN_NO_CHANGE) { + if(uart->rx_pin != UART_PIN_DEFAULT) { + gpio_set_function(uart->rx_pin, GPIO_FUNC_NULL); + } + gpio_set_function(rx_pin, GPIO_FUNC_UART); + uart->rx_pin = rx_pin; + } + + return true; +} + +void smg_uart_set_debug(int uart_nr) +{ + s_uart_debug_nr = uart_nr; +} + +int smg_uart_get_debug() +{ + return s_uart_debug_nr; +} + +void smg_uart_detach(int uart_nr) +{ + if(!bitRead(isrMask, uart_nr)) { + return; + } + + uart_disable_isr(uart_nr); + auto dev = getDevice(uart_nr); + dev->imsc = 0; + + bitClear(isrMask, uart_nr); +} + +void smg_uart_detach_all() +{ + smg_uart_detach(0); + smg_uart_detach(1); +} diff --git a/Sming/Arch/Rp2040/Components/driver/uart.rst b/Sming/Arch/Rp2040/Components/driver/uart.rst new file mode 100644 index 0000000000..665a30ec31 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/driver/uart.rst @@ -0,0 +1,8 @@ +UART: Universal Asynchronous Receive/Transmit +============================================= + +Custom asynchronous driver. + +.. doxygengroup:: uart_driver + :content-only: + :members: diff --git a/Sming/Arch/Rp2040/Components/gdbstub/README.rst b/Sming/Arch/Rp2040/Components/gdbstub/README.rst new file mode 100644 index 0000000000..e13e526cee --- /dev/null +++ b/Sming/Arch/Rp2040/Components/gdbstub/README.rst @@ -0,0 +1,6 @@ +GDB Stub for RP2040 +=================== + +This defines the command line to use when ``make gdb`` is run. + +TODO: Implement stub code to allow serial debugging. diff --git a/Sming/Arch/Rp2040/Components/gdbstub/component.mk b/Sming/Arch/Rp2040/Components/gdbstub/component.mk new file mode 100644 index 0000000000..46fd3ee841 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/gdbstub/component.mk @@ -0,0 +1,6 @@ +# Full GDB command line +DEBUG_VARS += GDBSTUB_DIR +GDBSTUB_DIR := $(COMPONENT_PATH) + +CACHE_VARS += GDB_CMDLINE +GDB_CMDLINE = trap '' INT; $(GDB) -x $(GDBSTUB_DIR)/gdbcmds --args $(TARGET_OUT_0) $(CLI_TARGET_OPTIONS) --pause -- $(HOST_PARAMETERS) diff --git a/Sming/Arch/Rp2040/Components/gdbstub/gdb_syscall.cpp b/Sming/Arch/Rp2040/Components/gdbstub/gdb_syscall.cpp new file mode 100644 index 0000000000..52c57f1c0d --- /dev/null +++ b/Sming/Arch/Rp2040/Components/gdbstub/gdb_syscall.cpp @@ -0,0 +1,8 @@ +#include +#include + +int gdb_syscall(const GdbSyscallInfo& info) +{ + errno = ENODEV; + return -1; +} diff --git a/Sming/Arch/Rp2040/Components/gdbstub/gdbcmds b/Sming/Arch/Rp2040/Components/gdbstub/gdbcmds new file mode 100644 index 0000000000..ce3dfcdbb9 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/gdbstub/gdbcmds @@ -0,0 +1,10 @@ +handle SIGUSR1 nostop noprint + +# Enable this if you want to log all traffic between GDB and the stub +#set remotelogfile gdb_rsp_logfile.txt + +# Useful for lower-level debugging to see the result of stepping through assembler code +#set disassemble-next-line on + +# Display a welcome prompt +echo \nWelcome to SMING!\nType 'r' to run application\n\n diff --git a/Sming/Arch/Rp2040/Components/gdbstub/gdbstub.c b/Sming/Arch/Rp2040/Components/gdbstub/gdbstub.c new file mode 100644 index 0000000000..4b22298076 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/gdbstub/gdbstub.c @@ -0,0 +1,29 @@ +#include + +void gdb_enable(bool state) +{ +} + +GdbState gdb_present(void) +{ + return eGDB_NotPresent; +} + +void __attribute__((weak)) gdb_on_attach(bool attached) +{ +} + +void gdb_detach(void) +{ +} + + + +unsigned __gdb_no_op(void) +{ + return 0; +} + +//#define NOOP __attribute__((weak, alias("__gdb_no_op"))) +// +//void gdb_on_attach(bool attached) NOOP; diff --git a/Sming/Arch/Rp2040/Components/libc/README.rst b/Sming/Arch/Rp2040/Components/libc/README.rst new file mode 100644 index 0000000000..fd5cfaf62a --- /dev/null +++ b/Sming/Arch/Rp2040/Components/libc/README.rst @@ -0,0 +1,4 @@ +RP2040 LIBC Component +===================== + +This Component accommodates the differences in runtime libraries for the various supported toolchains. diff --git a/Sming/Arch/Rp2040/Components/libc/component.mk b/Sming/Arch/Rp2040/Components/libc/component.mk new file mode 100644 index 0000000000..e316951715 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/libc/component.mk @@ -0,0 +1,11 @@ +COMPONENT_INCDIRS := src/include +COMPONENT_SRCDIRS := src + +# pico_printf +LIBC_DEFSYMS := \ + __wrap_putchar=m_putc \ + __wrap_puts=m_puts \ + __wrap_vprintf=m_vprintf \ + __wrap_printf=m_printf + +EXTRA_LDFLAGS := $(call DefSym,$(LIBC_DEFSYMS)) diff --git a/Sming/Arch/Rp2040/Components/libc/src/heap.c b/Sming/Arch/Rp2040/Components/libc/src/heap.c new file mode 100644 index 0000000000..de274e3b4e --- /dev/null +++ b/Sming/Arch/Rp2040/Components/libc/src/heap.c @@ -0,0 +1,16 @@ +/* + * heap.c + */ + +#include "include/heap.h" +#include + +uint32_t system_get_free_heap_size(void) +{ + // These are set by linker + extern char __end__; + extern char __StackLimit; + uint32_t maxHeap = (uint32_t)&__StackLimit - (uint32_t)&__end__; + struct mallinfo m = mallinfo(); + return maxHeap - m.uordblks; +} diff --git a/Sming/Arch/Rp2040/Components/libc/src/include/esp_attr.h b/Sming/Arch/Rp2040/Components/libc/src/include/esp_attr.h new file mode 100644 index 0000000000..34a29d9f7e --- /dev/null +++ b/Sming/Arch/Rp2040/Components/libc/src/include/esp_attr.h @@ -0,0 +1,32 @@ +// ESP8266 attribute definitions (previously in c_types.h) +#pragma once + +// http://stackoverflow.com/a/35441900 +#define MACROQUOT(x) #x +#define MACROQUOTE(x) MACROQUOT(x) + +#define STORE_TYPEDEF_ATTR __attribute__((aligned(4), packed)) +#define STORE_ATTR __attribute__((aligned(4))) + +#define DMEM_ATTR __attribute__((section(".bss"))) + +#define ICACHE_FLASH_SECTION ".rodata" + +#define ICACHE_FLASH_ATTR \ + __attribute__((section(ICACHE_FLASH_SECTION "." __FILE__ "." MACROQUOTE(__LINE__) "." MACROQUOTE(__COUNTER__)))) + +#define ICACHE_RODATA_SECTION ICACHE_FLASH_SECTION + +#define ICACHE_RODATA_ATTR ICACHE_FLASH_ATTR + +#define ICACHE_RAM_SECTION ".time_critical." + +#define IRAM_ATTR __attribute__((section(ICACHE_RAM_SECTION "." MACROQUOTE(__LINE__) "." MACROQUOTE(__COUNTER__)))) + +#define STORE_ATTR __attribute__((aligned(4))) + +#ifdef ENABLE_GDB +#define GDB_IRAM_ATTR IRAM_ATTR +#else +#define GDB_IRAM_ATTR +#endif diff --git a/Sming/Arch/Rp2040/Components/libc/src/include/heap.h b/Sming/Arch/Rp2040/Components/libc/src/include/heap.h new file mode 100644 index 0000000000..180eed6642 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/libc/src/include/heap.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +uint32_t system_get_free_heap_size(void); + +#define os_malloc(s) malloc(s) +#define os_free(p) free(p) + +#ifdef __cplusplus +} +#endif diff --git a/Sming/Arch/Rp2040/Components/libc/src/include/sys/pgmspace.h b/Sming/Arch/Rp2040/Components/libc/src/include/sys/pgmspace.h new file mode 100644 index 0000000000..676e70fec6 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/libc/src/include/sys/pgmspace.h @@ -0,0 +1,80 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * pgmspace.h - Support for reading flash memory + * + ****/ + +#pragma once + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Simple check to determine if a pointer refers to flash memory + */ +#define isFlashPtr(ptr) ((uint32_t)(ptr) >= XIP_MAIN_BASE && (uint32_t)(ptr) < XIP_NOALLOC_BASE) + +#define PROGMEM STORE_ATTR ICACHE_RODATA_ATTR +#define PROGMEM_PSTR PROGMEM +#define PSTR(str) (str) + +#define PGM_P const char* +#define PGM_VOID_P const void* + +/** + * @name Macros to safely read PROGMEM locations + * @{ + */ + +#define pgm_read_byte(addr) (*(const unsigned char*)(addr)) +#define pgm_read_word(addr) \ + ({ \ + uint32_t tmp_addr = (uint32_t)(addr); \ + *(const uint16_t*)tmp_addr; \ + }) +#define pgm_read_dword(addr) \ + ({ \ + uint32_t tmp_addr = (uint32_t)(addr); \ + *(const uint32_t*)tmp_addr; \ + }) +#define pgm_read_float(addr) \ + ({ \ + uint32_t tmp_addr = (uint32_t)(addr); \ + *(const float*)tmp_addr; \ + }) + +/** @} */ + +#define pgm_read_byte_near(addr) pgm_read_byte(addr) +#define pgm_read_word_near(addr) pgm_read_word(addr) +#define pgm_read_dword_near(addr) pgm_read_dword(addr) +#define pgm_read_float_near(addr) pgm_read_float(addr) +#define pgm_read_byte_far(addr) pgm_read_byte(addr) +#define pgm_read_word_far(addr) pgm_read_word(addr) +#define pgm_read_dword_far(addr) pgm_read_dword(addr) +#define pgm_read_float_far(addr) pgm_read_float(addr) + +#define memcpy_P(dest, src, num) memcpy(dest, src, num) +#define memcmp_P(a1, b1, len) memcmp(a1, b1, len) +#define strlen_P(a) strlen(a) +#define strcpy_P(dest, src) strcpy(dest, src) +#define strncpy_P(dest, src, size) strncpy(dest, src, size) +#define strcmp_P(a, b) strcmp(a, b) +#define strncmp_P(str1, str2_P, size) strncmp(str1, str2_P, size) +#define strcasecmp_P(a, b) strcasecmp(a, b) +#define strcat_P(dest, src) strcat(dest, src) +#define strstr_P(a, b) strstr(a, b) +#define sprintf_P(s, f, ...) m_snprintf(s, 1024, f, ##__VA_ARGS__) + +#ifdef __cplusplus +} +#endif diff --git a/Sming/Arch/Rp2040/Components/picotool/README.rst b/Sming/Arch/Rp2040/Components/picotool/README.rst new file mode 100644 index 0000000000..e887b5d13e --- /dev/null +++ b/Sming/Arch/Rp2040/Components/picotool/README.rst @@ -0,0 +1,6 @@ +Picotool +======== + +Picotool is a tool for inspecting RP2040 binaries, and interacting with RP2040 devices when they are in BOOTSEL mode. + +Note for full documentation see https://rptl.io/pico-get-started Appendix B. diff --git a/Sming/Arch/Rp2040/Components/picotool/component.mk b/Sming/Arch/Rp2040/Components/picotool/component.mk new file mode 100644 index 0000000000..e339d2025c --- /dev/null +++ b/Sming/Arch/Rp2040/Components/picotool/component.mk @@ -0,0 +1,36 @@ +COMPONENT_SUBMODULES := picotool +PICOTOOL_SRC := $(COMPONENT_PATH)/picotool +LIBUSB_PATH := $(COMPONENT_PATH)/libusb +LIBUSB_DLL := libusb-1.0.dll +PICOTOOL := $(TOOLS_BASE)/picotool$(TOOL_EXT) +COMPONENT_LIBNAME := + +DEBUG_VARS += PICOTOOL + +CMAKE_OPTIONS := + +ifeq ($(UNAME),Windows) +PICOTOOL_CMAKE_OPTIONS += \ + -DLIBUSB_INCLUDE_DIR=$(LIBUSB_PATH) \ + -DLIBUSB_LIBRARIES=$(LIBUSB_PATH)/$(LIBUSB_DLL) \ + -G "MSYS Makefiles" + +COMPONENT_TARGETS += $(TOOLS_BASE)/$(LIBUSB_DLL) + +$(COMPONENT_RULE)$(TOOLS_BASE)/$(LIBUSB_DLL): $(LIBUSB_PATH)/$(LIBUSB_DLL) + cp $< $@ +endif + +COMPONENT_TARGETS += $(PICOTOOL) + +$(COMPONENT_RULE)$(PICOTOOL): + $(Q) mkdir -p $(@D) + $(Q) cd $(@D) && $(CMAKE) $(PICOTOOL_CMAKE_OPTIONS) $(PICOTOOL_SRC) && $(MAKE) + + +# Read flash manufacturer ID and determine actual size +define ReadFlashID + $(info ReadFlashID) + $(Q) $(PICOTOOL) info -a $(TARGET_BIN) + # $(PICOTOOL) help info + endef diff --git a/Sming/Arch/Rp2040/Components/picotool/libusb/libusb-1.0.dll b/Sming/Arch/Rp2040/Components/picotool/libusb/libusb-1.0.dll new file mode 100644 index 0000000000..fd7a9414f2 Binary files /dev/null and b/Sming/Arch/Rp2040/Components/picotool/libusb/libusb-1.0.dll differ diff --git a/Sming/Arch/Rp2040/Components/picotool/libusb/libusb.h b/Sming/Arch/Rp2040/Components/picotool/libusb/libusb.h new file mode 100644 index 0000000000..1308571cd6 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/picotool/libusb/libusb.h @@ -0,0 +1,2113 @@ +/* + * Public libusb header file + * Copyright © 2001 Johannes Erdfelt + * Copyright © 2007-2008 Daniel Drake + * Copyright © 2012 Pete Batard + * Copyright © 2012-2018 Nathan Hjelm + * Copyright © 2014-2020 Chris Dickens + * For more information, please visit: http://libusb.info + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef LIBUSB_H +#define LIBUSB_H + +#if defined(_MSC_VER) +/* on MS environments, the inline keyword is available in C++ only */ +#if !defined(__cplusplus) +#define inline __inline +#endif +/* ssize_t is also not available */ +#include +typedef SSIZE_T ssize_t; +#endif /* _MSC_VER */ + +#include +#include +#include +#if !defined(_MSC_VER) +#include +#endif +#include + +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +#define ZERO_SIZED_ARRAY /* [] - valid C99 code */ +#else +#define ZERO_SIZED_ARRAY 0 /* [0] - non-standard, but usually working code */ +#endif /* __STDC_VERSION__ */ + +/* 'interface' might be defined as a macro on Windows, so we need to + * undefine it so as not to break the current libusb API, because + * libusb_config_descriptor has an 'interface' member + * As this can be problematic if you include windows.h after libusb.h + * in your sources, we force windows.h to be included first. */ +#if defined(_WIN32) || defined(__CYGWIN__) +#include +#if defined(interface) +#undef interface +#endif +#if !defined(__CYGWIN__) +#include +#endif +#endif /* _WIN32 || __CYGWIN__ */ + +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) +#define LIBUSB_DEPRECATED_FOR(f) __attribute__ ((deprecated ("Use " #f " instead"))) +#elif defined(__GNUC__) && (__GNUC__ >= 3) +#define LIBUSB_DEPRECATED_FOR(f) __attribute__ ((deprecated)) +#else +#define LIBUSB_DEPRECATED_FOR(f) +#endif /* __GNUC__ */ + +#if defined(__GNUC__) +#define LIBUSB_PACKED __attribute__ ((packed)) +#else +#define LIBUSB_PACKED +#endif /* __GNUC__ */ + +/** \def LIBUSB_CALL + * \ingroup libusb_misc + * libusb's Windows calling convention. + * + * Under Windows, the selection of available compilers and configurations + * means that, unlike other platforms, there is not one true calling + * convention (calling convention: the manner in which parameters are + * passed to functions in the generated assembly code). + * + * Matching the Windows API itself, libusb uses the WINAPI convention (which + * translates to the stdcall convention) and guarantees that the + * library is compiled in this way. The public header file also includes + * appropriate annotations so that your own software will use the right + * convention, even if another convention is being used by default within + * your codebase. + * + * The one consideration that you must apply in your software is to mark + * all functions which you use as libusb callbacks with this LIBUSB_CALL + * annotation, so that they too get compiled for the correct calling + * convention. + * + * On non-Windows operating systems, this macro is defined as nothing. This + * means that you can apply it to your code without worrying about + * cross-platform compatibility. + */ +/* LIBUSB_CALL must be defined on both definition and declaration of libusb + * functions. You'd think that declaration would be enough, but cygwin will + * complain about conflicting types unless both are marked this way. + * The placement of this macro is important too; it must appear after the + * return type, before the function name. See internal documentation for + * API_EXPORTED. + */ +#if defined(_WIN32) || defined(__CYGWIN__) +#define LIBUSB_CALL WINAPI +#else +#define LIBUSB_CALL +#endif /* _WIN32 || __CYGWIN__ */ + +/** \def LIBUSB_API_VERSION + * \ingroup libusb_misc + * libusb's API version. + * + * Since version 1.0.13, to help with feature detection, libusb defines + * a LIBUSB_API_VERSION macro that gets increased every time there is a + * significant change to the API, such as the introduction of a new call, + * the definition of a new macro/enum member, or any other element that + * libusb applications may want to detect at compilation time. + * + * The macro is typically used in an application as follows: + * \code + * #if defined(LIBUSB_API_VERSION) && (LIBUSB_API_VERSION >= 0x01001234) + * // Use one of the newer features from the libusb API + * #endif + * \endcode + * + * Internally, LIBUSB_API_VERSION is defined as follows: + * (libusb major << 24) | (libusb minor << 16) | (16 bit incremental) + */ +#define LIBUSB_API_VERSION 0x01000108 + +/* The following is kept for compatibility, but will be deprecated in the future */ +#define LIBUSBX_API_VERSION LIBUSB_API_VERSION + +#if defined(__cplusplus) +extern "C" { +#endif + +/** + * \ingroup libusb_misc + * Convert a 16-bit value from host-endian to little-endian format. On + * little endian systems, this function does nothing. On big endian systems, + * the bytes are swapped. + * \param x the host-endian value to convert + * \returns the value in little-endian byte order + */ +static inline uint16_t libusb_cpu_to_le16(const uint16_t x) +{ + union { + uint8_t b8[2]; + uint16_t b16; + } _tmp; + _tmp.b8[1] = (uint8_t) (x >> 8); + _tmp.b8[0] = (uint8_t) (x & 0xff); + return _tmp.b16; +} + +/** \def libusb_le16_to_cpu + * \ingroup libusb_misc + * Convert a 16-bit value from little-endian to host-endian format. On + * little endian systems, this function does nothing. On big endian systems, + * the bytes are swapped. + * \param x the little-endian value to convert + * \returns the value in host-endian byte order + */ +#define libusb_le16_to_cpu libusb_cpu_to_le16 + +/* standard USB stuff */ + +/** \ingroup libusb_desc + * Device and/or Interface Class codes */ +enum libusb_class_code { + /** In the context of a \ref libusb_device_descriptor "device descriptor", + * this bDeviceClass value indicates that each interface specifies its + * own class information and all interfaces operate independently. + */ + LIBUSB_CLASS_PER_INTERFACE = 0x00, + + /** Audio class */ + LIBUSB_CLASS_AUDIO = 0x01, + + /** Communications class */ + LIBUSB_CLASS_COMM = 0x02, + + /** Human Interface Device class */ + LIBUSB_CLASS_HID = 0x03, + + /** Physical */ + LIBUSB_CLASS_PHYSICAL = 0x05, + + /** Image class */ + LIBUSB_CLASS_IMAGE = 0x06, + LIBUSB_CLASS_PTP = 0x06, /* legacy name from libusb-0.1 usb.h */ + + /** Printer class */ + LIBUSB_CLASS_PRINTER = 0x07, + + /** Mass storage class */ + LIBUSB_CLASS_MASS_STORAGE = 0x08, + + /** Hub class */ + LIBUSB_CLASS_HUB = 0x09, + + /** Data class */ + LIBUSB_CLASS_DATA = 0x0a, + + /** Smart Card */ + LIBUSB_CLASS_SMART_CARD = 0x0b, + + /** Content Security */ + LIBUSB_CLASS_CONTENT_SECURITY = 0x0d, + + /** Video */ + LIBUSB_CLASS_VIDEO = 0x0e, + + /** Personal Healthcare */ + LIBUSB_CLASS_PERSONAL_HEALTHCARE = 0x0f, + + /** Diagnostic Device */ + LIBUSB_CLASS_DIAGNOSTIC_DEVICE = 0xdc, + + /** Wireless class */ + LIBUSB_CLASS_WIRELESS = 0xe0, + + /** Miscellaneous class */ + LIBUSB_CLASS_MISCELLANEOUS = 0xef, + + /** Application class */ + LIBUSB_CLASS_APPLICATION = 0xfe, + + /** Class is vendor-specific */ + LIBUSB_CLASS_VENDOR_SPEC = 0xff +}; + +/** \ingroup libusb_desc + * Descriptor types as defined by the USB specification. */ +enum libusb_descriptor_type { + /** Device descriptor. See libusb_device_descriptor. */ + LIBUSB_DT_DEVICE = 0x01, + + /** Configuration descriptor. See libusb_config_descriptor. */ + LIBUSB_DT_CONFIG = 0x02, + + /** String descriptor */ + LIBUSB_DT_STRING = 0x03, + + /** Interface descriptor. See libusb_interface_descriptor. */ + LIBUSB_DT_INTERFACE = 0x04, + + /** Endpoint descriptor. See libusb_endpoint_descriptor. */ + LIBUSB_DT_ENDPOINT = 0x05, + + /** BOS descriptor */ + LIBUSB_DT_BOS = 0x0f, + + /** Device Capability descriptor */ + LIBUSB_DT_DEVICE_CAPABILITY = 0x10, + + /** HID descriptor */ + LIBUSB_DT_HID = 0x21, + + /** HID report descriptor */ + LIBUSB_DT_REPORT = 0x22, + + /** Physical descriptor */ + LIBUSB_DT_PHYSICAL = 0x23, + + /** Hub descriptor */ + LIBUSB_DT_HUB = 0x29, + + /** SuperSpeed Hub descriptor */ + LIBUSB_DT_SUPERSPEED_HUB = 0x2a, + + /** SuperSpeed Endpoint Companion descriptor */ + LIBUSB_DT_SS_ENDPOINT_COMPANION = 0x30 +}; + +/* Descriptor sizes per descriptor type */ +#define LIBUSB_DT_DEVICE_SIZE 18 +#define LIBUSB_DT_CONFIG_SIZE 9 +#define LIBUSB_DT_INTERFACE_SIZE 9 +#define LIBUSB_DT_ENDPOINT_SIZE 7 +#define LIBUSB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */ +#define LIBUSB_DT_HUB_NONVAR_SIZE 7 +#define LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE 6 +#define LIBUSB_DT_BOS_SIZE 5 +#define LIBUSB_DT_DEVICE_CAPABILITY_SIZE 3 + +/* BOS descriptor sizes */ +#define LIBUSB_BT_USB_2_0_EXTENSION_SIZE 7 +#define LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE 10 +#define LIBUSB_BT_CONTAINER_ID_SIZE 20 + +/* We unwrap the BOS => define its max size */ +#define LIBUSB_DT_BOS_MAX_SIZE \ + (LIBUSB_DT_BOS_SIZE + \ + LIBUSB_BT_USB_2_0_EXTENSION_SIZE + \ + LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE + \ + LIBUSB_BT_CONTAINER_ID_SIZE) + +#define LIBUSB_ENDPOINT_ADDRESS_MASK 0x0f /* in bEndpointAddress */ +#define LIBUSB_ENDPOINT_DIR_MASK 0x80 + +/** \ingroup libusb_desc + * Endpoint direction. Values for bit 7 of the + * \ref libusb_endpoint_descriptor::bEndpointAddress "endpoint address" scheme. + */ +enum libusb_endpoint_direction { + /** Out: host-to-device */ + LIBUSB_ENDPOINT_OUT = 0x00, + + /** In: device-to-host */ + LIBUSB_ENDPOINT_IN = 0x80 +}; + +#define LIBUSB_TRANSFER_TYPE_MASK 0x03 /* in bmAttributes */ + +/** \ingroup libusb_desc + * Endpoint transfer type. Values for bits 0:1 of the + * \ref libusb_endpoint_descriptor::bmAttributes "endpoint attributes" field. + */ +enum libusb_endpoint_transfer_type { + /** Control endpoint */ + LIBUSB_ENDPOINT_TRANSFER_TYPE_CONTROL = 0x0, + + /** Isochronous endpoint */ + LIBUSB_ENDPOINT_TRANSFER_TYPE_ISOCHRONOUS = 0x1, + + /** Bulk endpoint */ + LIBUSB_ENDPOINT_TRANSFER_TYPE_BULK = 0x2, + + /** Interrupt endpoint */ + LIBUSB_ENDPOINT_TRANSFER_TYPE_INTERRUPT = 0x3 +}; + +/** \ingroup libusb_misc + * Standard requests, as defined in table 9-5 of the USB 3.0 specifications */ +enum libusb_standard_request { + /** Request status of the specific recipient */ + LIBUSB_REQUEST_GET_STATUS = 0x00, + + /** Clear or disable a specific feature */ + LIBUSB_REQUEST_CLEAR_FEATURE = 0x01, + + /* 0x02 is reserved */ + + /** Set or enable a specific feature */ + LIBUSB_REQUEST_SET_FEATURE = 0x03, + + /* 0x04 is reserved */ + + /** Set device address for all future accesses */ + LIBUSB_REQUEST_SET_ADDRESS = 0x05, + + /** Get the specified descriptor */ + LIBUSB_REQUEST_GET_DESCRIPTOR = 0x06, + + /** Used to update existing descriptors or add new descriptors */ + LIBUSB_REQUEST_SET_DESCRIPTOR = 0x07, + + /** Get the current device configuration value */ + LIBUSB_REQUEST_GET_CONFIGURATION = 0x08, + + /** Set device configuration */ + LIBUSB_REQUEST_SET_CONFIGURATION = 0x09, + + /** Return the selected alternate setting for the specified interface */ + LIBUSB_REQUEST_GET_INTERFACE = 0x0a, + + /** Select an alternate interface for the specified interface */ + LIBUSB_REQUEST_SET_INTERFACE = 0x0b, + + /** Set then report an endpoint's synchronization frame */ + LIBUSB_REQUEST_SYNCH_FRAME = 0x0c, + + /** Sets both the U1 and U2 Exit Latency */ + LIBUSB_REQUEST_SET_SEL = 0x30, + + /** Delay from the time a host transmits a packet to the time it is + * received by the device. */ + LIBUSB_SET_ISOCH_DELAY = 0x31 +}; + +/** \ingroup libusb_misc + * Request type bits of the + * \ref libusb_control_setup::bmRequestType "bmRequestType" field in control + * transfers. */ +enum libusb_request_type { + /** Standard */ + LIBUSB_REQUEST_TYPE_STANDARD = (0x00 << 5), + + /** Class */ + LIBUSB_REQUEST_TYPE_CLASS = (0x01 << 5), + + /** Vendor */ + LIBUSB_REQUEST_TYPE_VENDOR = (0x02 << 5), + + /** Reserved */ + LIBUSB_REQUEST_TYPE_RESERVED = (0x03 << 5) +}; + +/** \ingroup libusb_misc + * Recipient bits of the + * \ref libusb_control_setup::bmRequestType "bmRequestType" field in control + * transfers. Values 4 through 31 are reserved. */ +enum libusb_request_recipient { + /** Device */ + LIBUSB_RECIPIENT_DEVICE = 0x00, + + /** Interface */ + LIBUSB_RECIPIENT_INTERFACE = 0x01, + + /** Endpoint */ + LIBUSB_RECIPIENT_ENDPOINT = 0x02, + + /** Other */ + LIBUSB_RECIPIENT_OTHER = 0x03 +}; + +#define LIBUSB_ISO_SYNC_TYPE_MASK 0x0c + +/** \ingroup libusb_desc + * Synchronization type for isochronous endpoints. Values for bits 2:3 of the + * \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in + * libusb_endpoint_descriptor. + */ +enum libusb_iso_sync_type { + /** No synchronization */ + LIBUSB_ISO_SYNC_TYPE_NONE = 0x0, + + /** Asynchronous */ + LIBUSB_ISO_SYNC_TYPE_ASYNC = 0x1, + + /** Adaptive */ + LIBUSB_ISO_SYNC_TYPE_ADAPTIVE = 0x2, + + /** Synchronous */ + LIBUSB_ISO_SYNC_TYPE_SYNC = 0x3 +}; + +#define LIBUSB_ISO_USAGE_TYPE_MASK 0x30 + +/** \ingroup libusb_desc + * Usage type for isochronous endpoints. Values for bits 4:5 of the + * \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in + * libusb_endpoint_descriptor. + */ +enum libusb_iso_usage_type { + /** Data endpoint */ + LIBUSB_ISO_USAGE_TYPE_DATA = 0x0, + + /** Feedback endpoint */ + LIBUSB_ISO_USAGE_TYPE_FEEDBACK = 0x1, + + /** Implicit feedback Data endpoint */ + LIBUSB_ISO_USAGE_TYPE_IMPLICIT = 0x2 +}; + +/** \ingroup libusb_desc + * Supported speeds (wSpeedSupported) bitfield. Indicates what + * speeds the device supports. + */ +enum libusb_supported_speed { + /** Low speed operation supported (1.5MBit/s). */ + LIBUSB_LOW_SPEED_OPERATION = (1 << 0), + + /** Full speed operation supported (12MBit/s). */ + LIBUSB_FULL_SPEED_OPERATION = (1 << 1), + + /** High speed operation supported (480MBit/s). */ + LIBUSB_HIGH_SPEED_OPERATION = (1 << 2), + + /** Superspeed operation supported (5000MBit/s). */ + LIBUSB_SUPER_SPEED_OPERATION = (1 << 3) +}; + +/** \ingroup libusb_desc + * Masks for the bits of the + * \ref libusb_usb_2_0_extension_descriptor::bmAttributes "bmAttributes" field + * of the USB 2.0 Extension descriptor. + */ +enum libusb_usb_2_0_extension_attributes { + /** Supports Link Power Management (LPM) */ + LIBUSB_BM_LPM_SUPPORT = (1 << 1) +}; + +/** \ingroup libusb_desc + * Masks for the bits of the + * \ref libusb_ss_usb_device_capability_descriptor::bmAttributes "bmAttributes" field + * field of the SuperSpeed USB Device Capability descriptor. + */ +enum libusb_ss_usb_device_capability_attributes { + /** Supports Latency Tolerance Messages (LTM) */ + LIBUSB_BM_LTM_SUPPORT = (1 << 1) +}; + +/** \ingroup libusb_desc + * USB capability types + */ +enum libusb_bos_type { + /** Wireless USB device capability */ + LIBUSB_BT_WIRELESS_USB_DEVICE_CAPABILITY = 0x01, + + /** USB 2.0 extensions */ + LIBUSB_BT_USB_2_0_EXTENSION = 0x02, + + /** SuperSpeed USB device capability */ + LIBUSB_BT_SS_USB_DEVICE_CAPABILITY = 0x03, + + /** Container ID type */ + LIBUSB_BT_CONTAINER_ID = 0x04 +}; + +/** \ingroup libusb_desc + * A structure representing the standard USB device descriptor. This + * descriptor is documented in section 9.6.1 of the USB 3.0 specification. + * All multiple-byte fields are represented in host-endian format. + */ +struct libusb_device_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE LIBUSB_DT_DEVICE in this + * context. */ + uint8_t bDescriptorType; + + /** USB specification release number in binary-coded decimal. A value of + * 0x0200 indicates USB 2.0, 0x0110 indicates USB 1.1, etc. */ + uint16_t bcdUSB; + + /** USB-IF class code for the device. See \ref libusb_class_code. */ + uint8_t bDeviceClass; + + /** USB-IF subclass code for the device, qualified by the bDeviceClass + * value */ + uint8_t bDeviceSubClass; + + /** USB-IF protocol code for the device, qualified by the bDeviceClass and + * bDeviceSubClass values */ + uint8_t bDeviceProtocol; + + /** Maximum packet size for endpoint 0 */ + uint8_t bMaxPacketSize0; + + /** USB-IF vendor ID */ + uint16_t idVendor; + + /** USB-IF product ID */ + uint16_t idProduct; + + /** Device release number in binary-coded decimal */ + uint16_t bcdDevice; + + /** Index of string descriptor describing manufacturer */ + uint8_t iManufacturer; + + /** Index of string descriptor describing product */ + uint8_t iProduct; + + /** Index of string descriptor containing device serial number */ + uint8_t iSerialNumber; + + /** Number of possible configurations */ + uint8_t bNumConfigurations; +}; + +/** \ingroup libusb_desc + * A structure representing the standard USB endpoint descriptor. This + * descriptor is documented in section 9.6.6 of the USB 3.0 specification. + * All multiple-byte fields are represented in host-endian format. + */ +struct libusb_endpoint_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_ENDPOINT LIBUSB_DT_ENDPOINT in + * this context. */ + uint8_t bDescriptorType; + + /** The address of the endpoint described by this descriptor. Bits 0:3 are + * the endpoint number. Bits 4:6 are reserved. Bit 7 indicates direction, + * see \ref libusb_endpoint_direction. */ + uint8_t bEndpointAddress; + + /** Attributes which apply to the endpoint when it is configured using + * the bConfigurationValue. Bits 0:1 determine the transfer type and + * correspond to \ref libusb_endpoint_transfer_type. Bits 2:3 are only used + * for isochronous endpoints and correspond to \ref libusb_iso_sync_type. + * Bits 4:5 are also only used for isochronous endpoints and correspond to + * \ref libusb_iso_usage_type. Bits 6:7 are reserved. */ + uint8_t bmAttributes; + + /** Maximum packet size this endpoint is capable of sending/receiving. */ + uint16_t wMaxPacketSize; + + /** Interval for polling endpoint for data transfers. */ + uint8_t bInterval; + + /** For audio devices only: the rate at which synchronization feedback + * is provided. */ + uint8_t bRefresh; + + /** For audio devices only: the address if the synch endpoint */ + uint8_t bSynchAddress; + + /** Extra descriptors. If libusb encounters unknown endpoint descriptors, + * it will store them here, should you wish to parse them. */ + const unsigned char *extra; + + /** Length of the extra descriptors, in bytes. Must be non-negative. */ + int extra_length; +}; + +/** \ingroup libusb_desc + * A structure representing the standard USB interface descriptor. This + * descriptor is documented in section 9.6.5 of the USB 3.0 specification. + * All multiple-byte fields are represented in host-endian format. + */ +struct libusb_interface_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_INTERFACE LIBUSB_DT_INTERFACE + * in this context. */ + uint8_t bDescriptorType; + + /** Number of this interface */ + uint8_t bInterfaceNumber; + + /** Value used to select this alternate setting for this interface */ + uint8_t bAlternateSetting; + + /** Number of endpoints used by this interface (excluding the control + * endpoint). */ + uint8_t bNumEndpoints; + + /** USB-IF class code for this interface. See \ref libusb_class_code. */ + uint8_t bInterfaceClass; + + /** USB-IF subclass code for this interface, qualified by the + * bInterfaceClass value */ + uint8_t bInterfaceSubClass; + + /** USB-IF protocol code for this interface, qualified by the + * bInterfaceClass and bInterfaceSubClass values */ + uint8_t bInterfaceProtocol; + + /** Index of string descriptor describing this interface */ + uint8_t iInterface; + + /** Array of endpoint descriptors. This length of this array is determined + * by the bNumEndpoints field. */ + const struct libusb_endpoint_descriptor *endpoint; + + /** Extra descriptors. If libusb encounters unknown interface descriptors, + * it will store them here, should you wish to parse them. */ + const unsigned char *extra; + + /** Length of the extra descriptors, in bytes. Must be non-negative. */ + int extra_length; +}; + +/** \ingroup libusb_desc + * A collection of alternate settings for a particular USB interface. + */ +struct libusb_interface { + /** Array of interface descriptors. The length of this array is determined + * by the num_altsetting field. */ + const struct libusb_interface_descriptor *altsetting; + + /** The number of alternate settings that belong to this interface. + * Must be non-negative. */ + int num_altsetting; +}; + +/** \ingroup libusb_desc + * A structure representing the standard USB configuration descriptor. This + * descriptor is documented in section 9.6.3 of the USB 3.0 specification. + * All multiple-byte fields are represented in host-endian format. + */ +struct libusb_config_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_CONFIG LIBUSB_DT_CONFIG + * in this context. */ + uint8_t bDescriptorType; + + /** Total length of data returned for this configuration */ + uint16_t wTotalLength; + + /** Number of interfaces supported by this configuration */ + uint8_t bNumInterfaces; + + /** Identifier value for this configuration */ + uint8_t bConfigurationValue; + + /** Index of string descriptor describing this configuration */ + uint8_t iConfiguration; + + /** Configuration characteristics */ + uint8_t bmAttributes; + + /** Maximum power consumption of the USB device from this bus in this + * configuration when the device is fully operation. Expressed in units + * of 2 mA when the device is operating in high-speed mode and in units + * of 8 mA when the device is operating in super-speed mode. */ + uint8_t MaxPower; + + /** Array of interfaces supported by this configuration. The length of + * this array is determined by the bNumInterfaces field. */ + const struct libusb_interface *interface; + + /** Extra descriptors. If libusb encounters unknown configuration + * descriptors, it will store them here, should you wish to parse them. */ + const unsigned char *extra; + + /** Length of the extra descriptors, in bytes. Must be non-negative. */ + int extra_length; +}; + +/** \ingroup libusb_desc + * A structure representing the superspeed endpoint companion + * descriptor. This descriptor is documented in section 9.6.7 of + * the USB 3.0 specification. All multiple-byte fields are represented in + * host-endian format. + */ +struct libusb_ss_endpoint_companion_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_SS_ENDPOINT_COMPANION in + * this context. */ + uint8_t bDescriptorType; + + /** The maximum number of packets the endpoint can send or + * receive as part of a burst. */ + uint8_t bMaxBurst; + + /** In bulk EP: bits 4:0 represents the maximum number of + * streams the EP supports. In isochronous EP: bits 1:0 + * represents the Mult - a zero based value that determines + * the maximum number of packets within a service interval */ + uint8_t bmAttributes; + + /** The total number of bytes this EP will transfer every + * service interval. Valid only for periodic EPs. */ + uint16_t wBytesPerInterval; +}; + +/** \ingroup libusb_desc + * A generic representation of a BOS Device Capability descriptor. It is + * advised to check bDevCapabilityType and call the matching + * libusb_get_*_descriptor function to get a structure fully matching the type. + */ +struct libusb_bos_dev_capability_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY + * LIBUSB_DT_DEVICE_CAPABILITY in this context. */ + uint8_t bDescriptorType; + + /** Device Capability type */ + uint8_t bDevCapabilityType; + + /** Device Capability data (bLength - 3 bytes) */ + uint8_t dev_capability_data[ZERO_SIZED_ARRAY]; +}; + +/** \ingroup libusb_desc + * A structure representing the Binary Device Object Store (BOS) descriptor. + * This descriptor is documented in section 9.6.2 of the USB 3.0 specification. + * All multiple-byte fields are represented in host-endian format. + */ +struct libusb_bos_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_BOS LIBUSB_DT_BOS + * in this context. */ + uint8_t bDescriptorType; + + /** Length of this descriptor and all of its sub descriptors */ + uint16_t wTotalLength; + + /** The number of separate device capability descriptors in + * the BOS */ + uint8_t bNumDeviceCaps; + + /** bNumDeviceCap Device Capability Descriptors */ + struct libusb_bos_dev_capability_descriptor *dev_capability[ZERO_SIZED_ARRAY]; +}; + +/** \ingroup libusb_desc + * A structure representing the USB 2.0 Extension descriptor + * This descriptor is documented in section 9.6.2.1 of the USB 3.0 specification. + * All multiple-byte fields are represented in host-endian format. + */ +struct libusb_usb_2_0_extension_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY + * LIBUSB_DT_DEVICE_CAPABILITY in this context. */ + uint8_t bDescriptorType; + + /** Capability type. Will have value + * \ref libusb_capability_type::LIBUSB_BT_USB_2_0_EXTENSION + * LIBUSB_BT_USB_2_0_EXTENSION in this context. */ + uint8_t bDevCapabilityType; + + /** Bitmap encoding of supported device level features. + * A value of one in a bit location indicates a feature is + * supported; a value of zero indicates it is not supported. + * See \ref libusb_usb_2_0_extension_attributes. */ + uint32_t bmAttributes; +}; + +/** \ingroup libusb_desc + * A structure representing the SuperSpeed USB Device Capability descriptor + * This descriptor is documented in section 9.6.2.2 of the USB 3.0 specification. + * All multiple-byte fields are represented in host-endian format. + */ +struct libusb_ss_usb_device_capability_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY + * LIBUSB_DT_DEVICE_CAPABILITY in this context. */ + uint8_t bDescriptorType; + + /** Capability type. Will have value + * \ref libusb_capability_type::LIBUSB_BT_SS_USB_DEVICE_CAPABILITY + * LIBUSB_BT_SS_USB_DEVICE_CAPABILITY in this context. */ + uint8_t bDevCapabilityType; + + /** Bitmap encoding of supported device level features. + * A value of one in a bit location indicates a feature is + * supported; a value of zero indicates it is not supported. + * See \ref libusb_ss_usb_device_capability_attributes. */ + uint8_t bmAttributes; + + /** Bitmap encoding of the speed supported by this device when + * operating in SuperSpeed mode. See \ref libusb_supported_speed. */ + uint16_t wSpeedSupported; + + /** The lowest speed at which all the functionality supported + * by the device is available to the user. For example if the + * device supports all its functionality when connected at + * full speed and above then it sets this value to 1. */ + uint8_t bFunctionalitySupport; + + /** U1 Device Exit Latency. */ + uint8_t bU1DevExitLat; + + /** U2 Device Exit Latency. */ + uint16_t bU2DevExitLat; +}; + +/** \ingroup libusb_desc + * A structure representing the Container ID descriptor. + * This descriptor is documented in section 9.6.2.3 of the USB 3.0 specification. + * All multiple-byte fields, except UUIDs, are represented in host-endian format. + */ +struct libusb_container_id_descriptor { + /** Size of this descriptor (in bytes) */ + uint8_t bLength; + + /** Descriptor type. Will have value + * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY + * LIBUSB_DT_DEVICE_CAPABILITY in this context. */ + uint8_t bDescriptorType; + + /** Capability type. Will have value + * \ref libusb_capability_type::LIBUSB_BT_CONTAINER_ID + * LIBUSB_BT_CONTAINER_ID in this context. */ + uint8_t bDevCapabilityType; + + /** Reserved field */ + uint8_t bReserved; + + /** 128 bit UUID */ + uint8_t ContainerID[16]; +}; + +/** \ingroup libusb_asyncio + * Setup packet for control transfers. */ +#if defined(_MSC_VER) +#pragma pack(push, 1) +#endif +struct libusb_control_setup { + /** Request type. Bits 0:4 determine recipient, see + * \ref libusb_request_recipient. Bits 5:6 determine type, see + * \ref libusb_request_type. Bit 7 determines data transfer direction, see + * \ref libusb_endpoint_direction. + */ + uint8_t bmRequestType; + + /** Request. If the type bits of bmRequestType are equal to + * \ref libusb_request_type::LIBUSB_REQUEST_TYPE_STANDARD + * "LIBUSB_REQUEST_TYPE_STANDARD" then this field refers to + * \ref libusb_standard_request. For other cases, use of this field is + * application-specific. */ + uint8_t bRequest; + + /** Value. Varies according to request */ + uint16_t wValue; + + /** Index. Varies according to request, typically used to pass an index + * or offset */ + uint16_t wIndex; + + /** Number of bytes to transfer */ + uint16_t wLength; +} LIBUSB_PACKED; +#if defined(_MSC_VER) +#pragma pack(pop) +#endif + +#define LIBUSB_CONTROL_SETUP_SIZE (sizeof(struct libusb_control_setup)) + +/* libusb */ + +struct libusb_context; +struct libusb_device; +struct libusb_device_handle; + +/** \ingroup libusb_lib + * Structure providing the version of the libusb runtime + */ +struct libusb_version { + /** Library major version. */ + const uint16_t major; + + /** Library minor version. */ + const uint16_t minor; + + /** Library micro version. */ + const uint16_t micro; + + /** Library nano version. */ + const uint16_t nano; + + /** Library release candidate suffix string, e.g. "-rc4". */ + const char *rc; + + /** For ABI compatibility only. */ + const char *describe; +}; + +/** \ingroup libusb_lib + * Structure representing a libusb session. The concept of individual libusb + * sessions allows for your program to use two libraries (or dynamically + * load two modules) which both independently use libusb. This will prevent + * interference between the individual libusb users - for example + * libusb_set_option() will not affect the other user of the library, and + * libusb_exit() will not destroy resources that the other user is still + * using. + * + * Sessions are created by libusb_init() and destroyed through libusb_exit(). + * If your application is guaranteed to only ever include a single libusb + * user (i.e. you), you do not have to worry about contexts: pass NULL in + * every function call where a context is required. The default context + * will be used. + * + * For more information, see \ref libusb_contexts. + */ +typedef struct libusb_context libusb_context; + +/** \ingroup libusb_dev + * Structure representing a USB device detected on the system. This is an + * opaque type for which you are only ever provided with a pointer, usually + * originating from libusb_get_device_list(). + * + * Certain operations can be performed on a device, but in order to do any + * I/O you will have to first obtain a device handle using libusb_open(). + * + * Devices are reference counted with libusb_ref_device() and + * libusb_unref_device(), and are freed when the reference count reaches 0. + * New devices presented by libusb_get_device_list() have a reference count of + * 1, and libusb_free_device_list() can optionally decrease the reference count + * on all devices in the list. libusb_open() adds another reference which is + * later destroyed by libusb_close(). + */ +typedef struct libusb_device libusb_device; + + +/** \ingroup libusb_dev + * Structure representing a handle on a USB device. This is an opaque type for + * which you are only ever provided with a pointer, usually originating from + * libusb_open(). + * + * A device handle is used to perform I/O and other operations. When finished + * with a device handle, you should call libusb_close(). + */ +typedef struct libusb_device_handle libusb_device_handle; + +/** \ingroup libusb_dev + * Speed codes. Indicates the speed at which the device is operating. + */ +enum libusb_speed { + /** The OS doesn't report or know the device speed. */ + LIBUSB_SPEED_UNKNOWN = 0, + + /** The device is operating at low speed (1.5MBit/s). */ + LIBUSB_SPEED_LOW = 1, + + /** The device is operating at full speed (12MBit/s). */ + LIBUSB_SPEED_FULL = 2, + + /** The device is operating at high speed (480MBit/s). */ + LIBUSB_SPEED_HIGH = 3, + + /** The device is operating at super speed (5000MBit/s). */ + LIBUSB_SPEED_SUPER = 4, + + /** The device is operating at super speed plus (10000MBit/s). */ + LIBUSB_SPEED_SUPER_PLUS = 5 +}; + +/** \ingroup libusb_misc + * Error codes. Most libusb functions return 0 on success or one of these + * codes on failure. + * You can call libusb_error_name() to retrieve a string representation of an + * error code or libusb_strerror() to get an end-user suitable description of + * an error code. + */ +enum libusb_error { + /** Success (no error) */ + LIBUSB_SUCCESS = 0, + + /** Input/output error */ + LIBUSB_ERROR_IO = -1, + + /** Invalid parameter */ + LIBUSB_ERROR_INVALID_PARAM = -2, + + /** Access denied (insufficient permissions) */ + LIBUSB_ERROR_ACCESS = -3, + + /** No such device (it may have been disconnected) */ + LIBUSB_ERROR_NO_DEVICE = -4, + + /** Entity not found */ + LIBUSB_ERROR_NOT_FOUND = -5, + + /** Resource busy */ + LIBUSB_ERROR_BUSY = -6, + + /** Operation timed out */ + LIBUSB_ERROR_TIMEOUT = -7, + + /** Overflow */ + LIBUSB_ERROR_OVERFLOW = -8, + + /** Pipe error */ + LIBUSB_ERROR_PIPE = -9, + + /** System call interrupted (perhaps due to signal) */ + LIBUSB_ERROR_INTERRUPTED = -10, + + /** Insufficient memory */ + LIBUSB_ERROR_NO_MEM = -11, + + /** Operation not supported or unimplemented on this platform */ + LIBUSB_ERROR_NOT_SUPPORTED = -12, + + /* NB: Remember to update LIBUSB_ERROR_COUNT below as well as the + message strings in strerror.c when adding new error codes here. */ + + /** Other error */ + LIBUSB_ERROR_OTHER = -99 +}; + +/* Total number of error codes in enum libusb_error */ +#define LIBUSB_ERROR_COUNT 14 + +/** \ingroup libusb_asyncio + * Transfer type */ +enum libusb_transfer_type { + /** Control transfer */ + LIBUSB_TRANSFER_TYPE_CONTROL = 0U, + + /** Isochronous transfer */ + LIBUSB_TRANSFER_TYPE_ISOCHRONOUS = 1U, + + /** Bulk transfer */ + LIBUSB_TRANSFER_TYPE_BULK = 2U, + + /** Interrupt transfer */ + LIBUSB_TRANSFER_TYPE_INTERRUPT = 3U, + + /** Bulk stream transfer */ + LIBUSB_TRANSFER_TYPE_BULK_STREAM = 4U +}; + +/** \ingroup libusb_asyncio + * Transfer status codes */ +enum libusb_transfer_status { + /** Transfer completed without error. Note that this does not indicate + * that the entire amount of requested data was transferred. */ + LIBUSB_TRANSFER_COMPLETED, + + /** Transfer failed */ + LIBUSB_TRANSFER_ERROR, + + /** Transfer timed out */ + LIBUSB_TRANSFER_TIMED_OUT, + + /** Transfer was cancelled */ + LIBUSB_TRANSFER_CANCELLED, + + /** For bulk/interrupt endpoints: halt condition detected (endpoint + * stalled). For control endpoints: control request not supported. */ + LIBUSB_TRANSFER_STALL, + + /** Device was disconnected */ + LIBUSB_TRANSFER_NO_DEVICE, + + /** Device sent more data than requested */ + LIBUSB_TRANSFER_OVERFLOW + + /* NB! Remember to update libusb_error_name() + when adding new status codes here. */ +}; + +/** \ingroup libusb_asyncio + * libusb_transfer.flags values */ +enum libusb_transfer_flags { + /** Report short frames as errors */ + LIBUSB_TRANSFER_SHORT_NOT_OK = (1U << 0), + + /** Automatically free() transfer buffer during libusb_free_transfer(). + * Note that buffers allocated with libusb_dev_mem_alloc() should not + * be attempted freed in this way, since free() is not an appropriate + * way to release such memory. */ + LIBUSB_TRANSFER_FREE_BUFFER = (1U << 1), + + /** Automatically call libusb_free_transfer() after callback returns. + * If this flag is set, it is illegal to call libusb_free_transfer() + * from your transfer callback, as this will result in a double-free + * when this flag is acted upon. */ + LIBUSB_TRANSFER_FREE_TRANSFER = (1U << 2), + + /** Terminate transfers that are a multiple of the endpoint's + * wMaxPacketSize with an extra zero length packet. This is useful + * when a device protocol mandates that each logical request is + * terminated by an incomplete packet (i.e. the logical requests are + * not separated by other means). + * + * This flag only affects host-to-device transfers to bulk and interrupt + * endpoints. In other situations, it is ignored. + * + * This flag only affects transfers with a length that is a multiple of + * the endpoint's wMaxPacketSize. On transfers of other lengths, this + * flag has no effect. Therefore, if you are working with a device that + * needs a ZLP whenever the end of the logical request falls on a packet + * boundary, then it is sensible to set this flag on every + * transfer (you do not have to worry about only setting it on transfers + * that end on the boundary). + * + * This flag is currently only supported on Linux. + * On other systems, libusb_submit_transfer() will return + * LIBUSB_ERROR_NOT_SUPPORTED for every transfer where this flag is set. + * + * Available since libusb-1.0.9. + */ + LIBUSB_TRANSFER_ADD_ZERO_PACKET = (1U << 3) +}; + +/** \ingroup libusb_asyncio + * Isochronous packet descriptor. */ +struct libusb_iso_packet_descriptor { + /** Length of data to request in this packet */ + unsigned int length; + + /** Amount of data that was actually transferred */ + unsigned int actual_length; + + /** Status code for this packet */ + enum libusb_transfer_status status; +}; + +struct libusb_transfer; + +/** \ingroup libusb_asyncio + * Asynchronous transfer callback function type. When submitting asynchronous + * transfers, you pass a pointer to a callback function of this type via the + * \ref libusb_transfer::callback "callback" member of the libusb_transfer + * structure. libusb will call this function later, when the transfer has + * completed or failed. See \ref libusb_asyncio for more information. + * \param transfer The libusb_transfer struct the callback function is being + * notified about. + */ +typedef void (LIBUSB_CALL *libusb_transfer_cb_fn)(struct libusb_transfer *transfer); + +/** \ingroup libusb_asyncio + * The generic USB transfer structure. The user populates this structure and + * then submits it in order to request a transfer. After the transfer has + * completed, the library populates the transfer with the results and passes + * it back to the user. + */ +struct libusb_transfer { + /** Handle of the device that this transfer will be submitted to */ + libusb_device_handle *dev_handle; + + /** A bitwise OR combination of \ref libusb_transfer_flags. */ + uint8_t flags; + + /** Address of the endpoint where this transfer will be sent. */ + unsigned char endpoint; + + /** Type of the transfer from \ref libusb_transfer_type */ + unsigned char type; + + /** Timeout for this transfer in milliseconds. A value of 0 indicates no + * timeout. */ + unsigned int timeout; + + /** The status of the transfer. Read-only, and only for use within + * transfer callback function. + * + * If this is an isochronous transfer, this field may read COMPLETED even + * if there were errors in the frames. Use the + * \ref libusb_iso_packet_descriptor::status "status" field in each packet + * to determine if errors occurred. */ + enum libusb_transfer_status status; + + /** Length of the data buffer. Must be non-negative. */ + int length; + + /** Actual length of data that was transferred. Read-only, and only for + * use within transfer callback function. Not valid for isochronous + * endpoint transfers. */ + int actual_length; + + /** Callback function. This will be invoked when the transfer completes, + * fails, or is cancelled. */ + libusb_transfer_cb_fn callback; + + /** User context data. Useful for associating specific data to a transfer + * that can be accessed from within the callback function. + * + * This field may be set manually or is taken as the `user_data` parameter + * of the following functions: + * - libusb_fill_bulk_transfer() + * - libusb_fill_bulk_stream_transfer() + * - libusb_fill_control_transfer() + * - libusb_fill_interrupt_transfer() + * - libusb_fill_iso_transfer() */ + void *user_data; + + /** Data buffer */ + unsigned char *buffer; + + /** Number of isochronous packets. Only used for I/O with isochronous + * endpoints. Must be non-negative. */ + int num_iso_packets; + + /** Isochronous packet descriptors, for isochronous transfers only. */ + struct libusb_iso_packet_descriptor iso_packet_desc[ZERO_SIZED_ARRAY]; +}; + +/** \ingroup libusb_misc + * Capabilities supported by an instance of libusb on the current running + * platform. Test if the loaded library supports a given capability by calling + * \ref libusb_has_capability(). + */ +enum libusb_capability { + /** The libusb_has_capability() API is available. */ + LIBUSB_CAP_HAS_CAPABILITY = 0x0000U, + + /** Hotplug support is available on this platform. */ + LIBUSB_CAP_HAS_HOTPLUG = 0x0001U, + + /** The library can access HID devices without requiring user intervention. + * Note that before being able to actually access an HID device, you may + * still have to call additional libusb functions such as + * \ref libusb_detach_kernel_driver(). */ + LIBUSB_CAP_HAS_HID_ACCESS = 0x0100U, + + /** The library supports detaching of the default USB driver, using + * \ref libusb_detach_kernel_driver(), if one is set by the OS kernel */ + LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER = 0x0101U +}; + +/** \ingroup libusb_lib + * Log message levels. + */ +enum libusb_log_level { + /** (0) : No messages ever emitted by the library (default) */ + LIBUSB_LOG_LEVEL_NONE = 0, + + /** (1) : Error messages are emitted */ + LIBUSB_LOG_LEVEL_ERROR = 1, + + /** (2) : Warning and error messages are emitted */ + LIBUSB_LOG_LEVEL_WARNING = 2, + + /** (3) : Informational, warning and error messages are emitted */ + LIBUSB_LOG_LEVEL_INFO = 3, + + /** (4) : All messages are emitted */ + LIBUSB_LOG_LEVEL_DEBUG = 4 +}; + +/** \ingroup libusb_lib + * Log callback mode. + * \see libusb_set_log_cb() + */ +enum libusb_log_cb_mode { + /** Callback function handling all log messages. */ + LIBUSB_LOG_CB_GLOBAL = (1 << 0), + + /** Callback function handling context related log messages. */ + LIBUSB_LOG_CB_CONTEXT = (1 << 1) +}; + +/** \ingroup libusb_lib + * Callback function for handling log messages. + * \param ctx the context which is related to the log message, or NULL if it + * is a global log message + * \param level the log level, see \ref libusb_log_level for a description + * \param str the log message + * \see libusb_set_log_cb() + */ +typedef void (LIBUSB_CALL *libusb_log_cb)(libusb_context *ctx, + enum libusb_log_level level, const char *str); + +int LIBUSB_CALL libusb_init(libusb_context **ctx); +void LIBUSB_CALL libusb_exit(libusb_context *ctx); +LIBUSB_DEPRECATED_FOR(libusb_set_option) +void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level); +void LIBUSB_CALL libusb_set_log_cb(libusb_context *ctx, libusb_log_cb cb, int mode); +const struct libusb_version * LIBUSB_CALL libusb_get_version(void); +int LIBUSB_CALL libusb_has_capability(uint32_t capability); +const char * LIBUSB_CALL libusb_error_name(int errcode); +int LIBUSB_CALL libusb_setlocale(const char *locale); +const char * LIBUSB_CALL libusb_strerror(int errcode); + +ssize_t LIBUSB_CALL libusb_get_device_list(libusb_context *ctx, + libusb_device ***list); +void LIBUSB_CALL libusb_free_device_list(libusb_device **list, + int unref_devices); +libusb_device * LIBUSB_CALL libusb_ref_device(libusb_device *dev); +void LIBUSB_CALL libusb_unref_device(libusb_device *dev); + +int LIBUSB_CALL libusb_get_configuration(libusb_device_handle *dev, + int *config); +int LIBUSB_CALL libusb_get_device_descriptor(libusb_device *dev, + struct libusb_device_descriptor *desc); +int LIBUSB_CALL libusb_get_active_config_descriptor(libusb_device *dev, + struct libusb_config_descriptor **config); +int LIBUSB_CALL libusb_get_config_descriptor(libusb_device *dev, + uint8_t config_index, struct libusb_config_descriptor **config); +int LIBUSB_CALL libusb_get_config_descriptor_by_value(libusb_device *dev, + uint8_t bConfigurationValue, struct libusb_config_descriptor **config); +void LIBUSB_CALL libusb_free_config_descriptor( + struct libusb_config_descriptor *config); +int LIBUSB_CALL libusb_get_ss_endpoint_companion_descriptor( + libusb_context *ctx, + const struct libusb_endpoint_descriptor *endpoint, + struct libusb_ss_endpoint_companion_descriptor **ep_comp); +void LIBUSB_CALL libusb_free_ss_endpoint_companion_descriptor( + struct libusb_ss_endpoint_companion_descriptor *ep_comp); +int LIBUSB_CALL libusb_get_bos_descriptor(libusb_device_handle *dev_handle, + struct libusb_bos_descriptor **bos); +void LIBUSB_CALL libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos); +int LIBUSB_CALL libusb_get_usb_2_0_extension_descriptor( + libusb_context *ctx, + struct libusb_bos_dev_capability_descriptor *dev_cap, + struct libusb_usb_2_0_extension_descriptor **usb_2_0_extension); +void LIBUSB_CALL libusb_free_usb_2_0_extension_descriptor( + struct libusb_usb_2_0_extension_descriptor *usb_2_0_extension); +int LIBUSB_CALL libusb_get_ss_usb_device_capability_descriptor( + libusb_context *ctx, + struct libusb_bos_dev_capability_descriptor *dev_cap, + struct libusb_ss_usb_device_capability_descriptor **ss_usb_device_cap); +void LIBUSB_CALL libusb_free_ss_usb_device_capability_descriptor( + struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_cap); +int LIBUSB_CALL libusb_get_container_id_descriptor(libusb_context *ctx, + struct libusb_bos_dev_capability_descriptor *dev_cap, + struct libusb_container_id_descriptor **container_id); +void LIBUSB_CALL libusb_free_container_id_descriptor( + struct libusb_container_id_descriptor *container_id); +uint8_t LIBUSB_CALL libusb_get_bus_number(libusb_device *dev); +uint8_t LIBUSB_CALL libusb_get_port_number(libusb_device *dev); +int LIBUSB_CALL libusb_get_port_numbers(libusb_device *dev, uint8_t *port_numbers, int port_numbers_len); +LIBUSB_DEPRECATED_FOR(libusb_get_port_numbers) +int LIBUSB_CALL libusb_get_port_path(libusb_context *ctx, libusb_device *dev, uint8_t *path, uint8_t path_length); +libusb_device * LIBUSB_CALL libusb_get_parent(libusb_device *dev); +uint8_t LIBUSB_CALL libusb_get_device_address(libusb_device *dev); +int LIBUSB_CALL libusb_get_device_speed(libusb_device *dev); +int LIBUSB_CALL libusb_get_max_packet_size(libusb_device *dev, + unsigned char endpoint); +int LIBUSB_CALL libusb_get_max_iso_packet_size(libusb_device *dev, + unsigned char endpoint); + +int LIBUSB_CALL libusb_wrap_sys_device(libusb_context *ctx, intptr_t sys_dev, libusb_device_handle **dev_handle); +int LIBUSB_CALL libusb_open(libusb_device *dev, libusb_device_handle **dev_handle); +void LIBUSB_CALL libusb_close(libusb_device_handle *dev_handle); +libusb_device * LIBUSB_CALL libusb_get_device(libusb_device_handle *dev_handle); + +int LIBUSB_CALL libusb_set_configuration(libusb_device_handle *dev_handle, + int configuration); +int LIBUSB_CALL libusb_claim_interface(libusb_device_handle *dev_handle, + int interface_number); +int LIBUSB_CALL libusb_release_interface(libusb_device_handle *dev_handle, + int interface_number); + +libusb_device_handle * LIBUSB_CALL libusb_open_device_with_vid_pid( + libusb_context *ctx, uint16_t vendor_id, uint16_t product_id); + +int LIBUSB_CALL libusb_set_interface_alt_setting(libusb_device_handle *dev_handle, + int interface_number, int alternate_setting); +int LIBUSB_CALL libusb_clear_halt(libusb_device_handle *dev_handle, + unsigned char endpoint); +int LIBUSB_CALL libusb_reset_device(libusb_device_handle *dev_handle); + +int LIBUSB_CALL libusb_alloc_streams(libusb_device_handle *dev_handle, + uint32_t num_streams, unsigned char *endpoints, int num_endpoints); +int LIBUSB_CALL libusb_free_streams(libusb_device_handle *dev_handle, + unsigned char *endpoints, int num_endpoints); + +unsigned char * LIBUSB_CALL libusb_dev_mem_alloc(libusb_device_handle *dev_handle, + size_t length); +int LIBUSB_CALL libusb_dev_mem_free(libusb_device_handle *dev_handle, + unsigned char *buffer, size_t length); + +int LIBUSB_CALL libusb_kernel_driver_active(libusb_device_handle *dev_handle, + int interface_number); +int LIBUSB_CALL libusb_detach_kernel_driver(libusb_device_handle *dev_handle, + int interface_number); +int LIBUSB_CALL libusb_attach_kernel_driver(libusb_device_handle *dev_handle, + int interface_number); +int LIBUSB_CALL libusb_set_auto_detach_kernel_driver( + libusb_device_handle *dev_handle, int enable); + +/* async I/O */ + +/** \ingroup libusb_asyncio + * Get the data section of a control transfer. This convenience function is here + * to remind you that the data does not start until 8 bytes into the actual + * buffer, as the setup packet comes first. + * + * Calling this function only makes sense from a transfer callback function, + * or situations where you have already allocated a suitably sized buffer at + * transfer->buffer. + * + * \param transfer a transfer + * \returns pointer to the first byte of the data section + */ +static inline unsigned char *libusb_control_transfer_get_data( + struct libusb_transfer *transfer) +{ + return transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE; +} + +/** \ingroup libusb_asyncio + * Get the control setup packet of a control transfer. This convenience + * function is here to remind you that the control setup occupies the first + * 8 bytes of the transfer data buffer. + * + * Calling this function only makes sense from a transfer callback function, + * or situations where you have already allocated a suitably sized buffer at + * transfer->buffer. + * + * \param transfer a transfer + * \returns a casted pointer to the start of the transfer data buffer + */ +static inline struct libusb_control_setup *libusb_control_transfer_get_setup( + struct libusb_transfer *transfer) +{ + return (struct libusb_control_setup *)(void *)transfer->buffer; +} + +/** \ingroup libusb_asyncio + * Helper function to populate the setup packet (first 8 bytes of the data + * buffer) for a control transfer. The wIndex, wValue and wLength values should + * be given in host-endian byte order. + * + * \param buffer buffer to output the setup packet into + * This pointer must be aligned to at least 2 bytes boundary. + * \param bmRequestType see the + * \ref libusb_control_setup::bmRequestType "bmRequestType" field of + * \ref libusb_control_setup + * \param bRequest see the + * \ref libusb_control_setup::bRequest "bRequest" field of + * \ref libusb_control_setup + * \param wValue see the + * \ref libusb_control_setup::wValue "wValue" field of + * \ref libusb_control_setup + * \param wIndex see the + * \ref libusb_control_setup::wIndex "wIndex" field of + * \ref libusb_control_setup + * \param wLength see the + * \ref libusb_control_setup::wLength "wLength" field of + * \ref libusb_control_setup + */ +static inline void libusb_fill_control_setup(unsigned char *buffer, + uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, + uint16_t wLength) +{ + struct libusb_control_setup *setup = (struct libusb_control_setup *)(void *)buffer; + setup->bmRequestType = bmRequestType; + setup->bRequest = bRequest; + setup->wValue = libusb_cpu_to_le16(wValue); + setup->wIndex = libusb_cpu_to_le16(wIndex); + setup->wLength = libusb_cpu_to_le16(wLength); +} + +struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer(int iso_packets); +int LIBUSB_CALL libusb_submit_transfer(struct libusb_transfer *transfer); +int LIBUSB_CALL libusb_cancel_transfer(struct libusb_transfer *transfer); +void LIBUSB_CALL libusb_free_transfer(struct libusb_transfer *transfer); +void LIBUSB_CALL libusb_transfer_set_stream_id( + struct libusb_transfer *transfer, uint32_t stream_id); +uint32_t LIBUSB_CALL libusb_transfer_get_stream_id( + struct libusb_transfer *transfer); + +/** \ingroup libusb_asyncio + * Helper function to populate the required \ref libusb_transfer fields + * for a control transfer. + * + * If you pass a transfer buffer to this function, the first 8 bytes will + * be interpreted as a control setup packet, and the wLength field will be + * used to automatically populate the \ref libusb_transfer::length "length" + * field of the transfer. Therefore the recommended approach is: + * -# Allocate a suitably sized data buffer (including space for control setup) + * -# Call libusb_fill_control_setup() + * -# If this is a host-to-device transfer with a data stage, put the data + * in place after the setup packet + * -# Call this function + * -# Call libusb_submit_transfer() + * + * It is also legal to pass a NULL buffer to this function, in which case this + * function will not attempt to populate the length field. Remember that you + * must then populate the buffer and length fields later. + * + * \param transfer the transfer to populate + * \param dev_handle handle of the device that will handle the transfer + * \param buffer data buffer. If provided, this function will interpret the + * first 8 bytes as a setup packet and infer the transfer length from that. + * This pointer must be aligned to at least 2 bytes boundary. + * \param callback callback function to be invoked on transfer completion + * \param user_data user data to pass to callback function + * \param timeout timeout for the transfer in milliseconds + */ +static inline void libusb_fill_control_transfer( + struct libusb_transfer *transfer, libusb_device_handle *dev_handle, + unsigned char *buffer, libusb_transfer_cb_fn callback, void *user_data, + unsigned int timeout) +{ + struct libusb_control_setup *setup = (struct libusb_control_setup *)(void *)buffer; + transfer->dev_handle = dev_handle; + transfer->endpoint = 0; + transfer->type = LIBUSB_TRANSFER_TYPE_CONTROL; + transfer->timeout = timeout; + transfer->buffer = buffer; + if (setup) + transfer->length = (int) (LIBUSB_CONTROL_SETUP_SIZE + + libusb_le16_to_cpu(setup->wLength)); + transfer->user_data = user_data; + transfer->callback = callback; +} + +/** \ingroup libusb_asyncio + * Helper function to populate the required \ref libusb_transfer fields + * for a bulk transfer. + * + * \param transfer the transfer to populate + * \param dev_handle handle of the device that will handle the transfer + * \param endpoint address of the endpoint where this transfer will be sent + * \param buffer data buffer + * \param length length of data buffer + * \param callback callback function to be invoked on transfer completion + * \param user_data user data to pass to callback function + * \param timeout timeout for the transfer in milliseconds + */ +static inline void libusb_fill_bulk_transfer(struct libusb_transfer *transfer, + libusb_device_handle *dev_handle, unsigned char endpoint, + unsigned char *buffer, int length, libusb_transfer_cb_fn callback, + void *user_data, unsigned int timeout) +{ + transfer->dev_handle = dev_handle; + transfer->endpoint = endpoint; + transfer->type = LIBUSB_TRANSFER_TYPE_BULK; + transfer->timeout = timeout; + transfer->buffer = buffer; + transfer->length = length; + transfer->user_data = user_data; + transfer->callback = callback; +} + +/** \ingroup libusb_asyncio + * Helper function to populate the required \ref libusb_transfer fields + * for a bulk transfer using bulk streams. + * + * Since version 1.0.19, \ref LIBUSB_API_VERSION >= 0x01000103 + * + * \param transfer the transfer to populate + * \param dev_handle handle of the device that will handle the transfer + * \param endpoint address of the endpoint where this transfer will be sent + * \param stream_id bulk stream id for this transfer + * \param buffer data buffer + * \param length length of data buffer + * \param callback callback function to be invoked on transfer completion + * \param user_data user data to pass to callback function + * \param timeout timeout for the transfer in milliseconds + */ +static inline void libusb_fill_bulk_stream_transfer( + struct libusb_transfer *transfer, libusb_device_handle *dev_handle, + unsigned char endpoint, uint32_t stream_id, + unsigned char *buffer, int length, libusb_transfer_cb_fn callback, + void *user_data, unsigned int timeout) +{ + libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer, + length, callback, user_data, timeout); + transfer->type = LIBUSB_TRANSFER_TYPE_BULK_STREAM; + libusb_transfer_set_stream_id(transfer, stream_id); +} + +/** \ingroup libusb_asyncio + * Helper function to populate the required \ref libusb_transfer fields + * for an interrupt transfer. + * + * \param transfer the transfer to populate + * \param dev_handle handle of the device that will handle the transfer + * \param endpoint address of the endpoint where this transfer will be sent + * \param buffer data buffer + * \param length length of data buffer + * \param callback callback function to be invoked on transfer completion + * \param user_data user data to pass to callback function + * \param timeout timeout for the transfer in milliseconds + */ +static inline void libusb_fill_interrupt_transfer( + struct libusb_transfer *transfer, libusb_device_handle *dev_handle, + unsigned char endpoint, unsigned char *buffer, int length, + libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout) +{ + transfer->dev_handle = dev_handle; + transfer->endpoint = endpoint; + transfer->type = LIBUSB_TRANSFER_TYPE_INTERRUPT; + transfer->timeout = timeout; + transfer->buffer = buffer; + transfer->length = length; + transfer->user_data = user_data; + transfer->callback = callback; +} + +/** \ingroup libusb_asyncio + * Helper function to populate the required \ref libusb_transfer fields + * for an isochronous transfer. + * + * \param transfer the transfer to populate + * \param dev_handle handle of the device that will handle the transfer + * \param endpoint address of the endpoint where this transfer will be sent + * \param buffer data buffer + * \param length length of data buffer + * \param num_iso_packets the number of isochronous packets + * \param callback callback function to be invoked on transfer completion + * \param user_data user data to pass to callback function + * \param timeout timeout for the transfer in milliseconds + */ +static inline void libusb_fill_iso_transfer(struct libusb_transfer *transfer, + libusb_device_handle *dev_handle, unsigned char endpoint, + unsigned char *buffer, int length, int num_iso_packets, + libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout) +{ + transfer->dev_handle = dev_handle; + transfer->endpoint = endpoint; + transfer->type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS; + transfer->timeout = timeout; + transfer->buffer = buffer; + transfer->length = length; + transfer->num_iso_packets = num_iso_packets; + transfer->user_data = user_data; + transfer->callback = callback; +} + +/** \ingroup libusb_asyncio + * Convenience function to set the length of all packets in an isochronous + * transfer, based on the num_iso_packets field in the transfer structure. + * + * \param transfer a transfer + * \param length the length to set in each isochronous packet descriptor + * \see libusb_get_max_packet_size() + */ +static inline void libusb_set_iso_packet_lengths( + struct libusb_transfer *transfer, unsigned int length) +{ + int i; + + for (i = 0; i < transfer->num_iso_packets; i++) + transfer->iso_packet_desc[i].length = length; +} + +/** \ingroup libusb_asyncio + * Convenience function to locate the position of an isochronous packet + * within the buffer of an isochronous transfer. + * + * This is a thorough function which loops through all preceding packets, + * accumulating their lengths to find the position of the specified packet. + * Typically you will assign equal lengths to each packet in the transfer, + * and hence the above method is sub-optimal. You may wish to use + * libusb_get_iso_packet_buffer_simple() instead. + * + * \param transfer a transfer + * \param packet the packet to return the address of + * \returns the base address of the packet buffer inside the transfer buffer, + * or NULL if the packet does not exist. + * \see libusb_get_iso_packet_buffer_simple() + */ +static inline unsigned char *libusb_get_iso_packet_buffer( + struct libusb_transfer *transfer, unsigned int packet) +{ + int i; + size_t offset = 0; + int _packet; + + /* oops..slight bug in the API. packet is an unsigned int, but we use + * signed integers almost everywhere else. range-check and convert to + * signed to avoid compiler warnings. FIXME for libusb-2. */ + if (packet > INT_MAX) + return NULL; + _packet = (int) packet; + + if (_packet >= transfer->num_iso_packets) + return NULL; + + for (i = 0; i < _packet; i++) + offset += transfer->iso_packet_desc[i].length; + + return transfer->buffer + offset; +} + +/** \ingroup libusb_asyncio + * Convenience function to locate the position of an isochronous packet + * within the buffer of an isochronous transfer, for transfers where each + * packet is of identical size. + * + * This function relies on the assumption that every packet within the transfer + * is of identical size to the first packet. Calculating the location of + * the packet buffer is then just a simple calculation: + * buffer + (packet_size * packet) + * + * Do not use this function on transfers other than those that have identical + * packet lengths for each packet. + * + * \param transfer a transfer + * \param packet the packet to return the address of + * \returns the base address of the packet buffer inside the transfer buffer, + * or NULL if the packet does not exist. + * \see libusb_get_iso_packet_buffer() + */ +static inline unsigned char *libusb_get_iso_packet_buffer_simple( + struct libusb_transfer *transfer, unsigned int packet) +{ + int _packet; + + /* oops..slight bug in the API. packet is an unsigned int, but we use + * signed integers almost everywhere else. range-check and convert to + * signed to avoid compiler warnings. FIXME for libusb-2. */ + if (packet > INT_MAX) + return NULL; + _packet = (int) packet; + + if (_packet >= transfer->num_iso_packets) + return NULL; + + return transfer->buffer + ((int) transfer->iso_packet_desc[0].length * _packet); +} + +/* sync I/O */ + +int LIBUSB_CALL libusb_control_transfer(libusb_device_handle *dev_handle, + uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, + unsigned char *data, uint16_t wLength, unsigned int timeout); + +int LIBUSB_CALL libusb_bulk_transfer(libusb_device_handle *dev_handle, + unsigned char endpoint, unsigned char *data, int length, + int *actual_length, unsigned int timeout); + +int LIBUSB_CALL libusb_interrupt_transfer(libusb_device_handle *dev_handle, + unsigned char endpoint, unsigned char *data, int length, + int *actual_length, unsigned int timeout); + +/** \ingroup libusb_desc + * Retrieve a descriptor from the default control pipe. + * This is a convenience function which formulates the appropriate control + * message to retrieve the descriptor. + * + * \param dev_handle a device handle + * \param desc_type the descriptor type, see \ref libusb_descriptor_type + * \param desc_index the index of the descriptor to retrieve + * \param data output buffer for descriptor + * \param length size of data buffer + * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure + */ +static inline int libusb_get_descriptor(libusb_device_handle *dev_handle, + uint8_t desc_type, uint8_t desc_index, unsigned char *data, int length) +{ + return libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_IN, + LIBUSB_REQUEST_GET_DESCRIPTOR, (uint16_t) ((desc_type << 8) | desc_index), + 0, data, (uint16_t) length, 1000); +} + +/** \ingroup libusb_desc + * Retrieve a descriptor from a device. + * This is a convenience function which formulates the appropriate control + * message to retrieve the descriptor. The string returned is Unicode, as + * detailed in the USB specifications. + * + * \param dev_handle a device handle + * \param desc_index the index of the descriptor to retrieve + * \param langid the language ID for the string descriptor + * \param data output buffer for descriptor + * \param length size of data buffer + * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure + * \see libusb_get_string_descriptor_ascii() + */ +static inline int libusb_get_string_descriptor(libusb_device_handle *dev_handle, + uint8_t desc_index, uint16_t langid, unsigned char *data, int length) +{ + return libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_IN, + LIBUSB_REQUEST_GET_DESCRIPTOR, (uint16_t)((LIBUSB_DT_STRING << 8) | desc_index), + langid, data, (uint16_t) length, 1000); +} + +int LIBUSB_CALL libusb_get_string_descriptor_ascii(libusb_device_handle *dev_handle, + uint8_t desc_index, unsigned char *data, int length); + +/* polling and timeouts */ + +int LIBUSB_CALL libusb_try_lock_events(libusb_context *ctx); +void LIBUSB_CALL libusb_lock_events(libusb_context *ctx); +void LIBUSB_CALL libusb_unlock_events(libusb_context *ctx); +int LIBUSB_CALL libusb_event_handling_ok(libusb_context *ctx); +int LIBUSB_CALL libusb_event_handler_active(libusb_context *ctx); +void LIBUSB_CALL libusb_interrupt_event_handler(libusb_context *ctx); +void LIBUSB_CALL libusb_lock_event_waiters(libusb_context *ctx); +void LIBUSB_CALL libusb_unlock_event_waiters(libusb_context *ctx); +int LIBUSB_CALL libusb_wait_for_event(libusb_context *ctx, struct timeval *tv); + +int LIBUSB_CALL libusb_handle_events_timeout(libusb_context *ctx, + struct timeval *tv); +int LIBUSB_CALL libusb_handle_events_timeout_completed(libusb_context *ctx, + struct timeval *tv, int *completed); +int LIBUSB_CALL libusb_handle_events(libusb_context *ctx); +int LIBUSB_CALL libusb_handle_events_completed(libusb_context *ctx, int *completed); +int LIBUSB_CALL libusb_handle_events_locked(libusb_context *ctx, + struct timeval *tv); +int LIBUSB_CALL libusb_pollfds_handle_timeouts(libusb_context *ctx); +int LIBUSB_CALL libusb_get_next_timeout(libusb_context *ctx, + struct timeval *tv); + +/** \ingroup libusb_poll + * File descriptor for polling + */ +struct libusb_pollfd { + /** Numeric file descriptor */ + int fd; + + /** Event flags to poll for from . POLLIN indicates that you + * should monitor this file descriptor for becoming ready to read from, + * and POLLOUT indicates that you should monitor this file descriptor for + * nonblocking write readiness. */ + short events; +}; + +/** \ingroup libusb_poll + * Callback function, invoked when a new file descriptor should be added + * to the set of file descriptors monitored for events. + * \param fd the new file descriptor + * \param events events to monitor for, see \ref libusb_pollfd for a + * description + * \param user_data User data pointer specified in + * libusb_set_pollfd_notifiers() call + * \see libusb_set_pollfd_notifiers() + */ +typedef void (LIBUSB_CALL *libusb_pollfd_added_cb)(int fd, short events, + void *user_data); + +/** \ingroup libusb_poll + * Callback function, invoked when a file descriptor should be removed from + * the set of file descriptors being monitored for events. After returning + * from this callback, do not use that file descriptor again. + * \param fd the file descriptor to stop monitoring + * \param user_data User data pointer specified in + * libusb_set_pollfd_notifiers() call + * \see libusb_set_pollfd_notifiers() + */ +typedef void (LIBUSB_CALL *libusb_pollfd_removed_cb)(int fd, void *user_data); + +const struct libusb_pollfd ** LIBUSB_CALL libusb_get_pollfds( + libusb_context *ctx); +void LIBUSB_CALL libusb_free_pollfds(const struct libusb_pollfd **pollfds); +void LIBUSB_CALL libusb_set_pollfd_notifiers(libusb_context *ctx, + libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb, + void *user_data); + +/** \ingroup libusb_hotplug + * Callback handle. + * + * Callbacks handles are generated by libusb_hotplug_register_callback() + * and can be used to deregister callbacks. Callback handles are unique + * per libusb_context and it is safe to call libusb_hotplug_deregister_callback() + * on an already deregistered callback. + * + * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 + * + * For more information, see \ref libusb_hotplug. + */ +typedef int libusb_hotplug_callback_handle; + +/** \ingroup libusb_hotplug + * + * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 + * + * Hotplug events */ +typedef enum { + /** A device has been plugged in and is ready to use */ + LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED = (1 << 0), + + /** A device has left and is no longer available. + * It is the user's responsibility to call libusb_close on any handle associated with a disconnected device. + * It is safe to call libusb_get_device_descriptor on a device that has left */ + LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT = (1 << 1) +} libusb_hotplug_event; + +/** \ingroup libusb_hotplug + * + * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 + * + * Hotplug flags */ +typedef enum { + /** Arm the callback and fire it for all matching currently attached devices. */ + LIBUSB_HOTPLUG_ENUMERATE = (1 << 0) +} libusb_hotplug_flag; + +/** \ingroup libusb_hotplug + * Convenience macro when not using any flags */ +#define LIBUSB_HOTPLUG_NO_FLAGS 0 + +/** \ingroup libusb_hotplug + * Wildcard matching for hotplug events */ +#define LIBUSB_HOTPLUG_MATCH_ANY -1 + +/** \ingroup libusb_hotplug + * Hotplug callback function type. When requesting hotplug event notifications, + * you pass a pointer to a callback function of this type. + * + * This callback may be called by an internal event thread and as such it is + * recommended the callback do minimal processing before returning. + * + * libusb will call this function later, when a matching event had happened on + * a matching device. See \ref libusb_hotplug for more information. + * + * It is safe to call either libusb_hotplug_register_callback() or + * libusb_hotplug_deregister_callback() from within a callback function. + * + * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 + * + * \param ctx context of this notification + * \param device libusb_device this event occurred on + * \param event event that occurred + * \param user_data user data provided when this callback was registered + * \returns bool whether this callback is finished processing events. + * returning 1 will cause this callback to be deregistered + */ +typedef int (LIBUSB_CALL *libusb_hotplug_callback_fn)(libusb_context *ctx, + libusb_device *device, libusb_hotplug_event event, void *user_data); + +/** \ingroup libusb_hotplug + * Register a hotplug callback function + * + * Register a callback with the libusb_context. The callback will fire + * when a matching event occurs on a matching device. The callback is + * armed until either it is deregistered with libusb_hotplug_deregister_callback() + * or the supplied callback returns 1 to indicate it is finished processing events. + * + * If the \ref LIBUSB_HOTPLUG_ENUMERATE is passed the callback will be + * called with a \ref LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED for all devices + * already plugged into the machine. Note that libusb modifies its internal + * device list from a separate thread, while calling hotplug callbacks from + * libusb_handle_events(), so it is possible for a device to already be present + * on, or removed from, its internal device list, while the hotplug callbacks + * still need to be dispatched. This means that when using \ref + * LIBUSB_HOTPLUG_ENUMERATE, your callback may be called twice for the arrival + * of the same device, once from libusb_hotplug_register_callback() and once + * from libusb_handle_events(); and/or your callback may be called for the + * removal of a device for which an arrived call was never made. + * + * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 + * + * \param[in] ctx context to register this callback with + * \param[in] events bitwise or of hotplug events that will trigger this callback. + * See \ref libusb_hotplug_event + * \param[in] flags bitwise or of hotplug flags that affect registration. + * See \ref libusb_hotplug_flag + * \param[in] vendor_id the vendor id to match or \ref LIBUSB_HOTPLUG_MATCH_ANY + * \param[in] product_id the product id to match or \ref LIBUSB_HOTPLUG_MATCH_ANY + * \param[in] dev_class the device class to match or \ref LIBUSB_HOTPLUG_MATCH_ANY + * \param[in] cb_fn the function to be invoked on a matching event/device + * \param[in] user_data user data to pass to the callback function + * \param[out] callback_handle pointer to store the handle of the allocated callback (can be NULL) + * \returns LIBUSB_SUCCESS on success LIBUSB_ERROR code on failure + */ +int LIBUSB_CALL libusb_hotplug_register_callback(libusb_context *ctx, + int events, int flags, + int vendor_id, int product_id, int dev_class, + libusb_hotplug_callback_fn cb_fn, void *user_data, + libusb_hotplug_callback_handle *callback_handle); + +/** \ingroup libusb_hotplug + * Deregisters a hotplug callback. + * + * Deregister a callback from a libusb_context. This function is safe to call from within + * a hotplug callback. + * + * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 + * + * \param[in] ctx context this callback is registered with + * \param[in] callback_handle the handle of the callback to deregister + */ +void LIBUSB_CALL libusb_hotplug_deregister_callback(libusb_context *ctx, + libusb_hotplug_callback_handle callback_handle); + +/** \ingroup libusb_hotplug + * Gets the user_data associated with a hotplug callback. + * + * Since version v1.0.24 \ref LIBUSB_API_VERSION >= 0x01000108 + * + * \param[in] ctx context this callback is registered with + * \param[in] callback_handle the handle of the callback to get the user_data of + */ +void * LIBUSB_CALL libusb_hotplug_get_user_data(libusb_context *ctx, + libusb_hotplug_callback_handle callback_handle); + +/** \ingroup libusb_lib + * Available option values for libusb_set_option(). + */ +enum libusb_option { + /** Set the log message verbosity. + * + * The default level is LIBUSB_LOG_LEVEL_NONE, which means no messages are ever + * printed. If you choose to increase the message verbosity level, ensure + * that your application does not close the stderr file descriptor. + * + * You are advised to use level LIBUSB_LOG_LEVEL_WARNING. libusb is conservative + * with its message logging and most of the time, will only log messages that + * explain error conditions and other oddities. This will help you debug + * your software. + * + * If the LIBUSB_DEBUG environment variable was set when libusb was + * initialized, this function does nothing: the message verbosity is fixed + * to the value in the environment variable. + * + * If libusb was compiled without any message logging, this function does + * nothing: you'll never get any messages. + * + * If libusb was compiled with verbose debug message logging, this function + * does nothing: you'll always get messages from all levels. + */ + LIBUSB_OPTION_LOG_LEVEL = 0, + + /** Use the UsbDk backend for a specific context, if available. + * + * This option should be set immediately after calling libusb_init(), otherwise + * unspecified behavior may occur. + * + * Only valid on Windows. + */ + LIBUSB_OPTION_USE_USBDK = 1, + + /** Set libusb has weak authority. With this option, libusb will skip + * scan devices in libusb_init. + * + * This option should be set before calling libusb_init(), otherwise + * libusb_init will failed. Normally libusb_wrap_sys_device need set + * this option. + * + * Only valid on Linux-based operating system, such as Android. + */ + LIBUSB_OPTION_WEAK_AUTHORITY = 2 +}; + +int LIBUSB_CALL libusb_set_option(libusb_context *ctx, enum libusb_option option, ...); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/Sming/Arch/Rp2040/Components/picotool/picotool b/Sming/Arch/Rp2040/Components/picotool/picotool new file mode 160000 index 0000000000..5d6df39033 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/picotool/picotool @@ -0,0 +1 @@ +Subproject commit 5d6df39033c7166ea6e76cbde1ff0c0240a4bba4 diff --git a/Sming/Arch/Rp2040/Components/rp2040/Kconfig b/Sming/Arch/Rp2040/Components/rp2040/Kconfig new file mode 100644 index 0000000000..3c7a01b401 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/rp2040/Kconfig @@ -0,0 +1,15 @@ +menu "RP2040 Core" + config PICO_BOARD + bool "Development board in use" + default pico + help + If using custom hardware, select ``none``. + List available boards with ``make board-list``. + + config ENABLE_BOOTSEL + bool "Enable BOOTSEL" + default y if SMING_RELEASE + help + Monitor BOOTSEL button and restart in boot mode if pressed. + Avoids need to power-cycle the board to re-program. +endmenu diff --git a/Sming/Arch/Rp2040/Components/rp2040/README.rst b/Sming/Arch/Rp2040/Components/rp2040/README.rst new file mode 100644 index 0000000000..727ddc2862 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/rp2040/README.rst @@ -0,0 +1,30 @@ +RP2040 Core Component +===================== + +.. highlight:: bash + +Contains startup code, crash handling and additional RP2040-specific support code. + +Configuration variables +----------------------- + +.. envvar:: PICO_BOARD + + default: pico + + Select development board in use. + List available boards with ``make list-boards``. + + The SDK defines various useful bits of information in a board header file, + such as the default LED pin, how much flash memory it has, etc. + Use ``make board-info`` to list these values. + + If using custom hardware, select ``none`` and provide definitions as required. + + +.. envvar:: ENABLE_BOOTSEL + + default: 1 for debug, 0 for release builds + + This setting is provided to make it easy to re-program RP2040 boards during development. + When enabled, Sming monitors the BOOTSEL button and restartS in boot mode if pressed. diff --git a/Sming/Arch/Rp2040/Components/rp2040/board-info.awk b/Sming/Arch/Rp2040/Components/rp2040/board-info.awk new file mode 100644 index 0000000000..6965e8113e --- /dev/null +++ b/Sming/Arch/Rp2040/Components/rp2040/board-info.awk @@ -0,0 +1,27 @@ +# Scan RP2040 SDK board header file and extract variables for use in makefiles +BEGIN { + FS = "#define " +} +/^#define +[^_]+/ { + n = index($2, " ") + if (n == 0) { + vars[$2] = "" + } else { + name = substr($2, 1, n-1) + value = substr($2, n + 1) + if (index(value, " ") == 0) { + vars[name] = value + } else { + vars[name] = "$$((" value "))" + } + } +} +END { + for (v in vars) { + printf "%s=%s\\n", v, vars[v] + } + printf "RP2040_BOARD_VARS := " + for (v in vars) { + printf v " " + } +} diff --git a/Sming/Arch/Rp2040/Components/rp2040/component.mk b/Sming/Arch/Rp2040/Components/rp2040/component.mk new file mode 100644 index 0000000000..cca3b2e132 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/rp2040/component.mk @@ -0,0 +1,166 @@ +COMPONENT_SUBMODULES := pico-sdk + +ifdef PICO_SDK_PATH +export PICO_SDK_PATH := $(call FixPath,$(PICO_SDK_PATH)) +else +export PICO_SDK_PATH := $(COMPONENT_PATH)/pico-sdk +endif + +COMPONENT_RELINK_VARS += PICO_BOARD +ifndef PICO_BOARD +export PICO_BOARD=pico +endif + +GLOBAL_CFLAGS += \ + -DPICO_ON_DEVICE=1 + +# Press BOOTSEL to reboot into programming mode +COMPONENT_RELINK_VARS := ENABLE_BOOTSEL +ifndef SMING_RELEASE +ENABLE_BOOTSEL ?= 1 +endif +ifeq ($(ENABLE_BOOTSEL),1) +COMPONENT_CXXFLAGS += -DENABLE_BOOTSEL=1 +endif + +WRAPPED_FUNCTIONS := + +$(foreach c,$(wildcard $(COMPONENT_PATH)/sdk/*.mk),$(eval include $c)) + +EXTRA_LDFLAGS := \ + $(call Wrap,$(WRAPPED_FUNCTIONS)) \ + -T memmap_default.ld + +SDK_INTERFACES := \ + boards \ + common/pico_base \ + common/pico_binary_info \ + common/pico_bit_ops \ + common/pico_divider \ + common/pico_sync \ + common/pico_util \ + rp2040/hardware_regs \ + rp2040/hardware_structs \ + rp2_common/hardware_gpio \ + rp2_common/pico_platform \ + rp2_common/hardware_base \ + rp2_common/hardware_sync \ + rp2_common/hardware_divider \ + rp2_common/hardware_timer \ + rp2_common/hardware_clocks \ + rp2_common/hardware_dma \ + rp2_common/hardware_exception \ + rp2_common/hardware_flash \ + rp2_common/hardware_irq \ + rp2_common/hardware_resets \ + rp2_common/hardware_rosc \ + rp2_common/hardware_rtc \ + rp2_common/hardware_pll \ + rp2_common/hardware_vreg \ + rp2_common/hardware_watchdog \ + rp2_common/hardware_xosc \ + rp2_common/pico_bootrom \ + rp2_common/pico_double \ + rp2_common/pico_int64_ops \ + rp2_common/pico_float \ + rp2_common/pico_runtime \ + rp2_common/pico_unique_id + +COMPONENT_INCDIRS := \ + src/include \ + $(foreach p,$(SDK_INTERFACES),$(PICO_SDK_PATH)/src/$p/include) + + +COMPONENT_SRCDIRS := src + +RP2040_COMPONENT_DIR := $(COMPONENT_PATH) +PICO_BUILD_DIR := $(COMPONENT_BUILD_BASE)/sdk +PICO_BASE_DIR := $(PICO_BUILD_DIR)/generated/pico_base +PICO_CONFIG := $(PICO_BASE_DIR)/pico/config_autogen.h +PICO_LIB := $(PICO_BUILD_DIR)/libpico.a + +COMPONENT_INCDIRS += $(PICO_BASE_DIR) + +LIBDIRS += \ + $(PICO_SDK_PATH)/src/rp2_common/pico_standard_link \ + $(PICO_BUILD_DIR) + +EXTRA_LIBS += \ + pico \ + m + +ifdef NINJA +NINJA := $(call FixPath,$(NINJA)) +else +NINJA := ninja +endif +RP2040_CMAKE_OPTIONS := \ + -G Ninja \ + -DCMAKE_MAKE_PROGRAM=$(NINJA) + +COMPONENT_PREREQUISITES := $(PICO_CONFIG) + +BOOTLOADER := $(PICO_BUILD_DIR)/pico-sdk/src/rp2_common/boot_stage2/bs2_default_padded_checksummed.S + +COMPONENT_TARGETS := \ + $(PICO_LIB) + +$(PICO_CONFIG): $(PICO_BUILD_DIR) + $(Q) cd $(PICO_BUILD_DIR) && $(CMAKE) $(RP2040_CMAKE_OPTIONS) $(RP2040_COMPONENT_DIR)/sdk + +$(COMPONENT_RULE)$(PICO_LIB): + $(Q) cd $(@D) && $(NINJA) + +ifdef COMPONENT_RULE +$(PICO_BUILD_DIR): + $(Q) mkdir -p $@ +endif + + +# Pull in board configuration, specifically PICO_FLASH_SIZE_BYTES +# It's only available in a .h file so needs some parsing +RP2040_BOARD_PATH := $(PICO_SDK_PATH)/src/boards/include/boards +RP2040_BOARD_HEADERS = $(notdir $(wildcard $(RP2040_BOARD_PATH)/*.h)) +RP2040_BOARDS = $(RP2040_BOARD_HEADERS:.h=) + +# Used to un-escape newlines from AWK script +define NewLine + + +endef + +BOARD_HEADER_PATH := $(PICO_SDK_PATH)/src/boards/include/boards/$(PICO_BOARD).h + +ifneq (,$(wildcard $(BOARD_HEADER_PATH))) +$(eval $(subst \n,$(NewLine),$(shell $(AWK) -f $(RP2040_COMPONENT_DIR)/board-info.awk $(BOARD_HEADER_PATH)))) +endif + +DEBUG_VARS += $(RP2040_BOARD_VARS) + + +CUSTOM_TARGETS += check-flash-size + +.PHONY: check-flash-size +check-flash-size: + @if [ $$(( $(STORAGE_DEVICE_spiFlash_SIZE_BYTES) - $(PICO_FLASH_SIZE_BYTES) )) -gt 0 ]; then \ + echo; \ + echo "ERROR: Hardware config spiFlash size exceeds value board definition"; \ + echo "PICO_FLASH_SIZE_BYTES = $(PICO_FLASH_SIZE_BYTES)"; \ + echo "spiFlash.size = $(STORAGE_DEVICE_spiFlash_SIZE_BYTES)"; \ + echo; \ + echo "Please fix your hardware configuration!"; \ + echo; \ + exit 1; \ + fi + + +##@Help + +.PHONY: list-boards +list-boards: ##List development boards defined in SDK + $(call PrintVariable,RP2040_BOARDS) + + +.PHONY: board-info +board-info: ##List RP2040 board configuration + $(call PrintVariableRefs,RP2040_BOARD_VARS) diff --git a/Sming/Arch/Rp2040/Components/rp2040/pico-sdk b/Sming/Arch/Rp2040/Components/rp2040/pico-sdk new file mode 160000 index 0000000000..bfcbefafc5 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/rp2040/pico-sdk @@ -0,0 +1 @@ +Subproject commit bfcbefafc5d2a210551a4d9d80b4303d4ae0adf7 diff --git a/Sming/Arch/Host/Components/fatfs/ff.h b/Sming/Arch/Rp2040/Components/rp2040/pico-sdk.no-recursive similarity index 100% rename from Sming/Arch/Host/Components/fatfs/ff.h rename to Sming/Arch/Rp2040/Components/rp2040/pico-sdk.no-recursive diff --git a/Sming/Arch/Rp2040/Components/rp2040/pico-sdk.patch b/Sming/Arch/Rp2040/Components/rp2040/pico-sdk.patch new file mode 100644 index 0000000000..405be571b1 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/rp2040/pico-sdk.patch @@ -0,0 +1,13 @@ +diff --git a/src/rp2_common/pico_platform/include/pico/platform.h b/src/rp2_common/pico_platform/include/pico/platform.h +index c008b95..bf5a690 100644 +--- a/src/rp2_common/pico_platform/include/pico/platform.h ++++ b/src/rp2_common/pico_platform/include/pico/platform.h +@@ -146,7 +146,7 @@ static inline void tight_loop_contents(void) {} + * \return a * b + */ + __force_inline static int32_t __mul_instruction(int32_t a, int32_t b) { +- asm ("mul %0, %1" : "+l" (a) : "l" (b) : ); ++ __asm__ ("mul %0, %1" : "+l" (a) : "l" (b) : ); + return a; + } + diff --git a/Sming/Arch/Rp2040/Components/rp2040/sdk/CMakeLists.txt b/Sming/Arch/Rp2040/Components/rp2040/sdk/CMakeLists.txt new file mode 100644 index 0000000000..739b172780 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/rp2040/sdk/CMakeLists.txt @@ -0,0 +1,76 @@ +cmake_minimum_required(VERSION 3.12) + +set(PICO_PLATFORM "rp2040") +set(PICO_COMPILER "pico_arm_gcc") + +set(CMAKE_C_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_BUILD_TYPE RelWithDebInfo) + +include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake) +# include(pico_extras_import.cmake) + +project(pico_lib C CXX ASM) + +# Don't want these interfaces +set(SKIP_PICO_MALLOC 1) +set(SKIP_PICO_STDIO 1) +set(SKIP_PICO_STDIO_SEMIHOSTING 1) +set(SKIP_PICO_STDIO_UART 1) +set(SKIP_PICO_STDIO_USB 1) +set(SKIP_TINYUSB 1) + +# Initialize the SDK +pico_sdk_init() + +add_library(pico STATIC) + +# Use a longer XOSC startup time, to accommodate Adafruit and other boards that may need it. +target_compile_definitions(pico PUBLIC + PICO_PRINTF_ALWAYS_INCLUDED=1 + PICO_FLASH_SIZE_BYTES=16777216 + PICO_XOSC_STARTUP_DELAY_MULTIPLIER=64 +) + +pico_set_program_name(pico "Sming") +pico_set_program_url(pico "https://github.com/SmingHub/Sming") + +include_directories(BEFORE ${pico_lib_SOURCE_DIR}) + +target_link_libraries(pico + hardware_adc + hardware_base + hardware_claim + hardware_clocks + hardware_divider + hardware_dma + hardware_exception + hardware_flash + hardware_gpio + hardware_i2c + hardware_interp + hardware_irq + hardware_pio + hardware_pll + hardware_pwm + hardware_resets + hardware_rtc + hardware_spi + hardware_sync + hardware_timer + hardware_uart + hardware_vreg + hardware_watchdog + hardware_xosc + pico_bit_ops + pico_divider + pico_double + pico_fix + pico_float + pico_int64_ops + pico_mem_ops + pico_runtime + pico_standard_link + pico_unique_id + pico_audio_i2s +) diff --git a/Sming/Arch/Rp2040/Components/rp2040/sdk/pico_bit_ops.mk b/Sming/Arch/Rp2040/Components/rp2040/sdk/pico_bit_ops.mk new file mode 100644 index 0000000000..a0ec0d43df --- /dev/null +++ b/Sming/Arch/Rp2040/Components/rp2040/sdk/pico_bit_ops.mk @@ -0,0 +1,9 @@ +# pico_bit_ops + +WRAPPED_FUNCTIONS += \ + __clzsi2 \ + __clzdi2 \ + __ctzsi2 \ + __ctzdi2 \ + __popcountsi2 \ + __popcountdi2 diff --git a/Sming/Arch/Rp2040/Components/rp2040/sdk/pico_divider.mk b/Sming/Arch/Rp2040/Components/rp2040/sdk/pico_divider.mk new file mode 100644 index 0000000000..8578a4ccf2 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/rp2040/sdk/pico_divider.mk @@ -0,0 +1,9 @@ +# pico_divider + +WRAPPED_FUNCTIONS += \ + __aeabi_idiv \ + __aeabi_idivmod \ + __aeabi_ldivmod \ + __aeabi_uidiv \ + __aeabi_uidivmod \ + __aeabi_uldivmod diff --git a/Sming/Arch/Rp2040/Components/rp2040/sdk/pico_double.mk b/Sming/Arch/Rp2040/Components/rp2040/sdk/pico_double.mk new file mode 100644 index 0000000000..765ee5f469 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/rp2040/sdk/pico_double.mk @@ -0,0 +1,64 @@ +# pico_double + +WRAPPED_FUNCTIONS += \ + __aeabi_dadd \ + __aeabi_ddiv \ + __aeabi_dmul \ + __aeabi_drsub \ + __aeabi_dsub \ + __aeabi_cdcmpeq \ + __aeabi_cdrcmple \ + __aeabi_cdcmple \ + __aeabi_dcmpeq \ + __aeabi_dcmplt \ + __aeabi_dcmple \ + __aeabi_dcmpge \ + __aeabi_dcmpgt \ + __aeabi_dcmpun \ + __aeabi_i2d \ + __aeabi_l2d \ + __aeabi_ui2d \ + __aeabi_ul2d \ + __aeabi_d2iz \ + __aeabi_d2lz \ + __aeabi_d2uiz \ + __aeabi_d2ulz \ + __aeabi_d2f \ + sqrt \ + cos \ + sin \ + tan \ + atan2 \ + exp \ + log \ + ldexp \ + copysign \ + trunc \ + floor \ + ceil \ + round \ + sincos \ + asin \ + acos \ + atan \ + sinh \ + cosh \ + tanh \ + asinh \ + acosh \ + atanh \ + exp2 \ + log2 \ + exp10 \ + log10 \ + pow \ + powint \ + hypot \ + cbrt \ + fmod \ + drem \ + remainder \ + remquo \ + expm1 \ + log1p \ + fma diff --git a/Sming/Arch/Rp2040/Components/rp2040/sdk/pico_float.mk b/Sming/Arch/Rp2040/Components/rp2040/sdk/pico_float.mk new file mode 100644 index 0000000000..e45345f639 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/rp2040/sdk/pico_float.mk @@ -0,0 +1,64 @@ +# pico_float + +WRAPPED_FUNCTIONS += \ + __aeabi_fadd \ + __aeabi_fdiv \ + __aeabi_fmul \ + __aeabi_frsub \ + __aeabi_fsub \ + __aeabi_cfcmpeq \ + __aeabi_cfrcmple \ + __aeabi_cfcmple \ + __aeabi_fcmpeq \ + __aeabi_fcmplt \ + __aeabi_fcmple \ + __aeabi_fcmpge \ + __aeabi_fcmpgt \ + __aeabi_fcmpun \ + __aeabi_i2f \ + __aeabi_l2f \ + __aeabi_ui2f \ + __aeabi_ul2f \ + __aeabi_f2iz \ + __aeabi_f2lz \ + __aeabi_f2uiz \ + __aeabi_f2ulz \ + __aeabi_f2d \ + sqrtf \ + cosf \ + sinf \ + tanf \ + atan2f \ + expf \ + logf \ + ldexpf \ + copysignf \ + truncf \ + floorf \ + ceilf \ + roundf \ + sincosf \ + asinf \ + acosf \ + atanf \ + sinhf \ + coshf \ + tanhf \ + asinhf \ + acoshf \ + atanhf \ + exp2f \ + log2f \ + exp10f \ + log10f \ + powf \ + powintf \ + hypotf \ + cbrtf \ + fmodf \ + dremf \ + remainderf \ + remquof \ + expm1f \ + log1pf \ + fmaf diff --git a/Sming/Arch/Rp2040/Components/rp2040/sdk/pico_int64_ops.mk b/Sming/Arch/Rp2040/Components/rp2040/sdk/pico_int64_ops.mk new file mode 100644 index 0000000000..83f39e1492 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/rp2040/sdk/pico_int64_ops.mk @@ -0,0 +1,4 @@ +# pico_int64_ops + +WRAPPED_FUNCTIONS += \ + __aeabi_lmul diff --git a/Sming/Arch/Rp2040/Components/rp2040/sdk/pico_mem_ops.mk b/Sming/Arch/Rp2040/Components/rp2040/sdk/pico_mem_ops.mk new file mode 100644 index 0000000000..6244c18b5d --- /dev/null +++ b/Sming/Arch/Rp2040/Components/rp2040/sdk/pico_mem_ops.mk @@ -0,0 +1,11 @@ +# pico_mem_ops + +WRAPPED_FUNCTIONS += \ + memcpy \ + memset \ + __aeabi_memcpy \ + __aeabi_memset \ + __aeabi_memcpy4 \ + __aeabi_memset4 \ + __aeabi_memcpy8 \ + __aeabi_memset8 diff --git a/Sming/Arch/Rp2040/Components/rp2040/sdk/pico_stdio.mk b/Sming/Arch/Rp2040/Components/rp2040/sdk/pico_stdio.mk new file mode 100644 index 0000000000..aaa395e7bc --- /dev/null +++ b/Sming/Arch/Rp2040/Components/rp2040/sdk/pico_stdio.mk @@ -0,0 +1,8 @@ +# pico_stdio + +WRAPPED_FUNCTIONS += \ + printf \ + vprintf \ + puts \ + putchar \ + getchar diff --git a/Sming/Arch/Rp2040/Components/rp2040/sdk/tusb_config.h b/Sming/Arch/Rp2040/Components/rp2040/sdk/tusb_config.h new file mode 100644 index 0000000000..0c98598d40 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/rp2040/sdk/tusb_config.h @@ -0,0 +1,92 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#ifndef _TUSB_CONFIG_H_ +#define _TUSB_CONFIG_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +//-------------------------------------------------------------------- +// COMMON CONFIGURATION +//-------------------------------------------------------------------- + +#ifndef CFG_TUSB_MCU + #define CFG_TUSB_MCU OPT_MCU_RP2040 +#endif + +#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE +#define CFG_TUSB_OS OPT_OS_PICO + +// CFG_TUSB_DEBUG is defined by compiler in DEBUG build +#ifndef CFG_TUSB_DEBUG +#define CFG_TUSB_DEBUG 0 +#endif + +/* 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 __attribute__ ((aligned(4))) +#endif + +//-------------------------------------------------------------------- +// DEVICE CONFIGURATION +//-------------------------------------------------------------------- + +#ifndef CFG_TUD_ENDPOINT0_SIZE +#define CFG_TUD_ENDPOINT0_SIZE 64 +#endif + +//------------- CLASS -------------// +#define CFG_TUD_HID (2) +#define CFG_TUD_CDC (1) +#define CFG_TUD_MSC (0) +#define CFG_TUD_MIDI (1) +#define CFG_TUD_VENDOR (0) + +#define CFG_TUD_CDC_RX_BUFSIZE (256) +#define CFG_TUD_CDC_TX_BUFSIZE (256) + +#define CFG_TUD_MIDI_RX_BUFSIZE (64) +#define CFG_TUD_MIDI_TX_BUFSIZE (64) + +// HID buffer size Should be sufficient to hold ID (if any) + Data +#define CFG_TUD_HID_EP_BUFSIZE (64) + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_CONFIG_H_ */ diff --git a/Sming/Arch/Rp2040/Components/rp2040/src/clk.c b/Sming/Arch/Rp2040/Components/rp2040/src/clk.c new file mode 100644 index 0000000000..d53a5dc366 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/rp2040/src/clk.c @@ -0,0 +1,117 @@ +#include "include/esp_clk.h" +#include "include/esp_system.h" +#include +#include +#include +#include +#include + +#define DEFAULT_CPU_FREQ (125 * MHZ) + +static volatile uint32_t systick_overflow; + +static void IRAM_ATTR systick_overflow_isr() +{ + ++systick_overflow; +} + +uint32_t IRAM_ATTR esp_get_ccount() +{ + extern volatile uint32_t systick_overflow; + uint32_t ovf = systick_overflow; + if(ovf != systick_overflow) { + ovf = systick_overflow; + } + return systick_hw->cvr | (ovf << 24); +} + +/*! \brief Check if a given system clock frequency is valid/attainable + * \ingroup pico_stdlib + * + * \param freq_khz Requested frequency + * \param vco_freq_out On success, the voltage controller oscillator frequeucny to be used by the SYS PLL + * \param post_div1_out On success, The first post divider for the SYS PLL + * \param post_div2_out On success, The second post divider for the SYS PLL. + * @return true if the frequency is possible and the output parameters have been written. + */ +static bool check_sys_clock_khz(uint32_t freq_khz, uint* vco_out, uint* postdiv1_out, uint* postdiv_out) +{ + uint crystal_freq_khz = clock_get_hz(clk_ref) / 1000; + for(uint fbdiv = 320; fbdiv >= 16; fbdiv--) { + uint vco = fbdiv * crystal_freq_khz; + if(vco < 400000 || vco > 1600000) { + continue; + } + for(uint postdiv1 = 7; postdiv1 >= 1; postdiv1--) { + for(uint postdiv2 = postdiv1; postdiv2 >= 1; postdiv2--) { + uint out = vco / (postdiv1 * postdiv2); + if(out == freq_khz && (vco % (postdiv1 * postdiv2)) == 0) { + *vco_out = vco * 1000; + *postdiv1_out = postdiv1; + *postdiv_out = postdiv2; + return true; + } + } + } + } + return false; +} + +// Fix the peripheral clocks but allow system (CPU) to be varied independently using PLL +void system_init_clocks() +{ + uint vco_freq, post_div1, post_div2; + check_sys_clock_khz(DEFAULT_CPU_FREQ / 1000U, &vco_freq, &post_div1, &post_div2); + + // Switch to stable system clock before enabling PLL + clock_configure(clk_sys, CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX, + CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB, 48 * MHZ, 48 * MHZ); + + pll_init(pll_sys, 1, vco_freq, post_div1, post_div2); + uint32_t freq = vco_freq / (post_div1 * post_div2); + + // CLK_REF = XOSC (12MHz) / 1 = 12MHz + clock_configure(clk_ref, CLOCKS_CLK_REF_CTRL_SRC_VALUE_XOSC_CLKSRC, + 0, // No aux mux + 12 * MHZ, 12 * MHZ); + + // CLK SYS = PLL SYS (125MHz) / 1 = 125MHz + clock_configure(clk_sys, CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX, + CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS, freq, freq); + + clock_configure(clk_peri, + 0, // Only AUX mux on ADC + CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB, 48 * MHZ, 48 * MHZ); + + // Initialise systick for use by esp_get_ccount() + exception_set_exclusive_handler(SYSTICK_EXCEPTION, systick_overflow_isr); + systick_hw->csr = (1 << M0PLUS_SYST_CSR_CLKSOURCE_LSB) // Processor CLK source + | M0PLUS_SYST_CSR_TICKINT_BITS // Enable overflow ISR + | M0PLUS_SYST_CSR_ENABLE_BITS; // ENABLE + systick_hw->rvr = M0PLUS_SYST_RVR_BITS; // Reload value when counter hits 0 +} + +bool system_update_cpu_freq(uint8_t mhz) +{ + uint vco_freq, post_div1, post_div2; + if(!check_sys_clock_khz(mhz * 1000U, &vco_freq, &post_div1, &post_div2)) { + return false; + } + + // Switch to stable system clock before messing with PLL + clock_configure(clk_sys, CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX, + CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB, 48 * MHZ, 48 * MHZ); + + pll_init(pll_sys, 1, vco_freq, post_div1, post_div2); + uint32_t freq = vco_freq / (post_div1 * post_div2); + + // CLK SYS = PLL SYS (125MHz) / 1 = 125MHz + clock_configure(clk_sys, CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX, + CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS, freq, freq); + return true; +} + +uint8_t system_get_cpu_freq(void) +{ + return clock_get_hz(clk_sys) / MHZ; +} diff --git a/Sming/Arch/Rp2040/Components/rp2040/src/esp_cplusplus.cpp b/Sming/Arch/Rp2040/Components/rp2040/src/esp_cplusplus.cpp new file mode 100644 index 0000000000..add05b64be --- /dev/null +++ b/Sming/Arch/Rp2040/Components/rp2040/src/esp_cplusplus.cpp @@ -0,0 +1,29 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * esp_cplusplus.cpp + * + ****/ + +#include +#include + +namespace std +{ +const nothrow_t nothrow; +} + +extern "C" void __cxa_pure_virtual(void) +{ + SYSTEM_ERROR("Bad pure_virtual_call"); + abort(); +} + +extern "C" void __cxa_deleted_virtual(void) +{ + SYSTEM_ERROR("Bad deleted_virtual_call"); + abort(); +} diff --git a/Sming/Arch/Rp2040/Components/rp2040/src/functexcept.cpp b/Sming/Arch/Rp2040/Components/rp2040/src/functexcept.cpp new file mode 100644 index 0000000000..7394848d03 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/rp2040/src/functexcept.cpp @@ -0,0 +1,93 @@ +// Function-Based Exception Support -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/functexcept.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{exception} + * + * This header provides support for -fno-exceptions. + */ + +// +// ISO C++ 14882: 19.1 Exception classes +// + +#include + +#define THROW_HANDLER(name, ...) \ + void WEAK_ATTR __throw_##name(__VA_ARGS__) \ + { \ + while(1) { \ + } \ + } + +namespace std +{ +// Helper for exception objects in +THROW_HANDLER(bad_exception, void) + +// Helper for exception objects in +THROW_HANDLER(bad_alloc, void) + +// Helper for exception objects in +THROW_HANDLER(bad_cast, void) + +THROW_HANDLER(bad_typeid, void) + +// Helpers for exception objects in +THROW_HANDLER(logic_error, const char*) + +THROW_HANDLER(domain_error, const char*) + +THROW_HANDLER(invalid_argument, const char*) + +THROW_HANDLER(length_error, const char*) + +THROW_HANDLER(out_of_range, const char*) + +THROW_HANDLER(out_of_range_fmt, const char*, ...) + +THROW_HANDLER(runtime_error, const char*) + +THROW_HANDLER(range_error, const char*) + +THROW_HANDLER(overflow_error, const char*) + +THROW_HANDLER(underflow_error, const char*) + +// Helpers for exception objects in +THROW_HANDLER(ios_failure, const char*) + +THROW_HANDLER(ios_failure, const char*, int) + +// Helpers for exception objects in +THROW_HANDLER(system_error, int) + +// Helpers for exception objects in +THROW_HANDLER(future_error, int) + +// Helpers for exception objects in +THROW_HANDLER(bad_function_call) + +} // namespace std diff --git a/Sming/Arch/Rp2040/Components/rp2040/src/include/esp_clk.h b/Sming/Arch/Rp2040/Components/rp2040/src/include/esp_clk.h new file mode 100644 index 0000000000..566119760a --- /dev/null +++ b/Sming/Arch/Rp2040/Components/rp2040/src/include/esp_clk.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +bool system_update_cpu_freq(uint8_t freq); + +uint8_t system_get_cpu_freq(void); + +uint32_t esp_get_ccount(); + +#ifdef __cplusplus +} +#endif diff --git a/Sming/Arch/Rp2040/Components/rp2040/src/include/esp_sleep.h b/Sming/Arch/Rp2040/Components/rp2040/src/include/esp_sleep.h new file mode 100644 index 0000000000..39d168354a --- /dev/null +++ b/Sming/Arch/Rp2040/Components/rp2040/src/include/esp_sleep.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum sleep_type { + NONE_SLEEP_T = 0, + LIGHT_SLEEP_T, + MODEM_SLEEP_T, +}; + +void system_deep_sleep(uint32_t time_in_us); +bool system_deep_sleep_set_option(uint8_t option); + +#ifdef __cplusplus +} +#endif diff --git a/Sming/Arch/Rp2040/Components/rp2040/src/include/esp_system.h b/Sming/Arch/Rp2040/Components/rp2040/src/include/esp_system.h new file mode 100644 index 0000000000..370ebb5d0c --- /dev/null +++ b/Sming/Arch/Rp2040/Components/rp2040/src/include/esp_system.h @@ -0,0 +1,49 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +uint32_t system_get_time(void); +void system_restart(void); + +uint32_t os_random(void); +int os_get_random(uint8_t* buf, size_t len); + +void system_soft_wdt_stop(void); +void system_soft_wdt_restart(void); +void system_soft_wdt_feed(void); + +enum rst_reason { + REASON_DEFAULT_RST, + REASON_WDT_RST, + REASON_EXCEPTION_RST, + REASON_SOFT_WDT_RST, + REASON_SOFT_RESTART, + REASON_DEEP_SLEEP_AWAKE, + REASON_EXT_SYS_RST, +}; + +struct rst_info { + uint32_t reason; + uint32_t exccause; + uint32_t epc1; + uint32_t epc2; + uint32_t epc3; + uint32_t excvaddr; + uint32_t depc; +}; + +struct rst_info* system_get_rst_info(void); + +void os_delay_us(uint32_t us); + +const char* system_get_sdk_version(void); + +uint32_t system_get_chip_id(void); + +#ifdef __cplusplus +} +#endif diff --git a/Sming/Arch/Rp2040/Components/rp2040/src/include/esp_systemapi.h b/Sming/Arch/Rp2040/Components/rp2040/src/include/esp_systemapi.h new file mode 100644 index 0000000000..b3b9dc7a59 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/rp2040/src/include/esp_systemapi.h @@ -0,0 +1,48 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * esp_systemapi.h + * + ****/ + +#pragma once + +// Default types +#include +#include + +#include +#include +#include +#include +#include +#include "esp_system.h" +#include + +#include "m_printf.h" +#include "debug_progmem.h" +#include "stringutil.h" + +#define SYSTEM_ERROR(fmt, ...) debug_e("ERROR: " fmt "\r\n", ##__VA_ARGS__) + +extern void ets_wdt_enable(void); +extern void ets_wdt_disable(void); +extern void wdt_feed(void); + + +/** @brief Disable interrupts + * @retval Current interrupt level + * @note Hardware timer is unaffected if operating in non-maskable mode + */ +uint32_t noInterrupts(); + +/** @brief Enable interrupts +*/ +void interrupts(); + +/** @brief Restore interrupts to level saved from previous noInterrupts() call + */ +void restoreInterrupts(uint32_t level); diff --git a/Sming/Arch/Rp2040/Components/rp2040/src/include/esp_tasks.h b/Sming/Arch/Rp2040/Components/rp2040/src/include/esp_tasks.h new file mode 100644 index 0000000000..a279b483d2 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/rp2040/src/include/esp_tasks.h @@ -0,0 +1,43 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint32_t os_signal_t; +typedef uint32_t os_param_t; + +typedef struct { + os_signal_t sig; + os_param_t par; +} os_event_t; + +typedef enum { + USER_TASK_PRIO_0, + USER_TASK_PRIO_1, + USER_TASK_PRIO_2, + USER_TASK_PRIO_MAX, +} os_task_priority_t; + +typedef void (*os_task_t)(os_event_t* e); + +bool system_os_task(os_task_t callback, os_task_priority_t prio, os_event_t* events, uint8_t qlen); +bool system_os_post(os_task_priority_t prio, os_signal_t sig, os_param_t par); + +#ifdef __cplusplus +} +#endif + +#ifdef DRIVER_CODE_INIT +// Setup default task queues +void system_init_tasks(); + +// Hook function to process task queues +void system_service_tasks(); + +typedef void (*system_task_callback_t)(os_param_t param); + +bool system_queue_callback(system_task_callback_t callback, os_param_t param); +#endif diff --git a/Sming/Arch/Rp2040/Components/rp2040/src/include/esp_tasks_ll.h b/Sming/Arch/Rp2040/Components/rp2040/src/include/esp_tasks_ll.h new file mode 100644 index 0000000000..2d7eac0a4f --- /dev/null +++ b/Sming/Arch/Rp2040/Components/rp2040/src/include/esp_tasks_ll.h @@ -0,0 +1,16 @@ +/* + * Used by drivers and system code + */ +#pragma once + +#include "esp_tasks.h" + +// Setup default task queues +void system_init_tasks(); + +// Hook function to process task queues +void system_service_tasks(); + +typedef void (*system_task_callback_t)(os_param_t param); + +bool system_queue_callback(system_task_callback_t callback, os_param_t param); diff --git a/Sming/Arch/Rp2040/Components/rp2040/src/random.cpp b/Sming/Arch/Rp2040/Components/rp2040/src/random.cpp new file mode 100644 index 0000000000..6b3b93e3b0 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/rp2040/src/random.cpp @@ -0,0 +1,26 @@ + +#include "include/esp_system.h" +#include + +uint32_t os_random(void) +{ + uint32_t res = 0; + for(unsigned i = 0; i < 32; ++i) { + res <<= 1; + res |= rosc_hw->randombit; + } + return res; +} + +int os_get_random(uint8_t* buf, size_t len) +{ + while(len-- != 0) { + uint8_t res = 0; + for(unsigned i = 0; i < 8; ++i) { + res <<= 1; + res |= rosc_hw->randombit; + } + *buf++ = res; + } + return 0; +} diff --git a/Sming/Arch/Rp2040/Components/rp2040/src/sleep.c b/Sming/Arch/Rp2040/Components/rp2040/src/sleep.c new file mode 100644 index 0000000000..6b6b38c998 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/rp2040/src/sleep.c @@ -0,0 +1,10 @@ +#include "include/esp_sleep.h" + +void system_deep_sleep(uint32_t time_in_us) +{ +} + +bool system_deep_sleep_set_option(uint8_t option) +{ + return false; +} diff --git a/Sming/Arch/Rp2040/Components/rp2040/src/startup.cpp b/Sming/Arch/Rp2040/Components/rp2040/src/startup.cpp new file mode 100644 index 0000000000..cf41746032 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/rp2040/src/startup.cpp @@ -0,0 +1,125 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * user_main.cpp + * + */ + +#include "Platform/System.h" +#include +#include +#include "include/esp_tasks_ll.h" +#include +#include +#include +#include + +extern void init(); +extern void hw_timer_init(); +extern void system_init_timers(); +extern void system_service_timers(); + +namespace +{ +#ifdef ENABLE_BOOTSEL +uint32_t last_bootsel_check; + +/* + * Read state of BOOTSEL switch on GPIO 1 (QSPI CS #0). + * + * https://github.com/raspberrypi/pico-examples/blob/master/picoboard/button/button.c + * + * TODO: Synchronise with second core if running code from flash. + */ +bool __noinline IRAM_ATTR get_bootsel_button() +{ + const unsigned CS_PIN_INDEX{1}; + + noInterrupts(); + + // Set chip select to Hi-Z + hw_write_masked(&ioqspi_hw->io[CS_PIN_INDEX].ctrl, GPIO_OVERRIDE_LOW << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB, + IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS); + + // Note we can't call into any sleep functions in flash right now + for(volatile int i = 0; i < 1000; ++i) { + // + } + + // Read input (low when BOOTSEL pressed) + bool button_state = !(sio_hw->gpio_hi_in & BIT(CS_PIN_INDEX)); + + // Re-enable chip select + hw_write_masked(&ioqspi_hw->io[CS_PIN_INDEX].ctrl, GPIO_OVERRIDE_NORMAL << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB, + IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS); + + interrupts(); + + return button_state; +} + +void check_bootsel() +{ + constexpr uint32_t sampleInterval{HW_TIMER2_CLK / 2}; + auto ticks = hw_timer2_read(); + auto elapsed = ticks - last_bootsel_check; + if(elapsed < sampleInterval) { + return; + } + last_bootsel_check = ticks; + + if(get_bootsel_button()) { + reset_usb_boot(BIT(PICO_DEFAULT_LED_PIN), 0); + } +} + +#endif // ENABLE_BOOTSEL + +} // namespace + +extern "C" int main(void) +{ + extern void system_init_clocks(void); + system_init_clocks(); + + system_soft_wdt_restart(); + + // Initialise hardware timers + hw_timer_init(); + + system_init_tasks(); + system_init_timers(); + + // Initialise UARTs to a known state + smg_uart_detach_all(); + + /* Note: System is a static class so it's safe to call initialize() before cpp_core_initialize() + * We need to do this so that class constructors can use the task queue or onReady() + */ + System.initialize(); + +#ifdef SMING_RELEASE + // disable all debug output for release builds + smg_uart_set_debug(UART_NO); +#endif + + // gdb_init(); + + Storage::initialize(); + + init(); // User code init + + while(true) { + system_soft_wdt_feed(); + system_service_tasks(); + system_service_timers(); +#ifdef ENABLE_BOOTSEL + check_bootsel(); +#endif + } + + return 0; +} diff --git a/Sming/Arch/Rp2040/Components/rp2040/src/system.cpp b/Sming/Arch/Rp2040/Components/rp2040/src/system.cpp new file mode 100644 index 0000000000..354027a31f --- /dev/null +++ b/Sming/Arch/Rp2040/Components/rp2040/src/system.cpp @@ -0,0 +1,98 @@ +#include "include/esp_system.h" +#include +#include +#include +#include +#include +#include + +namespace +{ +constexpr uint32_t WATCHDOG_PERIOD_MS{8000}; +constexpr uint32_t SYSTEM_RESTART_DELAY{250}; + +uint32_t savedIrqLevels[2]; + +}; // namespace + +void system_soft_wdt_stop() +{ + hw_clear_bits(&watchdog_hw->ctrl, WATCHDOG_CTRL_ENABLE_BITS); +} + +void system_soft_wdt_restart() +{ + constexpr uint32_t ticks = WATCHDOG_PERIOD_MS * 1000 * 2; + static_assert(ticks <= 0xffffff); + + watchdog_enable(WATCHDOG_PERIOD_MS, true); +} + +void system_soft_wdt_feed() +{ + watchdog_update(); +} + +void interrupts() +{ + restore_interrupts(savedIrqLevels[get_core_num()]); +} + +uint32_t noInterrupts() +{ + auto level = save_and_disable_interrupts(); + savedIrqLevels[get_core_num()] = level; + return level; +} + +void restoreInterrupts(uint32_t level) +{ + restore_interrupts(level); +} + +uint32_t system_get_time() +{ + return hw_timer2_read(); +} + +void system_restart() +{ + // Force a restart + watchdog_hw->ctrl = WATCHDOG_CTRL_TRIGGER_BITS; +} + +struct rst_info* system_get_rst_info() +{ + static struct rst_info info; + auto reason = watchdog_hw->reason; + if(reason & WATCHDOG_REASON_FORCE_BITS) { + info.reason = REASON_SOFT_RESTART; + } else if(reason != 0) { + info.reason = REASON_SOFT_WDT_RST; + } else { + info.reason = REASON_DEFAULT_RST; + } + return &info; +} + +void os_delay_us(uint32_t us) +{ + auto start = hw_timer2_read(); + while(hw_timer2_read() - start < us) { + // Wait + } +} + +const char* system_get_sdk_version() +{ + return "PICO_SDK_" PICO_SDK_VERSION_STRING; +} + +uint32_t system_get_chip_id() +{ + pico_unique_board_id_t id; + pico_get_unique_board_id(&id); + uint32_t res; + memcpy(&res, &id, sizeof(res)); + return res; +} diff --git a/Sming/Arch/Rp2040/Components/rp2040/src/tasks.cpp b/Sming/Arch/Rp2040/Components/rp2040/src/tasks.cpp new file mode 100644 index 0000000000..df1ddaa000 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/rp2040/src/tasks.cpp @@ -0,0 +1,110 @@ +#include "include/esp_tasks_ll.h" +#include +#include +#include + +class TaskQueue +{ +public: + TaskQueue(os_task_t callback, os_event_t* events, uint8_t length) + { + this->callback = callback; + this->events = events; + this->length = length; + read = count = 0; + } + + bool IRAM_ATTR post(os_signal_t sig, os_param_t par) + { + auto level = save_and_disable_interrupts(); + + bool full = (count == length); + if(!full) { + events[(read + count) % length] = os_event_t{sig, par}; + ++count; + } + + restore_interrupts(level); + return !full; + } + + void process() + { + // Don't service any newly queued events + for(unsigned n = count; n != 0; --n) { + auto evt = events[read]; + read = (read + 1) % length; + --count; + callback(&evt); + } + } + +private: + os_task_t callback; + os_event_t* events; + uint8_t read; + uint8_t count; + uint8_t length; +}; + +static TaskQueue* task_queues[USER_TASK_PRIO_MAX + 1]; + +const uint8_t SYSTEM_TASK_PRIO = USER_TASK_PRIO_MAX; + +bool system_os_task(os_task_t callback, os_task_priority_t prio, os_event_t* events, uint8_t qlen) +{ + if(prio >= USER_TASK_PRIO_MAX) { + debug_e("[TQ] Invalid priority %u", prio); + return false; + } + auto& queue = task_queues[prio]; + if(queue != nullptr) { + debug_e("[TQ] Queue %u already initialised", prio); + return false; + } + + queue = new TaskQueue(callback, events, qlen); + return queue != nullptr; +} + +bool IRAM_ATTR system_os_post(os_task_priority_t prio, os_signal_t sig, os_param_t par) +{ + if(prio >= USER_TASK_PRIO_MAX) { + return false; + } + auto& queue = task_queues[prio]; + if(queue == nullptr) { + return false; + } + + return task_queues[prio]->post(sig, par); +} + +void system_init_tasks() +{ + static os_event_t events[8]; + + auto systemTaskCallback = [](os_event_t* event) { + auto callback = system_task_callback_t(event->sig); + if(callback != nullptr) { + callback(event->par); + } + }; + + task_queues[SYSTEM_TASK_PRIO] = new TaskQueue(systemTaskCallback, events, ARRAY_SIZE(events)); +} + +void system_service_tasks() +{ + for(int prio = SYSTEM_TASK_PRIO; prio >= 0; --prio) { + auto queue = task_queues[prio]; + if(queue != nullptr) { + queue->process(); + } + } +} + +bool system_queue_callback(system_task_callback_t callback, uint32_t param) +{ + return task_queues[SYSTEM_TASK_PRIO]->post(os_signal_t(callback), param); +} diff --git a/Sming/Arch/Rp2040/Components/sming-arch/README.rst b/Sming/Arch/Rp2040/Components/sming-arch/README.rst new file mode 100644 index 0000000000..50e8ae1279 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/sming-arch/README.rst @@ -0,0 +1,5 @@ +Sming (Rp2040) +============== + +This Component builds a library containing architecture-specific code, and defines dependencies +for Sming to build for Raspberry Pi 2040 microcontroller-based boards. diff --git a/Sming/Arch/Rp2040/Components/sming-arch/component.mk b/Sming/Arch/Rp2040/Components/sming-arch/component.mk new file mode 100644 index 0000000000..95761ca116 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/sming-arch/component.mk @@ -0,0 +1,23 @@ +COMPONENT_SRCDIRS := \ + $(ARCH_CORE) $(call ListAllSubDirs,$(ARCH_CORE)) \ + $(ARCH_BASE)/Platform \ + $(ARCH_BASE)/Services/Profiling + +COMPONENT_INCDIRS := \ + $(ARCH_BASE) \ + $(ARCH_CORE) \ + $(ARCH_COMPONENTS) + +COMPONENT_DEPENDS := \ + libc \ + rp2040 \ + uf2 \ + driver \ + gdbstub \ + spi_flash + +# ELF and BIN files +DEBUG_VARS += TARGET_BIN +TARGET_OUT = $(BUILD_BASE)/$(APP_NAME).out +TARGET_BIN = $(FW_BASE)/$(APP_NAME).bin +TARGET_OUT_0 = $(TARGET_OUT) diff --git a/Sming/Arch/Rp2040/Components/spi_flash/README.rst b/Sming/Arch/Rp2040/Components/spi_flash/README.rst new file mode 100644 index 0000000000..193687eea2 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/spi_flash/README.rst @@ -0,0 +1,10 @@ +Rp2040 SPI Flash Support +======================== + +Provides functions for access to flash memory. + +.. toctree:: + :glob: + :maxdepth: 1 + + * diff --git a/Sming/Arch/Rp2040/Components/spi_flash/api.rst b/Sming/Arch/Rp2040/Components/spi_flash/api.rst new file mode 100644 index 0000000000..8034002df6 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/spi_flash/api.rst @@ -0,0 +1,6 @@ +API Documentation +================= + +.. doxygengroup:: spi_flash + :content-only: + :members: diff --git a/Sming/Arch/Rp2040/Components/spi_flash/component.mk b/Sming/Arch/Rp2040/Components/spi_flash/component.mk new file mode 100644 index 0000000000..d0e64b93f1 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/spi_flash/component.mk @@ -0,0 +1,2 @@ +COMPONENT_DEPENDS := rp2040 +COMPONENT_DOXYGEN_INPUT := include diff --git a/Sming/Arch/Rp2040/Components/spi_flash/flashmem.cpp b/Sming/Arch/Rp2040/Components/spi_flash/flashmem.cpp new file mode 100644 index 0000000000..641d1fde4d --- /dev/null +++ b/Sming/Arch/Rp2040/Components/spi_flash/flashmem.cpp @@ -0,0 +1,412 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * flashmem.cpp + * + ****/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define FLASHCMD_READ_SFDP 0x5a +#define FLASHCMD_READ_JEDEC_ID 0x9f + +// Buffers need to be word aligned for flash access +#define ATTR_ALIGNED __attribute__((aligned(4))) + +namespace +{ +/* + * To ensure memory alignment a temporary buffer is used by flashmem_read and flashmem_write functions. + * + * The buffer must be an integer multiple of INTERNAL_FLASH_WRITE_UNIT_SIZE. + */ +constexpr dma_channel_transfer_size dmaTransferSize{DMA_SIZE_32}; +constexpr size_t flashReadUnitSize{1 << dmaTransferSize}; +constexpr size_t flashBufferCount{FLASH_PAGE_SIZE / flashReadUnitSize}; + +// JEDEC flash ID read from chip +uint32_t flash_id; +// Size of flash chip read from device +uint32_t sfdp_flash_size_bytes; + +uint32_t sfdp_read_size() +{ + uint32_t hdr[4]; + flashmem_sfdp_read(0, hdr, sizeof(hdr)); + + // Check magic + constexpr uint32_t sfdp_magic{'S' | ('F' << 8) | ('D' << 16) | ('P' << 24)}; + if(sfdp_magic != hdr[0]) { + debug_e("[SFDP] Magic invalid: 0x%08x (expected 0x%08x)", hdr[0], sfdp_magic); + return 0; + } + + // Skip NPH -- we don't care about nonmandatory parameters. + // Check header byte for mandatory parameter table + // | ID | MinRev | MajRev | Length in words | ptr[2] | ptr[1] | ptr[0] | unused| + // ID must be 0 (JEDEC) for mandatory PTH + if((hdr[2] & 0xff) != 0) { + debug_e("[SFDP] PTH ID invalid"); + return 0; + } + + uint32_t param_table_ptr = hdr[3] & 0xffffffu; + uint32_t param[2]; + flashmem_sfdp_read(param_table_ptr, ¶m, sizeof(param)); + + // MSB set: array >= 2 Gbit, encoded as log2 of number of bits + auto array_size_word = param[1]; + if(array_size_word & BIT(31)) { + return 1UL << ((array_size_word & ~BIT(31)) - 3); + } + // MSB clear: array < 2 Gbit, encoded as direct bit count, minus 1 + return (array_size_word + 1) / 8; +} + +void initFlashInfo() +{ + if(flash_id != 0) { + return; + } + + // Read JEDEC ID: command, 3 data bytes (manf. ID, Memory Type ID, Capacity ID) + uint8_t buf[4] = {FLASHCMD_READ_JEDEC_ID}; + flash_do_cmd(buf, buf, 4); + flash_id = (buf[1] << 16) | (buf[2] << 8) | buf[3]; + + sfdp_flash_size_bytes = sfdp_read_size(); +} + +uint32_t writeAligned(const void* from, uint32_t toaddr, uint32_t size) +{ + auto flashaddr = XIP_BASE + toaddr; + if(!isFlashPtr(flashaddr)) { + debug_e("[FLSH] write toaddr not in flash 0x%08x", toaddr); + return 0; + } + + debug_d("[FLSH] write(%p, 0x%08x, 0x%08x)", from, toaddr, size); + + flash_range_program(toaddr, static_cast(from), size); + + return size; +} + +uint32_t readAligned(void* to, uint32_t fromaddr, uint32_t size) +{ + auto flashaddr = XIP_BASE + fromaddr; + if(!isFlashPtr(flashaddr)) { + debug_e("[FLSH] read fromaddr not in flash 0x%08x", fromaddr); + return 0; + } + + debug_d("[FLSH] read(%p, 0x%08x, 0x%08x)", to, fromaddr, size); + + auto transfer_count = size >> dmaTransferSize; + + /* + * https://github.com/raspberrypi/pico-examples/tree/master/flash/xip_stream + * + * The XIP has some internal hardware that can stream a linear access sequence to + * a DMAable FIFO, while the system is still doing random accesses on flash code + data. + */ + + /* + * Transfer started by writing nonzero value to stream_ctr. + * stream_ctr will count down as the transfer progresses. + * Can terminate early by writing 0 to stream_ctr. + * It's a good idea to drain the FIFO first! + */ + while(!(xip_ctrl_hw->stat & XIP_STAT_FIFO_EMPTY)) { + (void)xip_ctrl_hw->stream_fifo; + } + + xip_ctrl_hw->stream_addr = flashaddr; + xip_ctrl_hw->stream_ctr = transfer_count; + + /* + * Start DMA transfer from XIP stream FIFO to our buffer in memory. + * Use the auxiliary bus slave for the DMA<-FIFO accesses, to avoid stalling + * the DMA against general XIP traffic. + */ + constexpr unsigned dma_chan{0}; + dma_channel_config cfg = dma_channel_get_default_config(dma_chan); + channel_config_set_transfer_data_size(&cfg, dmaTransferSize); + channel_config_set_read_increment(&cfg, false); + channel_config_set_write_increment(&cfg, true); + channel_config_set_dreq(&cfg, DREQ_XIP_STREAM); + dma_channel_configure(dma_chan, &cfg, + to, // Write addr + reinterpret_cast(XIP_AUX_BASE), // Read addr + transfer_count, // Transfer count + true // Start immediately! + ); + + dma_channel_wait_for_finish_blocking(dma_chan); + + return size; +} + +} // namespace + +uint32_t flashmem_write(const void* from, uint32_t toaddr, uint32_t size) +{ + const uint32_t blksize = FLASH_PAGE_SIZE; + const uint32_t blkmask = FLASH_PAGE_SIZE - 1; + + if((toaddr & blkmask) == 0 && (size & blkmask) == 0) { + return writeAligned(from, toaddr, size); + } + + uint8_t tmpdata[FLASH_PAGE_SIZE]; + auto pfrom = static_cast(from); + uint32_t remain = size; + + // Align the start + uint32_t rest = toaddr & blkmask; + if(rest != 0) { + uint32_t addr_aligned = toaddr & ~blkmask; // this is the actual aligned address + + // Read existing unit and overlay with new data + if(readAligned(tmpdata, addr_aligned, blksize) != blksize) { + return 0; + } + + while(remain != 0 && rest < blksize) { + tmpdata[rest++] = *pfrom++; + --remain; + } + + // Write the unit + uint32_t written = writeAligned(tmpdata, addr_aligned, blksize); + if(written != blksize) { + return written; + } + + if(remain == 0) { + return size; + } + + toaddr = addr_aligned + blksize; + } + + // The start address is now a multiple of blksize + // Compute how many bytes we can write as multiples of blksize + rest = remain & blkmask; + remain &= ~blkmask; + // Program the blocks now + while(remain != 0) { + unsigned count = std::min(size_t(remain), sizeof(tmpdata)); + memcpy(tmpdata, pfrom, count); + uint32_t written = writeAligned(tmpdata, toaddr, count); + remain -= written; + if(written != count) { + return size - remain; + } + toaddr += count; + pfrom += count; + } + + // And the final part of a block if needed + if(rest != 0) { + if(readAligned(tmpdata, toaddr, blksize) != blksize) { + return size - remain; + } + for(unsigned i = 0; i < rest; ++i) { + tmpdata[i] = *pfrom++; + } + uint32_t written = writeAligned(tmpdata, toaddr, blksize); + remain -= written; + if(written != blksize) { + return size - remain; + } + } + + return size; +} + +uint32_t flashmem_read(void* to, uint32_t fromaddr, uint32_t size) +{ + if(IS_ALIGNED(to) && IS_ALIGNED(fromaddr) && IS_ALIGNED(size)) { + return readAligned(to, fromaddr, size); + } + + const uint32_t blksize = flashReadUnitSize; + const uint32_t blkmask = flashReadUnitSize - 1; + + ATTR_ALIGNED uint8_t tmpdata[flashBufferCount * blksize]; + auto pto = static_cast(to); + size_t remain = size; + + // Align the start + uint32_t rest = fromaddr & blkmask; + if(rest != 0) { + uint32_t addr_aligned = fromaddr & ~blkmask; // this is the actual aligned address + if(readAligned(tmpdata, addr_aligned, blksize) != blksize) { + return 0; + } + // memcpy(pto, &tmpdata[rest], std::min(blksize - rest, remain)) + while(remain != 0 && rest < blksize) { + *pto++ = tmpdata[rest++]; + --remain; + } + if(remain == 0) { + return size; + } + fromaddr = addr_aligned + blksize; + } + + // The start address is now a multiple of blksize + // Compute how many bytes we can read as multiples of blksize + rest = remain & blkmask; + remain &= ~blkmask; + // Read the blocks now + while(remain != 0) { + unsigned count = std::min(remain, sizeof(tmpdata)); + uint32_t read = readAligned(tmpdata, fromaddr, count); + memcpy(pto, tmpdata, read); + remain -= read; + if(read != count) { + return size - remain; + } + fromaddr += count; + pto += count; + } + + // And the final part of a block if needed + if(rest != 0) { + if(readAligned(tmpdata, fromaddr, blksize) != blksize) { + return size - remain; + } + for(unsigned i = 0; i < rest; ++i) { + *pto++ = tmpdata[i]; + } + } + + return size; +} + +bool flashmem_erase_sector(uint32_t sector_id) +{ + debug_d("flashmem_erase_sector(0x%08x)", sector_id); + flash_range_erase(sector_id * FLASH_SECTOR_SIZE, FLASH_SECTOR_SIZE); + return true; +} + +SPIFlashInfo flashmem_get_info() +{ + SPIFlashInfo info{}; + info.size = flashmem_get_size_type(); + + // Flash mode + uint32_t ctrlr0 = ssi_hw->ctrlr0; + auto ssi_frame_format = (ctrlr0 & SSI_CTRLR0_SPI_FRF_BITS) >> SSI_CTRLR0_SPI_FRF_LSB; + auto trans_type = (ctrlr0 & SSI_SPI_CTRLR0_TRANS_TYPE_BITS) >> SSI_SPI_CTRLR0_TRANS_TYPE_LSB; + + switch(ssi_frame_format) { + case SSI_CTRLR0_SPI_FRF_VALUE_DUAL: + info.mode = (trans_type == 0) ? MODE_DOUT : MODE_DIO; + break; + case SSI_CTRLR0_SPI_FRF_VALUE_QUAD: + info.mode = (trans_type == 0) ? MODE_QOUT : MODE_QIO; + break; + case SSI_CTRLR0_SPI_FRF_VALUE_STD: + default: + info.mode = MODE_SLOW_READ; + } + + return info; +} + +uint8_t flashmem_get_size_type() +{ + initFlashInfo(); + + switch(flashmem_get_size_bytes()) { + case 0x40000: + return SIZE_2MBIT; + case 0x80000: + return SIZE_4MBIT; + case 0x100000: + return SIZE_8MBIT; + case 0x200000: + return SIZE_16MBIT; + case 0x400000: + return SIZE_32MBIT; + default: + return SIZE_1MBIT; + } +} + +uint32_t flashmem_get_size_bytes() +{ + initFlashInfo(); + + // Use SFDP data if available + if(sfdp_flash_size_bytes != 0) { + return sfdp_flash_size_bytes; + } + + /* + * Determine flash size from the JEDEC device ID. + * The lower byte generally contains the device size in bytes as a power of 2. + * However, this isn't a hard standard so may not work in all situations. + */ + auto size_bytes = flash_id & 0xff; + return 1U << size_bytes; +} + +uint16_t flashmem_get_size_sectors() +{ + return flashmem_get_size_bytes() / FLASH_SECTOR_SIZE; +} + +uint32_t flashmem_find_sector(uint32_t address, uint32_t* pstart, uint32_t* pend) +{ + // All the sectors in the flash have the same size, so just align the address + uint32_t sect_id = address / FLASH_SECTOR_SIZE; + + if(pstart != nullptr) { + *pstart = sect_id * FLASH_SECTOR_SIZE; + } + if(pend != nullptr) { + *pend = (sect_id + 1) * FLASH_SECTOR_SIZE - 1; + } + return sect_id; +} + +uint32_t flashmem_get_sector_of_address(uint32_t addr) +{ + return flashmem_find_sector(addr, NULL, NULL); +} + +uint32_t spi_flash_get_id(void) +{ + initFlashInfo(); + return flash_id; +} + +void flashmem_sfdp_read(uint32_t addr, void* buffer, size_t count) +{ + size_t buflen = 5 + count; + uint8_t buf[buflen] = { + FLASHCMD_READ_SFDP, + uint8_t(addr >> 16), + uint8_t(addr >> 8), + uint8_t(addr & 0xff), + 0, // dummy + }; + + flash_do_cmd(buf, buf, buflen); + memcpy(buffer, &buf[5], count); +} diff --git a/Sming/Arch/Rp2040/Components/spi_flash/include/esp_spi_flash.h b/Sming/Arch/Rp2040/Components/spi_flash/include/esp_spi_flash.h new file mode 100644 index 0000000000..73640e8625 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/spi_flash/include/esp_spi_flash.h @@ -0,0 +1,176 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * Based on NodeMCU platform_flash + * https://github.com/nodemcu/nodemcu-firmware + * + ****/ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#define SPI_FLASH_SEC_SIZE 4096 + +/** + * @defgroup flash Flash Memory Support + * @defgroup spi_flash SPI Flash API + * @ingroup flash + * @{ + */ + +#define FLASH_TOTAL_SEC_COUNT PICO_FLASH_SIZE_BYTES + +/* + * TODO: Revise layout to use custom 2nd-stage bootloader with partition + * table support. + */ +/// Number of flash sectors reserved for system parameters at start +#define SYS_PARAM_SEC_COUNT 4 +#define FLASH_WORK_SEC_COUNT (FLASH_TOTAL_SEC_COUNT - SYS_PARAM_SEC_COUNT) + +#define INTERNAL_FLASH_SECTOR_SIZE SPI_FLASH_SEC_SIZE +#define INTERNAL_FLASH_SIZE ((FLASH_WORK_SEC_COUNT)*INTERNAL_FLASH_SECTOR_SIZE) +#define INTERNAL_FLASH_START_ADDRESS FLASH_BASE + +typedef enum { + MODE_QIO = 0, + MODE_QOUT = 1, + MODE_DIO = 2, + MODE_DOUT = 15, + MODE_SLOW_READ = 0xFE, ///< Not supported + MODE_FAST_READ = 0xFF, ///< Not supported +} SPIFlashMode; + +typedef enum { + SPEED_40MHZ = 0, + SPEED_26MHZ = 1, + SPEED_20MHZ = 2, + SPEED_80MHZ = 15, +} SPIFlashSpeed; + +typedef enum { + SIZE_4MBIT = 0, + SIZE_2MBIT = 1, + SIZE_8MBIT = 2, + SIZE_16MBIT = 3, + SIZE_32MBIT = 4, + SIZE_1MBIT = 0xFF, ///< Not supported +} SPIFlashSize; + +/** @brief SPI Flash memory information block. + * Stored at the beginning of flash memory. + */ +typedef struct { + uint8_t mode : 8; ///< SPIFlashMode + uint8_t speed : 4; ///< SPIFlashSpeed + uint8_t size : 4; ///< SPIFlashSize +} SPIFlashInfo; + +/** @brief Obtain the flash memory address for a memory pointer + * @param memptr + * @retval uint32_t Offset from start of flash memory + * @note If memptr is not in valid flash memory it will return an offset which exceeds + * the internal flash memory size. + * @note The flash location is dependent on where rBoot has mapped the firmware. + */ +static inline uint32_t flashmem_get_address(const void* memptr) +{ + auto addr = uint32_t(memptr); + if(addr < XIP_BASE || addr >= XIP_NOALLOC_BASE) { + return 0; + } + return addr - XIP_BASE; +} + +/** @brief Write a block of data to flash + * @param from Buffer to obtain data from + * @param toaddr Flash location to start writing + * @param size Number of bytes to write + * @retval uint32_t Number of bytes written + * @note None of the parameters need to be aligned + */ +uint32_t flashmem_write(const void* from, uint32_t toaddr, uint32_t size); + +/** @brief Read a block of data from flash + * @param to Buffer to store data + * @param fromaddr Flash location to start reading + * @param size Number of bytes to read + * @retval uint32_t Number of bytes written + * @note none of the parameters need to be aligned + */ +uint32_t flashmem_read(void* to, uint32_t fromaddr, uint32_t size); + +/** @brief Erase a single flash sector + * @param sector_id the sector to erase + * @retval true on success + */ +bool flashmem_erase_sector(uint32_t sector_id); + +/** @brief Get flash memory information block + * @retval SPIFlashInfo Information block + */ +SPIFlashInfo flashmem_get_info(); + +/** @brief Returns a number indicating the size of flash memory chip + * @retval uint8_t See SpiFlashInfo.size field for possible values + */ +uint8_t flashmem_get_size_type(); + +/** @brief get the total flash memory size + * @retval uint32_t Size in bytes + */ +uint32_t flashmem_get_size_bytes(); + +/** @brief Get the total number of flash sectors + * @retval uint16_t Sector count + */ +uint16_t flashmem_get_size_sectors(); + +/** @brief Helper function: find the flash sector in which an address resides + * @param address + * @param pstart OUT/OPTIONAL: Start of sector containing the given address + * @param pend OUT/OPTIONAL: Last address in sector + * @retval uint32_t Sector number for the given address + * @note Optional parameters may be null + */ +uint32_t flashmem_find_sector(uint32_t address, uint32_t* pstart, uint32_t* pend); + +/** @brief Get sector number containing the given address + * @param addr + * @retval uint32_t sector number + */ +uint32_t flashmem_get_sector_of_address(uint32_t addr); + +/* + * @brief Returns the address of the first free block on flash + * @retval uint32_t The actual address on flash + */ +uint32_t flashmem_get_first_free_block_address(); + +/* + * @brief Get unique 32-bit flash identification code + */ +uint32_t spi_flash_get_id(void); + +/* + * @brief Read flash SFDP device information (standard for Serial Flash Discoverable Parameters) + * @param addr First memory location to read + * @param buffer Buffer for data + * @param count Number of bytes to read + */ +void flashmem_sfdp_read(uint32_t addr, void* buffer, size_t count); + +/** @} */ + +#ifdef __cplusplus +} +#endif diff --git a/Sming/Arch/Rp2040/Components/spi_flash/include/iram_precache.h b/Sming/Arch/Rp2040/Components/spi_flash/include/iram_precache.h new file mode 100644 index 0000000000..a18771a3d6 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/spi_flash/include/iram_precache.h @@ -0,0 +1,17 @@ +/* + * Dummy stub. RP2040 has tons of RAM. +*/ + +#pragma once + +/** + * @defgroup iram_precache IRAM Precache Support + * @ingroup flash + * @{ + */ + +#define IRAM_PRECACHE_ATTR +#define IRAM_PRECACHE_START(tag) +#define IRAM_PRECACHE_END(tag) + +/** @} */ diff --git a/Sming/Arch/Rp2040/Components/uf2/LICENSE.txt b/Sming/Arch/Rp2040/Components/uf2/LICENSE.txt new file mode 100644 index 0000000000..d3e3605f81 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/uf2/LICENSE.txt @@ -0,0 +1,25 @@ +Microsoft UF2 + +The MIT License (MIT) + +Copyright (c) Microsoft Corporation + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Sming/Arch/Rp2040/Components/uf2/README.rst b/Sming/Arch/Rp2040/Components/uf2/README.rst new file mode 100644 index 0000000000..8c68b68e8e --- /dev/null +++ b/Sming/Arch/Rp2040/Components/uf2/README.rst @@ -0,0 +1,18 @@ +UF2 Support +=========== + +Provides support for converting binary code into UF2 format for uploading to RP2040 devices. + +.. toctree:: + :glob: + :maxdepth: 1 + + * + + +Configuration variables +----------------------- + +.. envvar:: UF2CONV_PY + + Path to the ``uf2conv`` utility should you wish to run it manually. diff --git a/Sming/Arch/Rp2040/Components/uf2/component.mk b/Sming/Arch/Rp2040/Components/uf2/component.mk new file mode 100644 index 0000000000..a2b36926e0 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/uf2/component.mk @@ -0,0 +1,63 @@ +COMPONENT_LIBNAME := + +COMPONENT_DOCFILES := \ + uf2.md \ + uf2conv.md + +# Path to python utility for manipulating files and uploading to target +DEBUG_VARS += UF2CONV_PY +UF2CONV_PY := $(COMPONENT_PATH)/uf2conv.py + + +# Invoke uf2conf utility +# $1 -> Parameters +ifdef WSL_ROOT +Uf2Conv = powershell.exe -Command "$(PYTHON) $(UF2CONV_PY) $(if $V,--verbose) $1" +else +Uf2Conv = $(PYTHON) $(UF2CONV_PY) $(if $V,--verbose) $1 +endif + + +# Read flash manufacturer ID and determine actual size +define ReadFlashID + $(info Reading Flash ID) + $(call Uf2Conv,--list --verbose) +endef + +# Write file contents to Flash +# $1 -> List of `Offset=File` chunks +define WriteFlash + $(if $1,\ + $(info WriteFlash $1) \ + $(call Uf2Conv,--upload $1 --output $(OUT_BASE)/flash.uf2) + ) +endef + +# Verify flash against file contents +# $1 -> List of `Offset=File` chunks +define VerifyFlash + $(if $1,\ + $(info VerifyFlash $1) + $(info ** NOT IMPLEMENTED **) + ) +endef + +# Read flash memory into file +# $1 -> `Offset,Size` chunk +# $2 -> Output filename +define ReadFlash + $(info ReadFlash $1,$2) + $(info ** NOT IMPLEMENTED **) +endef + +# Erase a region of Flash +# $1 -> Offset,Size +define EraseFlashRegion + $(info EraseFlashRegion $1) + $(info ** NOT IMPLEMENTED **) +endef + +# Erase flash memory contents +define EraseFlash + $(info ** NOT IMPLEMENTED **) +endef diff --git a/Sming/Arch/Rp2040/Components/uf2/uf2.h b/Sming/Arch/Rp2040/Components/uf2/uf2.h new file mode 100644 index 0000000000..04e7725379 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/uf2/uf2.h @@ -0,0 +1,63 @@ +/** + +Microsoft UF2 + +The MIT License (MIT) + +Copyright (c) Microsoft Corporation + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ +#ifndef UF2FORMAT_H +#define UF2FORMAT_H 1 + +#include +#include + +// All entries are little endian. + +#define UF2_MAGIC_START0 0x0A324655UL // "UF2\n" +#define UF2_MAGIC_START1 0x9E5D5157UL // Randomly selected +#define UF2_MAGIC_END 0x0AB16F30UL // Ditto + +// If set, the block is "comment" and should not be flashed to the device +#define UF2_FLAG_NOFLASH 0x00000001 + +typedef struct { + // 32 byte header + uint32_t magicStart0; + uint32_t magicStart1; + uint32_t flags; + uint32_t targetAddr; + uint32_t payloadSize; + uint32_t blockNo; + uint32_t numBlocks; + uint32_t reserved; + + // raw data; + uint8_t data[476]; + + // store magic also at the end to limit damage from partial block reads + uint32_t magicEnd; +} UF2_Block; + +#endif diff --git a/Sming/Arch/Rp2040/Components/uf2/uf2.md b/Sming/Arch/Rp2040/Components/uf2/uf2.md new file mode 100644 index 0000000000..0333c08da4 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/uf2/uf2.md @@ -0,0 +1,356 @@ +# USB Flashing Format (UF2) + +UF2 is a file format, developed by Microsoft for [PXT](https://github.com/Microsoft/pxt) +(also known as [Microsoft MakeCode](https://makecode.com)), that is particularly suitable for +flashing microcontrollers over MSC (Mass Storage Class; aka removable flash drive). + +For a more friendly explanation, check out [this blog post](https://makecode.com/blog/one-chip-to-flash-them-all). +Also, take a look at the list of [implementations](#implementations) at the bottom of this document. + +## Overview + +The UF2 file consists of 512 byte blocks, each of which is self-contained and independent of others. +Each 512 byte block consists of (see below for details): + * magic numbers at the beginning and at the end + * address where the data should be flashed + * up to 476 bytes of data + +The data transfers over MSC always arrive in multiples of 512 bytes. +Together with the FAT file system structure, this means that blocks of the +UF2 file are always aligned with the MSC writes - the microcontroller +never gets a partial file. + +The magic numbers let the microcontroller distinguish an UF2 file block from +other data (eg., FAT table entry, or various book-keeping files stored by some +operating systems). When a UF2 block is recognized, it can be flashed +immediately (unless flash page size is more than 256 bytes; in that case a buffer +is needed). The actual handling of file format during writing is very simple +(~10 lines of C code in simplest version). + +## File format + +A UF2 file consists of 512 byte blocks. Each block starts with a 32 byte +header, followed by data, and a final magic number. +All fields, except for data, are 32 bit unsigned little endian integers. + +| Offset | Size | Value | +|--------|------|---------------------------------------------------| +| 0 | 4 | First magic number, `0x0A324655` (`"UF2\n"`) | +| 4 | 4 | Second magic number, `0x9E5D5157` | +| 8 | 4 | Flags | +| 12 | 4 | Address in flash where the data should be written | +| 16 | 4 | Number of bytes used in data (often 256) | +| 20 | 4 | Sequential block number; starts at 0 | +| 24 | 4 | Total number of blocks in file | +| 28 | 4 | File size or board family ID or zero | +| 32 | 476 | Data, padded with zeros | +| 508 | 4 | Final magic number, `0x0AB16F30` | + +The following C struct can be used: + +```C +struct UF2_Block { + // 32 byte header + uint32_t magicStart0; + uint32_t magicStart1; + uint32_t flags; + uint32_t targetAddr; + uint32_t payloadSize; + uint32_t blockNo; + uint32_t numBlocks; + uint32_t fileSize; // or familyID; + uint8_t data[476]; + uint32_t magicEnd; +} UF2_Block; +``` + +### Flags + +Currently, there are five flags defined: + + * `0x00000001` - **not main flash** - this block should be skipped when writing the + device flash; it can be used to store "comments" in the file, typically + embedded source code or debug info that does not fit on the device flash + + * `0x00001000` - **file container** - see below + + * `0x00002000` - **familyID present** - when set, the `fileSize/familyID` holds a value + identifying the board family (usually corresponds to an MCU) + + * `0x00004000` - **MD5 checksum present** - see below + + * `0x00008000` - **extension tags present** - see below + +### Family ID + +This field is optional, and should be set only when the corresponding +flag is set. It is recommended that new bootloaders require the field to +be set appropriately, and refuse to flash UF2 files without it. +If you're developing your own bootloader, and your +board family isn't listed here, pick a new family ID at random. It's good +to also send a PR here, so your family can be listed. + +If the `familyID` doesn't match, the bootloader should disregard the +entire block, including `blockNo` and `numBlocks` fields. +In particular, writing a full UF2 file with non-matching `familyID` +should not reset the board. +This also allows for several files with different `familyID` to be +simply concatenated together, and the whole resulting file to be copied +to the device with only one actually being written to flash. + +#### Picking numbers at random + +The reason to pick numbers at random is to minimize risk of collisions +in the wild. Do not pick random numbers by banging on keyboard, or by using +`0xdeadf00d`, `0x42424242` etc. A good way is to use the following +shell command: `printf "0x%04x%04x\n" $RANDOM $RANDOM` +Another good way is the link at the bottom of https://microsoft.github.io/uf2/patcher/ +This procedure was unfortunately not used for the SAMD51 and NRF52840 below. + +#### Family list + +The current master list of family IDs is maintained in a [JSON file](utils/uf2families.json). + +### Rationale + +The magic number at the end is meant to mitigate partial block writes. + +Second and final magic numbers were randomly selected, except for the last byte +of final magic number, which was forced to be `'\n'` (`0xA`). Together with the +first magic number being `"UF2\n"` this makes it easy to identify UF2 blocks in +a text editor. + +The header is padded to 32 bytes, as hex editors commonly use 16 or 32 bytes +as line length. This way, the data payload is aligned to line start. + +32 bit integers are used for all fields so that large flash sizes can be +supported in future, as well as for simplicity. Little endian is used, as most +microcontrollers are little endian. 8 bit microcontrollers can choose to just +use the first 16 bits of various header fields. + +The total number of blocks in the file and the sequential block number make it +easy for the bootloader to detect that all blocks have been transferred. It +requires one bit of memory per block (eg., on SAMD21G18A it's 128 bytes). +Alternatively, the bootloader might ignore that and just implement a reset +after say 1 second break in incoming UF2 blocks. + +### Payload sizes + +The number of data bytes is configurable and depends on the size of +the flash page (that is the smallest size that can be erased) on the +microcontroller. + + * if the page size is more than `476` bytes, the bootloader should support + any payload size, as it needs to buffer the entire page in memory anyway + + * if the page size is less than `476` bytes, the payload should be a multiple + of page size, so it can be written without buffering; the target address + should also be a multiple of page size + +In any event, payload size and target address should always be 4-byte aligned. + +Note that payload size of `256` is always correct, and makes it easy to convert +between flash addresses and UF2 file offsets. + +For example, on Atmel's SAMD21 chips the page size is `256` bytes, and this +also is the payload size. If the page size was `128` bytes, one could use +payload of `128*3`. Nordic nRF51 has page size of `1024` bytes, and thus +any payload size should be allowed. + +### Embedding sources + +Some IDEs will embed program sources in the UF2 file. This allows a UF2 files to be +loaded by the IDE and serve as a natural backup and transfer format. +This can be done in two ways: + + * using the "not main flash" flag + * using normal blocks that are flashed to the device + +If the bootloader can expose `CURRENT.UF2` file (see below) and there is enough +flash available, than the second option is more desirable, as it allows sharing +programs directly from the board. + +See https://makecode.com/source-embedding for more info. + +### Robustness + +The file format is designed specifically to deal with the following problems: + + * operating system (OS) writing blocks in different order than occurs in a file + * OS writing blocks multiple times + * OS writing data that is not UF2 blocks + * OS writing first/final part of a block, possibly for metadata detection or search indexing + +The only file system assumption we make is that blocks of file are aligned with +blocks on the hard drive. It's likely true of many file systems besides FAT. + +We also assume that USB MSC device reports its block size to be a multiple of `512` +bytes. In the wild these devices always almost report exactly `512`, and some +operating systems do not support other values. + +## Files exposed by bootloaders + +Bootloaders may expose virtual files in their MSC devices. These are +standardized here, so that flashing tools can automatically detect the +bootloaders. + + * `INFO_UF2.TXT` - contains information about the bootloader build and the board on which it is running + + * `INDEX.HTM` - redirects to a page that contains an IDE or other information + + * `CURRENT.UF2` - the contents of the entire flash of the device, starting at `0x00000000`, with `256` payload size; + thus, the size of this file will report as twice the size of flash + +Flashing tools can use the presence of `INFO_UF2.TXT` (in upper or lower case, +as FAT is case-insensitive) file as an indication that a given directory is +actually a connected UF2 board. The other files should not be used for +detection. + +Typical `INFO_UF2.TXT` file looks like this: + +``` +UF2 Bootloader v1.1.3 SFA +Model: Arduino Zero +Board-ID: SAMD21G18A-Zero-v0 +``` + +The `Board-ID` field is machine-readable and consists of a number of dash-separated tokens. +The first token is the CPU type, second is the board type, and third is the board revision. +More tokens can be also added. + +The bootloader should contain its info file as a static string somewhere in its code. +If possible, the last word of the bootloader code should point to this string. +This way, the info file can be found in the initial section of the `CURRENT.UF2` +file as well. Thus, a board type can be determined from the contents of `CURRENT.UF2`. +This is particularly useful with the source embedding (see above). + +## File containers + +It is also possible to use the UF2 format as a container for one or more +regular files (akin to a TAR file, or ZIP archive without compression). This +is useful when the embedded device being flashed sports a file system. + +The program to run may reside in one of the files, or in the main flash memory. + +In such a usage the `file container` flag is set on blocks, the field `fileSize` +holds the file size of the current file, and the field `targetAddr` holds the +offset in current file. + +The `not main flash` flag on blocks should be ignored when the `file container` is set. + +The file name is stored at `&data[payloadSize]` (ie., right after the actual payload) and +terminated with a `0x00` byte. The format of filename is dependent on the +bootloader (usually implemented as some sort of file system daemon). + +The bootloader will usually allow any size of the payload. + +The current files on device might be exposed as multiple UF2 files, instead of +a single `CURRENT.UF2`. They may reside in directories, however, due to UF2 general +design, it doesn't matter which directory the UF2 file is written to. + +Typical writing procedure is as follows: + + * validate UF2 magic numbers + * make sure that `targetAddr < fileSize` and that `fileSize` isn't out of reasonable range + * write `0x00` at `data[475]` to ensure NUL termination of file name + * read file name from `&data[payloadSize]`; perform any mapping on the file name + * create a directory where the file is to be written if it doesn't exist + * open the file for writing + * truncate the file to `fileSize` + * seek `targetAddr` + * write the payload (ie., `data[0 ... payloadSize - 1]`) + * close the file + +The fields `blockNo` and `numBlocks` refer to the entire UF2 file, not the current +file. + +## MD5 checksum + +When the `0x4000` flag is set, the last 24 bytes of `data[]` hold the following structure: + +| Offset | Size | Value | +|--------|------|---------------------------------------------------| +| 0 | 4 | Start address of region | +| 4 | 4 | Length of region in bytes | +| 8 | 16 | MD5 checksum in binary format | + +The flashing program should compute the MD5 sum of the specified region. +If the region checksum matches, flashing of the current block can be skipped. +Typically, many blocks in sequence will have the same region specified, +and can all be skipped, if the matching succeeded. +The position of the current block will typically be inside of the region. +The position and size of the region should be multiple of page erase size +(4k or 64k on typical SPI flash). + +This is currently only used on ESP32, which is also why MD5 checksum is used. + +## Extension tags + +When the `0x8000` flag is set, additional information can be appended right after +payload data (i.e., it starts at `32 + payloadSize`). +Every tag starts at 4 byte boundary. +The first byte of tag contains its total size in bytes (including the size byte +and type designation). +The next three bytes designate the type of tag (if you want to define custom +tags, pick them at random). +The last tag has size of `0` and type of `0`. + +Standard tag designations follow: + + * `0x9fc7bc` - version of firmware file - UTF8 semver string + + * `0x650d9d` - description of device for which the firmware file is destined (UTF8) + + * `0x0be9f7` - page size of target device (32 bit unsigned number) + + * `0xb46db0` - SHA-2 checksum of firmware (can be of various size) + + * `0xc8a729` - device type identifier - a refinement of `familyID` meant to identify a kind of device + (eg., a toaster with specific pinout and heating unit), not only MCU; 32 or 64 bit number; can be hash of `0x650d9d` + +For example, the following bytes encode firmware version `0.1.2` for device +named `ACME Toaster mk3` (line breaks added for clarity): + +``` +09 bc c7 9f 30 2e 31 2e 32 00 00 00 +14 9d 0d 65 41 43 4d 45 20 54 6f 61 73 74 65 72 20 6d 6b 33 +00 00 00 00 +``` + +Extension tags can, but don't have to, be repeated in all blocks. + +## Implementations + +### Bootloaders + + * [Microchip ATSAMD21 and ATSAMD51](https://github.com/Microsoft/uf2-samdx1) + * [Arduino UNO](https://github.com/mmoskal/uf2-uno) + * [STM32F103](https://github.com/mmoskal/uf2-stm32) + * [STM32F4](https://github.com/mmoskal/uf2-stm32f) + * [Nordic NRF52840](https://github.com/adafruit/Adafruit_nRF52840_Bootloader) + * [Linux (RPi Zero)](https://github.com/microsoft/uf2-linux) + * [Cypress FX2](https://github.com/whitequark/libfx2/tree/master/firmware/boot-uf2) + * [Tiny UF2](https://github.com/adafruit/tinyuf2) - Support ESP32-S2, iMXRT10xx, STM32F4 + * [RP2040 chip](https://www.raspberrypi.org/products/raspberry-pi-pico/) - native support in silicon + * [UF2-ChibiOS](https://github.com/striso/uf2-ChibiOS) - Supports STM32H7 + +There's an ongoing effort to implement UF2 in [Codal](https://github.com/lancaster-university/codal-core). + +### Editors + +* https://arcade.makecode.com +* https://makecode.adafruit.com +* https://makecode.seeedstudio.com +* https://maker.makecode.com + +### Libraries + +* https://www.npmjs.com/package/uf2 + +## License + +MIT + +## Code of Conduct + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/Sming/Arch/Rp2040/Components/uf2/uf2conv.md b/Sming/Arch/Rp2040/Components/uf2/uf2conv.md new file mode 100644 index 0000000000..052f9c1ec1 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/uf2/uf2conv.md @@ -0,0 +1,35 @@ +# uf2conv -- Packing and unpacking UF2 files + +## SYNOPSIS + +This tool is based on the code at https://github.com/Microsoft/uf2 +but has been modified for use with Sming and the RP2040: + + - Handles multiple binary inputs using addr=content format + - Locations specified as offsets, relative to base address + - Defaults are set for RP2040, but can be changed (family ID and base address) + - Content is padded to flash sector size (4096 bytes) - required by RP2040 bootrom + - Content is padded with 0xff (not 0) as this represents erased (unprogrammed) flash location + - Renamed 'deploy' as 'upload' and added progress indicator + - Support for hex files and 'C' arrays removed + +Run `uf2conv.py -h` for full list of options. + +## EXAMPLES + +### Pack binary file(s) to .uf2 + +Specify source using `offset=content` values: + +```uf2conv.py --convert 0x2000=cpx/firmware.bin 0x4000=cpx/partitions.bin --output cpx/upload.uf2``` + +Offsets are relative to the start of flash memory. + +### Unpack a .uf2 file + +```uf2conv.py current.uf2 --output current.bin``` + +Produces a list of `current-{addr}.bin` files for each chunk found in the .uf2 source file. +Without the `--output` option just displays a chunk summary. + +Use the `--verbose` option to display details for every block in the file. diff --git a/Sming/Arch/Rp2040/Components/uf2/uf2conv.py b/Sming/Arch/Rp2040/Components/uf2/uf2conv.py new file mode 100644 index 0000000000..e51f4b7437 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/uf2/uf2conv.py @@ -0,0 +1,400 @@ +#!/usr/bin/env python3 +# +# uf2conv.py +# +# Tool for packing and unpacking UF2 files +# + +import sys, struct, os, re, subprocess, argparse, json, time + +# Sizes +UF2_BLOCK_SIZE = 512 +UF2_PAYLOAD_SIZE = 256 +UF2_MAX_PAYLOAD_SIZE = 476 +UF2_HEADER_SIZE = 32 +UF2_FOOTER_SIZE = 4 +# Header +UF2_MAGIC_START0 = 0x0A324655 # "UF2\n" +UF2_MAGIC_START1 = 0x9E5D5157 # Randomly selected +# Footer +UF2_MAGIC_END = 0x0AB16F30 # Ditto +# Flag bits +UF2_FLAG_NOFLASH = 0x00000001 # Block is "comment", do not flash +UF2_FLAG_FILE_CONTAINER = 0x00001000 +UF2_FLAG_FAMILY_ID = 0x00002000 +UF2_FLAG_MD5_CHECKSUM = 0x00004000 +UF2_FLAG_EXTENSION_TAGS = 0x00008000 # Block padding contains extension tags + +# Info file +INFO_FILE = "/INFO_UF2.TXT" +INFO_MODEL = "Model" +INFO_BOARD_ID = "Board-ID" + +DEFAULT_FAMILY_ID = "RP2040" +DEFAULT_BASE_ADDR = 0x10000000 # Flash window start address + +DEFAULT_WAIT_SECS = 20 + +# Content must be padded to complete flash sectors. Bootloader messes up otherwise. +FLASH_SECTOR_SIZE = 4096 + +# Global variables +base_address = 0 +familyid = 0 +verbose = False + +def is_uf2(buf): + w = struct.unpack(" UF2_MAX_PAYLOAD_SIZE: + error("Invalid UF2 data size at 0x%08x" % offset) + newaddr = hd[3] + if chunk_offset is None or curraddr != newaddr: + chunk_offset = newaddr - base_address + output[chunk_offset] = bytes() + if (hd[2] & UF2_FLAG_FAMILY_ID) and currfamilyid is None: + currfamilyid = hd[7] + if curraddr is None or ((hd[2] & UF2_FLAG_FAMILY_ID) and hd[7] != currfamilyid): + currfamilyid = hd[7] + curraddr = newaddr + if familyid == 0x0 or ((hd[2] & UF2_FLAG_FAMILY_ID) and familyid == hd[7]): + output[chunk_offset] += block[UF2_HEADER_SIZE : UF2_HEADER_SIZE + datalen] + curraddr = newaddr + datalen + if hd[2] & UF2_FLAG_FAMILY_ID: + if hd[7] in families_found.keys(): + if families_found[hd[7]] > newaddr: + families_found[hd[7]] = newaddr + else: + families_found[hd[7]] = newaddr + if prev_flag is None: + prev_flag = hd[2] + if prev_flag != hd[2]: + all_flags_same = False + + print("----- UF2 File Header Info -----") + families = load_families() + for family_hex in families_found.keys(): + family_short_name = "" + for name, value in families.items(): + if value == family_hex: + family_short_name = name + print("Family ID is %s, hex value is 0x%08x" % (family_short_name, family_hex)) + print("Target Address is 0x%08x" % families_found[family_hex]) + if all_flags_same: + print("All block flag values consistent, 0x%04x" % hd[2]) + else: + print("Flags were not all the same") + print(" Offset Size") + for addr, content in output.items(): + print(" 0x%08x 0x%06x %u" % (addr, len(content), len(content))) + print("--------------------------------") + if len(families_found) > 1 and familyid == 0x0: + output = [] + + return output + + +def getSectorCount(length): + return (length + FLASH_SECTOR_SIZE - 1) // FLASH_SECTOR_SIZE + + +def convert_to_uf2(content_map): + global familyid + global base_address + + numblocks = 0 + for addr, content in content_map.items(): + numblocks += getSectorCount(len(content)) * FLASH_SECTOR_SIZE // UF2_PAYLOAD_SIZE + + outp = [] + blockno = 0 + for addr in sorted(content_map): + content = bytearray(content_map[addr]) + length = len(content) + padding = (getSectorCount(length) * FLASH_SECTOR_SIZE) - length + content.extend(bytearray([0xff] * padding)) + length = len(content) + addr += base_address + offset = 0 + while offset < length: + chunk = content[offset:offset + UF2_PAYLOAD_SIZE] + flags = 0x0 + if familyid: + flags |= 0x2000 + block = struct.pack(b"= 3 and words[1] == "2" and words[2] == "FAT": + drives.append(words[0]) + else: + rootpath = "/media" + if sys.platform == "darwin": + rootpath = "/Volumes" + elif sys.platform == "linux": + tmp = rootpath + "/" + os.environ["USER"] + if os.path.isdir(tmp): + rootpath = tmp + for d in os.listdir(rootpath): + drives.append(os.path.join(rootpath, d)) + + def has_info(d): + try: + return os.path.isfile(d + INFO_FILE) + except: + return False + + return list(filter(has_info, drives)) + + +def board_info(path): + infofile = path + INFO_FILE + if not os.path.isfile(infofile): + return None + with open(infofile, mode='r') as f: + lines = f.readlines() + if len(lines) < 2: + return None + res = {} + res['header'] = lines[0].strip() + for line in lines[1:]: + k, v = line.split(': ') + res[k] = v.strip() + return res + + +def list_drives(): + drives = get_drives() + if len(drives) == 0: + print("No drives found.") + return + for d in drives: + info = board_info(d) + print("'%s' %s (%s)" % (d, info[INFO_BOARD_ID], info[INFO_MODEL])) + if verbose: + for k, v in info.items(): + print(" %s = %s" % (k, v)) + + +def write_file(name, content): + with open(name, "wb") as f: + f.write(content) + print("Wrote '%s', %u bytes" % (name, len(content))) + + +def upload_file(drive, content): + """Gives progress indication.""" + blockSize = UF2_BLOCK_SIZE * 32 + blockCount = (len(content) + blockSize - 1 ) // blockSize + offset = 0 + lastpercent = -1 + + # https://stackoverflow.com/questions/3173320/text-progress-bar-in-the-console + def progress(): + nonlocal lastpercent + block = (offset + blockSize - 1) // blockSize + percent = round(100 * block / blockCount) + if percent == lastpercent: + return + lastpercent = percent + + prefix = 'Progress:' + suffix = 'Complete' + length = 50 + fill = '█' + filledLength = round(length * percent / 100) + bar = fill * filledLength + '-' * (length - filledLength) + print(f'\r{prefix} |{bar}| {percent}% {suffix}', end = "\r") + + with open(drive + "/NEW.UF2", "wb") as f: + while offset < len(content): + f.write(content[offset:offset+blockSize]) + offset += blockSize + progress() + + print() + + +def load_families(): + # The expectation is that the `uf2families.json` file is in the same + # directory as this script. Make a path that works using `__file__` + # which contains the full path to this script. + filename = "uf2families.json" + pathname = os.path.join(os.path.dirname(os.path.abspath(__file__)), filename) + with open(pathname) as f: + raw_families = json.load(f) + + families = {} + for family in raw_families: + families[family["short_name"]] = int(family["id"], 0) + + return families + + +def error(msg): + print(msg) + sys.exit(1) + + +def main(): + global familyid + global base_address + global verbose + + parser = argparse.ArgumentParser(description='Utility to manage UF2 file conversion and flashing.') + parser.add_argument('-b' , '--base', dest='base', type=str, + default="0x%08x" % DEFAULT_BASE_ADDR, + help='set base address for chunks (default: 0x%08x)' % DEFAULT_BASE_ADDR) + parser.add_argument('input', metavar='INPUT', type=str, nargs='*', + help='Name of UF2 file to read, or addr=content pairs for source binary data') + parser.add_argument('-o' , '--output', metavar="FILE", dest='output', type=str, + help='Write output to named file. Defaults to "flash.uf2" or "flash.bin" as appropriate.') + parser.add_argument('-d' , '--device', dest="device_path", + help='Select a device path to flash. If not specified will auto-detect.') + parser.add_argument('-w' , '--wait', dest="wait_secs", type=int, + default=DEFAULT_WAIT_SECS, + help='Time in seconds to wait for target device connection') + parser.add_argument('-l' , '--list', action='store_true', + help='List connected devices') + parser.add_argument('-c' , '--convert', action='store_true', + help='Convert list of "addr=file" binary source files into single .uf2 file') + parser.add_argument('-u' , '--upload', action='store_true', + help='Just flash, do not convert') + parser.add_argument('-f' , '--family', dest='family', type=str, + default=DEFAULT_FAMILY_ID, + help='Specify familyID number or name (default: %s)' % DEFAULT_FAMILY_ID) + parser.add_argument('-v', '--verbose', action='store_true', + help='enable verbose console messages') + args = parser.parse_args() + + base_address = int(args.base, 0) + verbose = args.verbose + + families = load_families() + familyid = families.get(args.family.upper()) + if familyid is None: + try: + familyid = int(args.family, 0) + except ValueError: + error("Family ID needs to be a number or one of: " + ", ".join(families.keys())) + + if args.list: + list_drives() + return + + if not args.input: + parser.print_usage() + error("Need input file(s)") + + source_map = None + output_map = None + uf2 = None + if len(args.input) == 1 and args.input[0].endswith('.uf2') and not args.convert: + filename = args.input[0] + with open(filename, mode='rb') as f: + inpbuf = f.read() + if not is_uf2(inpbuf): + error("Not a UF2 file: %s" % filename) + output_map = convert_from_uf2(inpbuf) + else: + source_map = {} + for e in args.input: + try: + addr, srcfile = e.split('=') + addr = int(addr, 0) + except ValueError: + error("Invalid parameter '%s', expecting addr=content pair" % e) + with open(srcfile, mode='rb') as f: + content = f.read() + source_map[addr] = content + uf2 = convert_to_uf2(source_map) + + if args.output: + if uf2 is not None: + write_file(args.output, uf2) + if output_map is not None: + base = os.path.splitext(args.output) + for addr, content in output_map.items(): + filename = "%s-0x%08x%s" % (base[0], addr, base[1]) + with open(filename, "wb") as f: + f.write(content) + print("Wrote '%s', %u bytes" % (filename, len(content))) + + if args.upload or args.device_path is not None: + d = None + info = None + for attempt in range(args.wait_secs, 0, -1): + print("Waiting for target device to enter boot mode... %u " % attempt, end='\r') + sys.stdout.flush() + d = args.device_path + if d is None: + drives = get_drives() + if len(drives) != 0: + d = drives[0] + if d is not None: + info = board_info(d) + if info is not None: + break + time.sleep(1) + + if info is None: + error("\nUF2 drive not found!") + + print("Flashing to '%s' (%s / %s)" % (d, info[INFO_MODEL], info[INFO_BOARD_ID])) + upload_file(d, uf2) + + +if __name__ == "__main__": + main() diff --git a/Sming/Arch/Rp2040/Components/uf2/uf2families.json b/Sming/Arch/Rp2040/Components/uf2/uf2families.json new file mode 100644 index 0000000000..42b5bbc2a2 --- /dev/null +++ b/Sming/Arch/Rp2040/Components/uf2/uf2families.json @@ -0,0 +1,172 @@ +[ + { + "id": "0x16573617", + "short_name": "ATMEGA32", + "description": "Microchip (Atmel) ATmega32" + }, + { + "id": "0x1851780a", + "short_name": "SAML21", + "description": "Microchip (Atmel) SAML21" + }, + { + "id": "0x1b57745f", + "short_name": "NRF52", + "description": "Nordic NRF52" + }, + { + "id": "0x1c5f21b0", + "short_name": "ESP32", + "description": "ESP32" + }, + { + "id": "0x1e1f432d", + "short_name": "STM32L1", + "description": "ST STM32L1xx" + }, + { + "id": "0x202e3a91", + "short_name": "STM32L0", + "description": "ST STM32L0xx" + }, + { + "id": "0x21460ff0", + "short_name": "STM32WL", + "description": "ST STM32WLxx" + }, + { + "id": "0x2abc77ec", + "short_name": "LPC55", + "description": "NXP LPC55xx" + }, + { + "id": "0x300f5633", + "short_name": "STM32G0", + "description": "ST STM32G0xx" + }, + { + "id": "0x31d228c6", + "short_name": "GD32F350", + "description": "GD32F350" + }, + { + "id": "0x04240bdf", + "short_name": "STM32L5", + "description": "ST STM32L5xx" + }, + { + "id": "0x4c71240a", + "short_name": "STM32G4", + "description": "ST STM32G4xx" + }, + { + "id": "0x4fb2d5bd", + "short_name": "MIMXRT10XX", + "description": "NXP i.MX RT10XX" + }, + { + "id": "0x53b80f00", + "short_name": "STM32F7", + "description": "ST STM32F7xx" + }, + { + "id": "0x55114460", + "short_name": "SAMD51", + "description": "Microchip (Atmel) SAMD51" + }, + { + "id": "0x57755a57", + "short_name": "STM32F4", + "description": "ST STM32F401" + }, + { + "id": "0x5a18069b", + "short_name": "FX2", + "description": "Cypress FX2" + }, + { + "id": "0x5d1a0a2e", + "short_name": "STM32F2", + "description": "ST STM32F2xx" + }, + { + "id": "0x5ee21072", + "short_name": "STM32F1", + "description": "ST STM32F103" + }, + { + "id": "0x647824b6", + "short_name": "STM32F0", + "description": "ST STM32F0xx" + }, + { + "id": "0x68ed2b88", + "short_name": "SAMD21", + "description": "Microchip (Atmel) SAMD21" + }, + { + "id": "0x6b846188", + "short_name": "STM32F3", + "description": "ST STM32F3xx" + }, + { + "id": "0x6d0922fa", + "short_name": "STM32F407", + "description": "ST STM32F407" + }, + { + "id": "0x6db66082", + "short_name": "STM32H7", + "description": "ST STM32H7xx" + }, + { + "id": "0x70d16653", + "short_name": "STM32WB", + "description": "ST STM32WBxx" + }, + { + "id": "0x7eab61ed", + "short_name": "ESP8266", + "description": "ESP8266" + }, + { + "id": "0x7f83e793", + "short_name": "KL32L2", + "description": "NXP KL32L2x" + }, + { + "id": "0x8fb060fe", + "short_name": "STM32F407VG", + "description": "ST STM32F407VG" + }, + { + "id": "0xada52840", + "short_name": "NRF52840", + "description": "Nordic NRF52840" + }, + { + "id": "0xbfdd4eee", + "short_name": "ESP32S2", + "description": "ESP32-S2" + }, + { + "id": "0xc47e5767", + "short_name": "ESP32S3", + "description": "ESP32-S3" + }, + { + "id": "0xd42ba06c", + "short_name": "ESP32C3", + "description": "ESP32-C3" + }, + { + "id": "0xe48bff56", + "short_name": "RP2040", + "description": "Raspberry Pi RP2040" + }, + { + "id": "0x00ff6919", + "short_name": "STM32L4", + "description": "ST STM32L4xx" + } +] \ No newline at end of file diff --git a/Sming/Arch/Rp2040/Core/.cs b/Sming/Arch/Rp2040/Core/.cs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Sming/Arch/Rp2040/Core/Digital.cpp b/Sming/Arch/Rp2040/Core/Digital.cpp new file mode 100644 index 0000000000..9bc6e998d1 --- /dev/null +++ b/Sming/Arch/Rp2040/Core/Digital.cpp @@ -0,0 +1,132 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http:// github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * Digital.cpp + * + * Based on https:// github.com/earlephilhower/arduino-pico/blob/master/cores/rp2040/wiring_digital.cpp + * + ****/ + +#include +#include +#include +#include + +namespace +{ +constexpr uint32_t PIN_COUNT = NUM_BANK0_GPIOS; + +#define CHECK_PIN(pin_number, ...) \ + if(pin_number >= PIN_COUNT) { \ + SYSTEM_ERROR("ERROR: Illegal pin in %s (%d)", __FUNCTION__, pin_number); \ + return __VA_ARGS__; \ + } + +} // namespace + +void pinMode(uint16_t pin, uint8_t mode) +{ + CHECK_PIN(pin) + + switch(mode) { + case INPUT: + gpio_init(pin); + gpio_set_dir(pin, GPIO_IN); + gpio_disable_pulls(pin); + break; + case INPUT_PULLUP: + gpio_init(pin); + gpio_set_dir(pin, GPIO_IN); + gpio_pull_up(pin); + gpio_put(pin, 0); + break; + case INPUT_PULLDOWN: + gpio_init(pin); + gpio_set_dir(pin, GPIO_IN); + gpio_pull_down(pin); + gpio_put(pin, 1); + break; + case OUTPUT: + gpio_init(pin); + gpio_set_dir(pin, GPIO_OUT); + gpio_disable_pulls(pin); + break; + default: + SYSTEM_ERROR("ERROR: Illegal pinMode mode (%d)", mode); + return; + } +} + +bool isInputPin(uint16_t pin) +{ + CHECK_PIN(pin, false) + + return !gpio_is_dir_out(pin); +} + +void digitalWrite(uint16_t pin, uint8_t val) +{ + CHECK_PIN(pin) + + if(gpio_is_pulled_down(pin)) { + gpio_set_dir(pin, val != LOW); + } else if(gpio_is_pulled_up(pin)) { + gpio_set_dir(pin, val != HIGH); + } else { + gpio_put(pin, val != LOW); + } +} + +uint8_t digitalRead(uint16_t pin) +{ + CHECK_PIN(pin, LOW) + return gpio_get(pin); +} + +void pullup(uint16_t pin) +{ + CHECK_PIN(pin) + gpio_pull_up(pin); +} + +void noPullup(uint16_t pin) +{ + CHECK_PIN(pin) + gpio_disable_pulls(pin); +} + +unsigned long pulseIn(uint16_t pin, uint8_t state, unsigned long timeout) +{ + CHECK_PIN(pin, 0) + + OneShotFastUs timeout_timer; + timeout_timer.reset(timeout); + + // Wait for deassert, if needed + while(gpio_get(pin) != !state) { + if(timeout_timer.expired()) { + return 0; + } + } + + // Wait for assert + while(gpio_get(pin) != !!state) { + if(timeout_timer.expired()) { + return 0; + } + } + + OneShotFastUs timer; + + // Wait for deassert + while(gpio_get(pin) != !state) { + if(timeout_timer.expired()) { + return 0; + } + } + + return timer.elapsedTicks(); +} diff --git a/Sming/Arch/Rp2040/Core/HardwarePWM.cpp.todo b/Sming/Arch/Rp2040/Core/HardwarePWM.cpp.todo new file mode 100644 index 0000000000..6def2d36fd --- /dev/null +++ b/Sming/Arch/Rp2040/Core/HardwarePWM.cpp.todo @@ -0,0 +1,136 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * HardwarePWM.cpp + * + * Original Author: https://github.com/hrsavla + * + * This HardwarePWM library enables Sming framework user to use ESP SDK PWM API + * Period of PWM is fixed to 1000us / Frequency = 1khz + * Duty at 100% = 22222. Duty at 0% = 0 + * You can use function setPeriod() to change frequency/period. + * Calculate the max duty as per the formulae give in ESP8266 SDK + * Max Duty = (Period * 1000) / 45 + * + * PWM can be generated on up to 8 pins (ie All pins except pin 16) + * Created on August 17, 2015, 2:27 PM + * + * See also ESP8266 Technical Reference, Chapter 12: + * http://espressif.com/sites/default/files/documentation/esp8266-technical_reference_en.pdf + * + */ + +#include +#include "ESP8266EX.h" + +#include + +#define PERIOD_TO_MAX_DUTY(x) (x * 25) + +HardwarePWM::HardwarePWM(uint8* pins, uint8 no_of_pins) : channel_count(no_of_pins) +{ + if(no_of_pins > 0) { + uint32 io_info[PWM_CHANNEL_NUM_MAX][3]; // pin information + uint32 pwm_duty_init[PWM_CHANNEL_NUM_MAX]; // pwm duty + for(uint8 i = 0; i < no_of_pins; i++) { + io_info[i][0] = EspDigitalPins[pins[i]].mux; + io_info[i][1] = EspDigitalPins[pins[i]].gpioFunc; + io_info[i][2] = EspDigitalPins[pins[i]].id; + pwm_duty_init[i] = 0; // Start with zero output + channels[i] = pins[i]; + } + const int initial_period = 1000; + pwm_init(initial_period, pwm_duty_init, no_of_pins, io_info); + update(); + maxduty = PERIOD_TO_MAX_DUTY(initial_period); // for period of 1000 + } +} + +HardwarePWM::~HardwarePWM() +{ + // There is no function in the SDK to stop PWM output, yet. +} + +/* Function Name: getChannel + * Description: This function is used to get channel number for given pin + * Parameters: pin - Esp8266 pin number + */ +uint8 HardwarePWM::getChannel(uint8 pin) +{ + for(uint8 i = 0; i < channel_count; i++) { + if(channels[i] == pin) { + //debugf("getChannel %d is %d", pin, i); + return i; + } + } + //debugf("getChannel: can't find pin %d", pin); + return PWM_BAD_CHANNEL; +} + +/* Function Name: getDutyChan + * Description: This function is used to get the duty cycle number for a given channel + * Parameters: chan -Esp8266 channel number + */ +uint32 HardwarePWM::getDutyChan(uint8 chan) +{ + if(chan == PWM_BAD_CHANNEL) { + return 0; + } else { + return pwm_get_duty(chan); + } +} + +/* Function Name: setDutyChan + * Description: This function is used to set the pwm duty cycle for a given channel. If parameter 'update' is false + * then you have to call update() later to update duties. + * Parameters: chan - channel number + * duty - duty cycle value + * update - update PWM output + */ +bool HardwarePWM::setDutyChan(uint8 chan, uint32 duty, bool update) +{ + if(chan == PWM_BAD_CHANNEL) { + return false; + } else if(duty <= maxduty) { + pwm_set_duty(duty, chan); + if(update) { + this->update(); + } + return true; + } else { + debugf("Duty cycle value too high for current period."); + return false; + } +} + +/* Function Name: getPeriod + * Description: This function is used to get Period of PWM. + * Period / frequency will remain same for all pins. + * + */ +uint32 HardwarePWM::getPeriod() +{ + return pwm_get_period(); +} + +/* Function Name: setPeriod + * Description: This function is used to set Period of PWM. + * Period / frequency will remain same for all pins. + */ +void HardwarePWM::setPeriod(uint32 period) +{ + maxduty = PERIOD_TO_MAX_DUTY(period); + pwm_set_period(period); + update(); +} + +/* Function Name: update + * Description: This function is used to actually update the PWM. + */ +void HardwarePWM::update() +{ + pwm_start(); +} diff --git a/Sming/Arch/Rp2040/Core/Interrupts.cpp b/Sming/Arch/Rp2040/Core/Interrupts.cpp new file mode 100644 index 0000000000..133c22a939 --- /dev/null +++ b/Sming/Arch/Rp2040/Core/Interrupts.cpp @@ -0,0 +1,130 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * Interrupts.cpp + * + ****/ + +#include +#include +#include +#include + +namespace +{ +constexpr unsigned PIN_COUNT = NUM_BANK0_GPIOS; + +struct Handler { + enum class Type { + none, + interrupt, + delegate, + }; + union { + InterruptCallback interrupt; + InterruptDelegate* delegate; + }; + Type type; + + void reset() + { + if(type == Type::delegate) { + delete delegate; + } + type = Type::none; + } + + void setInterrupt(InterruptCallback interrupt) + { + reset(); + this->interrupt = interrupt; + type = Type::interrupt; + } + + void setDelegate(InterruptDelegate delegate) + { + reset(); + this->delegate = new InterruptDelegate(delegate); + type = Type::delegate; + } +}; + +Handler handlers[PIN_COUNT]{}; +bool interruptHandlerAttached; + +#define CHECK_PIN(pin_number, ...) \ + if(pin_number >= PIN_COUNT) { \ + SYSTEM_ERROR("ERROR: Illegal pin in %s (%d)", __FUNCTION__, pin_number); \ + return __VA_ARGS__; \ + } + +void interruptDelegateCallback(uint32_t gpio) +{ + auto& handler = handlers[gpio]; + if(handler.type == Handler::Type::delegate) { + (*handler.delegate)(); + } +} + +void IRAM_ATTR interruptHandler(uint gpio, uint32_t events) +{ + auto& handler = handlers[gpio]; + if(handler.type == Handler::Type::interrupt) { + handler.interrupt(); + } else if(handler.type == Handler::Type::delegate) { + System.queueCallback(interruptDelegateCallback, gpio); + } +} + +} // namespace + +void attachInterrupt(uint8_t pin, InterruptCallback callback, GPIO_INT_TYPE type) +{ + CHECK_PIN(pin) + + auto& handler = handlers[pin]; + handler.setInterrupt(callback); + attachInterruptHandler(pin, type); +} + +void attachInterrupt(uint8_t pin, InterruptDelegate delegateFunction, GPIO_INT_TYPE type) +{ + CHECK_PIN(pin) + + auto& handler = handlers[pin]; + handler.setDelegate(delegateFunction); + attachInterruptHandler(pin, type); +} + +void attachInterruptHandler(uint8_t pin, GPIO_INT_TYPE type) +{ + CHECK_PIN(pin) + + pinMode(pin, INPUT); + + if(interruptHandlerAttached) { + gpio_set_irq_enabled(pin, type, true); + } else { + gpio_set_irq_enabled_with_callback(pin, type, true, interruptHandler); + interruptHandlerAttached = true; + } +} + +void detachInterrupt(uint8_t pin) +{ + CHECK_PIN(pin) + + gpio_set_irq_enabled(pin, 0, false); + handlers[pin].reset(); +} + +void interruptMode(uint8_t pin, GPIO_INT_TYPE type) +{ + CHECK_PIN(pin) + + pinMode(pin, INPUT); + gpio_set_irq_enabled(pin, type, type != 0); +} diff --git a/Sming/Arch/Rp2040/Core/SPI.cpp.todo b/Sming/Arch/Rp2040/Core/SPI.cpp.todo new file mode 100644 index 0000000000..a566605f3f --- /dev/null +++ b/Sming/Arch/Rp2040/Core/SPI.cpp.todo @@ -0,0 +1,345 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * SPI.cpp + * + * Created on: Mar 2, 2016 + * Author: harry-boe + * + * Some code is derived from: + * David Ogilvy (MetalPhreak) + * + ****/ + +#include "SPI.h" +#include +#include "espinc/eagle_soc.h" +#include "espinc/spi_register.h" + +// define the static singleton +SPIClass SPI; + +namespace +{ +// Used internally to calculate optimum SPI speed +struct SpiPreDiv { + unsigned freq; + unsigned prescale; + unsigned divisor; +}; + +/** + * @brief Wait until HSPI has finished any current transaction + */ +__forceinline void spi_wait() +{ + while(READ_PERI_REG(SPI_CMD(SPI_NO)) & SPI_USR) { + // + } +} + +/** + * @brief Initiate an HSPI user transaction + */ +__forceinline void spi_send() +{ + SET_PERI_REG_MASK(SPI_CMD(SPI_NO), SPI_USR); +} + +/** + * @brief Configure SPI mode parameters for clock edge and clock polarity. + * + * Private method used by SPISetings + * + * @param SPI_MODE0 .. SPI_MODE4 + * + * Mode Clock Polarity (CPOL) Clock Phase (CPHA) + * SPI_MODE0 0 0 + * SPI_MODE1 0 1 + * SPI_MODE2 1 0 + * SPI_MODE3 1 1 + */ +void spi_mode(uint8_t mode) +{ + uint8_t spi_cpha = mode & 0x0F; + uint8_t spi_cpol = mode & 0xF0; + +#ifdef SPI_DEBUG + debugf("SPIClass::spi_mode(mode %x) spi_cpha %X,spi_cpol %X)", mode, spi_cpha, spi_cpol); +#endif + + if(spi_cpha == spi_cpol) { + CLEAR_PERI_REG_MASK(SPI_USER(SPI_NO), SPI_CK_OUT_EDGE); + } else { + SET_PERI_REG_MASK(SPI_USER(SPI_NO), SPI_CK_OUT_EDGE); + } + + if(spi_cpol) { + SET_PERI_REG_MASK(SPI_PIN(SPI_NO), SPI_IDLE_EDGE); + } else { + CLEAR_PERI_REG_MASK(SPI_PIN(SPI_NO), SPI_IDLE_EDGE); + } +} + +/** + * @brief Setup the byte order for shifting data out of buffer + * + * Private method used by SPISetings + * + * @param MSBFIRST 1 + * Data is sent out starting with Bit31 and down to Bit0 + * LSBFIRST 0 + * Data is sent out starting with the lowest BYTE, from MSB to LSB + * 0xABCDEFGH would be sent as 0xGHEFCDAB + */ +void spi_byte_order(uint8_t byte_order) +{ +#ifdef SPI_DEBUG + debugf("SPIClass::spi_byte_order(byte_order %u)", byte_order); +#endif + + if(byte_order) { + SET_PERI_REG_MASK(SPI_USER(SPI_NO), SPI_WR_BYTE_ORDER); + SET_PERI_REG_MASK(SPI_USER(SPI_NO), SPI_RD_BYTE_ORDER); + } else { + CLEAR_PERI_REG_MASK(SPI_USER(SPI_NO), SPI_WR_BYTE_ORDER); + CLEAR_PERI_REG_MASK(SPI_USER(SPI_NO), SPI_RD_BYTE_ORDER); + } +} + +/** + * @brief Calculate the closest prescale value for a given frequency and clock-divider + * @param cpuFreq current CPU frequency, in Hz + * @param freq target SPI bus frequency, in Hz + * @param div divisor value to use + * @retval SpiPreDiv contains resulting frequency, prescaler and divisor values + */ +SpiPreDiv calculateSpeed(unsigned cpuFreq, unsigned freq, unsigned div) +{ + SpiPreDiv prediv; + unsigned pre = cpuFreq / (freq * div); + if(pre == 0) { + pre = 1; + } + unsigned n = pre * div; + while(true) { + prediv.freq = cpuFreq / n; + if(prediv.freq <= freq) { + break; + } + ++pre; + n += div; + } + prediv.prescale = pre; + prediv.divisor = div; + +#ifdef SPI_DEBUG + debugf("SPI calculateSpeed(uint freq %u, uint pre %u, uint div %u)", f, pre, div); +#endif + + return prediv; +} + +/** @brief Check speed settings and perform any pre-calculation required + * @param speed IN: requested bus frequency, OUT: Modified settings with prescale values + * @note + * The algorithm is testing with clock dividers 2,3 and 5 to find the best pre-divider + * The resulting clock frequency is not 100% accurate but delivers result within 5% + * + * It is guaranteed that the frequency will not exceed the given target + * + * Make sure that the ESP clock frequency is set before initializing the SPI bus. + * Changes on the ESP clock are not recognised once initialized + */ +void checkSpeed(SPISpeed& speed) +{ + unsigned cpuFreq = system_get_cpu_freq() * 1000000UL; +#ifdef SPI_DEBUG + debugf("SPIClass::calculateSpeed() -> current cpu frequency %u", cpuFreq); +#endif + + SpiPreDiv prediv; + + // If we're not running at max then need to determine appropriate prescale values + if(speed.frequency >= cpuFreq) { + // Use maximum speed + prediv.freq = cpuFreq; + prediv.divisor = 0; + speed.regVal = SPI_CLK_EQU_SYSCLK; + } else { + prediv = calculateSpeed(cpuFreq, speed.frequency, 2); + if(prediv.freq != speed.frequency) { + // Use whichever divisor gives the highest frequency + SpiPreDiv pd3 = calculateSpeed(cpuFreq, speed.frequency, 3); + SpiPreDiv pd5 = calculateSpeed(cpuFreq, speed.frequency, 5); + if(pd3.freq > prediv.freq || pd5.freq > prediv.freq) { + prediv = (pd3.freq > pd5.freq) ? pd3 : pd5; + } + } + + // We have prescale and divisor values, now get regVal so we don't need to do this every time prepare() is called + speed.regVal = (((prediv.prescale - 1) & SPI_CLKDIV_PRE) << SPI_CLKDIV_PRE_S) | + (((prediv.divisor - 1) & SPI_CLKCNT_N) << SPI_CLKCNT_N_S) | + (((prediv.divisor >> 1) & SPI_CLKCNT_H) << SPI_CLKCNT_H_S) | + ((0 & SPI_CLKCNT_L) << SPI_CLKCNT_L_S); + } + + //#ifdef SPI_DEBUG + debug_e("-> Using clock divider %u -> target freq %u -> result %u", prediv.divisor, speed.frequency, prediv.freq); + //#endif + + speed.frequency = prediv.freq; +} + +void spi_set_clock(SPISpeed& speed) +{ + // Clock register value is never 0, so indicates it hasn't been calculated + if(speed.regVal == 0) { + checkSpeed(speed); + } else { +#ifdef SPI_DEBUG + unsigned prescale = (speed.regVal >> SPI_CLKDIV_PRE_S) + 1; + unsigned divisor = (speed.regVal >> SPI_CLKCNT_N_S) + 1; + debugf("spi_set_clock(prescaler %u, divisor %u) for target %u", prescale, divisor, speed.frequency); +#endif + } + + WRITE_PERI_REG(SPI_CLOCK(SPI_NO), speed.regVal); +} + +} // namespace + +bool SPIClass::begin() +{ + CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX, BIT9); + + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2); // HSPIQ MISO == GPIO12 + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2); // HSPID MOSI == GPIO13 + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2); // CLK == GPIO14 + + checkSpeed(SPIDefaultSettings.speed); + prepare(SPIDefaultSettings); + + return true; +} + +uint32_t SPIClass::transfer32(uint32_t data, uint8_t bits) +{ + uint32_t regvalue = READ_PERI_REG(SPI_USER(SPI_NO)) & (SPI_WR_BYTE_ORDER | SPI_RD_BYTE_ORDER | SPI_CK_OUT_EDGE); + + spi_wait(); + + regvalue |= SPI_USR_MOSI | SPI_DOUTDIN | SPI_CK_I_EDGE; + WRITE_PERI_REG(SPI_USER(SPI_NO), regvalue); + + WRITE_PERI_REG(SPI_USER1(SPI_NO), (((bits - 1) & SPI_USR_MOSI_BITLEN) << SPI_USR_MOSI_BITLEN_S) | + (((bits - 1) & SPI_USR_MISO_BITLEN) << SPI_USR_MISO_BITLEN_S)); + + // copy data to W0 + if(READ_PERI_REG(SPI_USER(SPI_NO)) & SPI_WR_BYTE_ORDER) { + WRITE_PERI_REG(SPI_W0(SPI_NO), data << (32 - bits)); + } else { + WRITE_PERI_REG(SPI_W0(SPI_NO), data); + } + + spi_send(); + spi_wait(); + + auto res = READ_PERI_REG(SPI_W0(SPI_NO)); + if(READ_PERI_REG(SPI_USER(SPI_NO)) & SPI_RD_BYTE_ORDER) { + res >>= (32 - bits); + } + + return res; +} + +uint8_t SPIClass::read8() +{ + spi_wait(); + + WRITE_PERI_REG(SPI_W0(SPI_NO), 0x00); + + spi_send(); + spi_wait(); + + auto res = READ_PERI_REG(SPI_W0(SPI_NO)); + if(READ_PERI_REG(SPI_USER(SPI_NO)) & SPI_RD_BYTE_ORDER) { + res >>= 24; + } + + return res; +} + +void SPIClass::transfer(uint8_t* buffer, size_t numberBytes) +{ +#define BLOCKSIZE 64U // the max length of the ESP SPI_W0 registers + + unsigned bufIndx = 0; + + unsigned blocks = ((numberBytes - 1) / BLOCKSIZE) + 1; +#ifdef SPI_DEBUG + unsigned total = blocks; +#endif + + // loop number of blocks + while(blocks--) { + // get full BLOCKSIZE or number of remaining bytes + auto bufLength = std::min(numberBytes - bufIndx, BLOCKSIZE); + +#ifdef SPI_DEBUG + debugf("Write/Read Block %u total %u bytes", total - blocks, bufLength); +#endif + + // compute the number of bits to clock + auto num_bits = bufLength * 8; + + uint32_t regvalue = READ_PERI_REG(SPI_USER(SPI_NO)) & (SPI_WR_BYTE_ORDER | SPI_RD_BYTE_ORDER | SPI_CK_OUT_EDGE); + + spi_wait(); + + regvalue |= SPI_USR_MOSI | SPI_DOUTDIN | SPI_CK_I_EDGE; + WRITE_PERI_REG(SPI_USER(SPI_NO), regvalue); + + // setup bit length + WRITE_PERI_REG(SPI_USER1(SPI_NO), (((num_bits - 1) & SPI_USR_MOSI_BITLEN) << SPI_USR_MOSI_BITLEN_S) | + (((num_bits - 1) & SPI_USR_MISO_BITLEN) << SPI_USR_MISO_BITLEN_S)); + + // copy the registers starting from last index position + if(IS_ALIGNED(buffer)) { + memcpy((void*)SPI_W0(SPI_NO), &buffer[bufIndx], ALIGNUP4(bufLength)); + } else { + uint32_t wordBuffer[BLOCKSIZE / 4]; + memcpy(wordBuffer, &buffer[bufIndx], bufLength); + memcpy((void*)SPI_W0(SPI_NO), wordBuffer, ALIGNUP4(bufLength)); + } + + spi_send(); + spi_wait(); + + // copy the registers starting from last index position + memcpy(&buffer[bufIndx], (void*)SPI_W0(SPI_NO), bufLength); + + // increment bufIndex + bufIndx += bufLength; + } +} + +void SPIClass::prepare(SPISettings& settings) +{ +#ifdef SPI_DEBUG + debugf("SPIClass::prepare(SPISettings)"); + settings.print("settings"); +#endif + + // setup clock + spi_set_clock(settings.speed); + + // set byte order + spi_byte_order(settings.byteOrder); + + // set spi mode + spi_mode(settings.dataMode); +} diff --git a/Sming/Arch/Rp2040/Core/SPI.h b/Sming/Arch/Rp2040/Core/SPI.h new file mode 100644 index 0000000000..e6ad930196 --- /dev/null +++ b/Sming/Arch/Rp2040/Core/SPI.h @@ -0,0 +1,63 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * SPI.h + * + * Created on: Mar 2, 2016 + * Author: harry-boe + * + */ + +/** @defgroup hw_spi SPI Hardware support + * @brief Provides hardware SPI support + */ + +#pragma once + +#include "SPIBase.h" +#include "SPISettings.h" + +//#define SPI_DEBUG 1 + +// for compatibility when porting from Arduino +#define SPI_HAS_TRANSACTION 0 + +#define SPI_NO 1 + +/** + * @brief Hardware SPI object + * @addtogroup hw_spi + * @{ + */ + +class SPIClass : public SPIBase +{ +public: + SPIClass() + { + } + + SPIClass(const SPIClass&) = delete; + SPIClass& operator=(const SPIClass&) = delete; + + bool begin() override; + + void end() override + { + } + + uint8_t read8() override; + uint32_t transfer32(uint32_t val, uint8_t bits = 32) override; + + using SPIBase::transfer; + void transfer(uint8_t* buffer, size_t numberBytes) override; + +protected: + void prepare(SPISettings& settings) override; +}; + +/** @brief Global instance of SPI class */ +extern SPIClass SPI; diff --git a/Sming/Arch/Rp2040/Core/adc.cpp.todo b/Sming/Arch/Rp2040/Core/adc.cpp.todo new file mode 100644 index 0000000000..6ab92823ff --- /dev/null +++ b/Sming/Arch/Rp2040/Core/adc.cpp.todo @@ -0,0 +1,10 @@ +#include +#include + +uint16_t analogRead(uint16_t pin) +{ + if(pin == A0) + return system_adc_read(); + else + return -1; // Not supported +} diff --git a/Sming/Arch/Rp2040/Core/pins_arduino.h b/Sming/Arch/Rp2040/Core/pins_arduino.h new file mode 100644 index 0000000000..c5fe1e9421 --- /dev/null +++ b/Sming/Arch/Rp2040/Core/pins_arduino.h @@ -0,0 +1,30 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * pins_arduino.h + * + ****/ + +// File name selected for compatibility + +#pragma once + +const uint8_t A0{0}; // TODO main ADC input + +#define NOT_A_PIN 0 +#define NOT_A_PORT 0 +#define NOT_ON_TIMER 0 + +#define GPIO_REG_TYPE uint32_t + +// We use maximum compatibility to standard Arduino logic. + +#define digitalPinToPort(pin) (0) +#define digitalPinToBitMask(pin) (1UL << (pin)) +#define digitalPinToTimer(pin) (NOT_ON_TIMER) +#define portOutputRegister(port) ((volatile uint32_t*)&GPO) +#define portInputRegister(port) ((volatile uint32_t*)&GPI) +#define portModeRegister(port) ((volatile uint32_t*)&GPE) diff --git a/Sming/Arch/Rp2040/Core/twi_arch.h b/Sming/Arch/Rp2040/Core/twi_arch.h new file mode 100644 index 0000000000..25279b6919 --- /dev/null +++ b/Sming/Arch/Rp2040/Core/twi_arch.h @@ -0,0 +1,23 @@ +/* + * twi_arch.h - Platform-specific code + * + * See Sming/Core/si2c.cpp + * + */ + +#pragma once + +#include +#include + +//Enable SDA (becomes output and since GPO is 0 for the pin, it will pull the line low) +#define SDA_LOW() gpio_set_dir(twi_sda, true) +//Disable SDA (becomes input and since it has pullup it will go high) +#define SDA_HIGH() gpio_set_dir(twi_sda, false) +#define SDA_READ() gpio_get(twi_sda) +#define SCL_LOW() gpio_set_dir(twi_scl, true) +#define SCL_HIGH() gpio_set_dir(twi_scl, false) +#define SCL_READ() gpio_get(twi_scl) + +#define DEFAULT_SDA_PIN PICO_DEFAULT_I2C_SDA_PIN +#define DEFAULT_SCL_PIN PICO_DEFAULT_I2C_SCL_PIN diff --git a/Sming/Arch/Rp2040/Platform/.cs b/Sming/Arch/Rp2040/Platform/.cs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Sming/Arch/Rp2040/Platform/Clocks.h b/Sming/Arch/Rp2040/Platform/Clocks.h new file mode 100644 index 0000000000..fe2184cf81 --- /dev/null +++ b/Sming/Arch/Rp2040/Platform/Clocks.h @@ -0,0 +1,25 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * Clocks.h + * + ****/ + +#pragma once + +/** @ingroup system_clocks + * @{ + */ + +using OsTimerClock = Timer2Clock; + +using PolledTimerClock = Timer2Clock; + +using CpuCycleClockSlow = CpuCycleClock; +using CpuCycleClockNormal = CpuCycleClock; +using CpuCycleClockFast = CpuCycleClock; + +/** @} */ diff --git a/Sming/Arch/Rp2040/Platform/RTC.cpp b/Sming/Arch/Rp2040/Platform/RTC.cpp new file mode 100644 index 0000000000..6d211744e4 --- /dev/null +++ b/Sming/Arch/Rp2040/Platform/RTC.cpp @@ -0,0 +1,79 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * RTC.cpp + * + ****/ + +#include +#include +#include + +RtcClass RTC; + +#define NS_PER_SECOND 1000000000 + +namespace +{ +bool initialised; + +void checkInit() +{ + if(initialised) { + return; + } + rtc_init(); + initialised = true; +} + +} // namespace + +RtcClass::RtcClass() +{ + rtc_init(); +} + +uint64_t RtcClass::getRtcNanoseconds() +{ + return uint64_t(getRtcSeconds()) * NS_PER_SECOND; +} + +uint32_t RtcClass::getRtcSeconds() +{ + checkInit(); + + datetime_t t; + rtc_get_datetime(&t); + + DateTime dt; + dt.setTime(t.sec, t.min, t.hour, t.day, t.month, t.year); + + return time_t(dt); +} + +bool RtcClass::setRtcNanoseconds(uint64_t nanoseconds) +{ + return setRtcSeconds(nanoseconds / NS_PER_SECOND); +} + +bool RtcClass::setRtcSeconds(uint32_t seconds) +{ + checkInit(); + + DateTime dt{seconds}; + + datetime_t t = { + .year = int16_t(dt.Year), + .month = int8_t(dt.Month), + .day = int8_t(dt.Day), + .dotw = int8_t(dt.DayofWeek), + .hour = int8_t(dt.Hour), + .min = int8_t(dt.Minute), + .sec = int8_t(dt.Second), + }; + + return rtc_set_datetime(&t); +} diff --git a/Sming/Arch/Rp2040/README.rst b/Sming/Arch/Rp2040/README.rst new file mode 100644 index 0000000000..8bda1debd7 --- /dev/null +++ b/Sming/Arch/Rp2040/README.rst @@ -0,0 +1,224 @@ +Sming RP2040 Architecture +========================= + +.. highlight:: bash + +Support building Sming for the `Raspberry Pi RP2040 SOC +`__. + +Testing so far has been limited to the Rasperry Pi Pico, but there are lots of other boards available. +Configure this using the :envvar:`PICO_BOARD` setting. The default is ``pico``. +You can find the `full list here `__. + +Special mention to the arduino-pico project https://github.com/earlephilhower/arduino-pico. +Lots of helpful stuff in there! + +.. note:: + + This architecture should be considered experimental at present. + +Tested and working: + +- CPU frequency adjustment :cpp:func:`system_get_cpu_freq`, :cpp:func:`system_update_cpu_freq` +- Timers working: hardware, software and CPU cycle counter +- Hardware serial ports (UART driver) +- Task queue +- Flash memory routines +- :cpp:func:`os_random` and :cpp:func:`os_get_random` implemented using ring oscillator. + This is the best the hardware is capable of, but not crypto grade. +- Heap is standard newlib implementation, :cpp:func:`system_get_free_heap_size` provided. +- Software watchdog implemented, timeout is 8 seconds +- A disassembly and symbol file are generated for this architecture. +- SDK declares flash memory size in the board header files. + This is checked at compile time against the value declared in the partition table. +- Reset information :cpp:func:`system_get_rst_info` indicates watchdog or manual resets. + Exception information not yet implemented. +- System functions :cpp:func:`system_get_chip_id`, :cpp:func:`system_get_sdk_version`. +- Partitions and file systems (except SD cards and FAT) + +The following items are yet to be implemented: + +USB + Best to write a separate ``Sming-USB`` library (based on TinyUSB) to support the RP2040, ESP32-S2 & ESP32-S3 variants. + Needs some thought about good integration into the framework. + Arduino-Pico overrides ``HardwareSerial`` to support serial devices, we can do something similar. +SPI + Nice for messing around with displays. +Analogue I/O + Has 4 channels + temperature. +PWM + Hardware can drive up to 16 outputs and measure input frequency/duty cycle. +I2C + Has hardware support +RTC + Can wake from deep sleep but requires an external clock (e.g. 32kHz crystal) and appropriate API. + (Setting and reading the time is implemented.) +Low-power modes + Deep sleep / suspend / power-saving +Dual-core support + RP2040 is a dual-core processor! +Networking + Applications must currently be built with :envvar:`DISABLE_NETWORK` =1. + RP2040 doesn't have WiFi but a network stack via ethernet adapter would be useful. + USB offers the possibility of CDMA networking for mobile applications. +PIO (Programmable I/O) + A killer feature for the RP2040. + Uses range from simple glue logic to I2S, etc. +Crash/exception handling & serial debugging + RP2040 supports JTAG debugging but requires extra hardware. + Serial debugging is often enough and easier to set up. + Requires GDB stub plus implementing crash handler callbacks, etc. +Multi-boot / OTA updates. + If you run ``make map`` you'll see there is no bootloader! + It's part of the firmware image at present. + Adding RP2040 support to rBoot would probably be simplest. + + +Requirements +------------ + +These requirements are in addition to the standard Sming setup. + +The easiest way to get started is with the Sming installer - see :doc:`/getting-started/index`. + +Note: Windows is not currently included in the chocolatey repository. +The following instructions should help. + +Compiler/linker + The RP2040 contains two ARM Cortex-M0+ cores. Tools for all platforms can be downloaded from the + `ARM developer website `__. + + Unzip the archive to a suitable location (e.g. ``/opt/rp2040`` or ``c:\tools\rp2040``) and set :envvar:`PICO_TOOLCHAIN_PATH` accordingly. + + .. note:: + + At time of writing the Ubuntu repositories contain an older version of this toolchain. + It also does not contain GDB, but can be installed separately: + + sudo apt install gcc-arm-none-eabi gdb-multiarch + + To use gdb-multiarch you'll need to do this: + + make gdb GDB=gdb-multiarch + +Ninja + This is used to build the RP2040 SDK code: + + sudo apt install ninja-build + + It is available for other platforms at https://ninja-build.org/ + and consists of a single executable file. + The application should either be in the system path, or set :envvar:`NINJA` + to the full path of the executable file. + + If you have Sming working with the ESP32 then you'll already have it installed. + + +Setup and programming +--------------------- + +Serial support requires a 3.3v USB adapter connected to the appropriate pins: + +- UART0: TX = 0, RX = 1 +- UART1: TX = 4, RX = 5 + +To program your device, unplug the USB cable (i.e. remove power from the device) +then hold down the ``BOOTSEL`` button whilst plugging it back in again. + +You can then run: + + make flash + +as usual and the device will be programmed. + +Once Sming is running on the device, reprogramming is simpler and only requires pressing +the ``BOOTSEL`` button (no power cycle). + +If the firmware has crashed or stalled the watchdog timer should reboot the system after 8 seconds, +at which point BOOTSEL should be detected. So just hold the button down until this happens. + +If all else fails, go through the initial power-cycle process. + +This behaviour can be disabled using the :envvar:`ENABLE_BOOTSEL` setting. + + +Boot process +------------ + +Unlike the Espressif parts, the RP2040 is not programmed via the serial port, +but written to the device when configured as a Mass Storage device (removable flash drive). + +Data to be flashed must be in `UF2 format `__ and +sent as a single file. See :component-rp2040:`uf2`. + +Once the file has finished sending the RP2040 reboots itself into normal operating mode +(assuming BOOTSEL has been released). + +The RP2040 can also be programmed via JTAG debugging but this requires additional hardware and setup. + +.. note:: + + The RP2040 bootloader does not include support for reading flash memory via mass storage, + so commands such as ``make verifyflash`` won't work at present. + + +Source code +----------- + +The RP2040 is a very capable SOC, albeit without WiFi. +A massive advantage is that the platform is fully open-source. +Even the bootrom is published! + +Here's a summary of the various Github repositories the Raspberry Pi Foundation have made available: + +https://github.com/raspberrypi/pico-sdk + The core SDK for the RP2040 SOC. Sming includes this as a submodule. + +https://github.com/raspberrypi/picotool + This is a tool for inspecting RP2040 binaries, and interacting with RP2040 devices + when they are in BOOTSEL mode. + It does this by talking to a custom USB device implemented in the RP2040 bootrom. + + Getting this to build is a bit fiddly. + So far I've managed without it, but there is a ``picotool`` component in the framework + which can be used to try building it. + +https://github.com/raspberrypi/pico-bootrom + Contents of the RP2040 boot rom. Very handy to be able to see this. + +https://github.com/raspberrypi/pico-examples + Examples using the pico SDK directly. + +https://github.com/raspberrypi/picoprobe + An RP2040 board can be used as a low-cost JTAG adapter using this firmware. + Takes some setting up to use though. + See [Getting Started PDF](https://datasheets.raspberrypi.org/pico/getting-started-with-pico.pdf) + for details. + +https://github.com/raspberrypi/pico-extras + Some additional libraries which may or may not end up in the SDK. + +https://github.com/raspberrypi/pico-playground + Further examples using the pico-extras libraries. + + +Build variables +--------------- + +.. envvar:: PICO_TOOLCHAIN_PATH + + This contains the base directory for the toolchain used to build the framework. + Pre-compiled toolchains can be downloaded from the + `ARM Developer website `__. + + +Components +---------- + +.. toctree:: + :glob: + :maxdepth: 1 + :titlesonly: + + Components/sming-arch/index + Components/*/index diff --git a/Sming/Arch/Rp2040/Services/Profiling/TaskStat.cpp b/Sming/Arch/Rp2040/Services/Profiling/TaskStat.cpp new file mode 100644 index 0000000000..dcedcfcec3 --- /dev/null +++ b/Sming/Arch/Rp2040/Services/Profiling/TaskStat.cpp @@ -0,0 +1,32 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * TaskStat.cpp + * + */ + +#include + +namespace Profiling +{ +struct TaskStat::Info { +}; + +TaskStat::TaskStat(Print& out) : out(out) +{ +} + +TaskStat::~TaskStat() +{ +} + +bool TaskStat::update() +{ + out.println("[TaskStat] Not Implemented"); + return false; +} + +} // namespace Profiling diff --git a/Sming/Arch/Rp2040/Tools/ci/build.run.cmd b/Sming/Arch/Rp2040/Tools/ci/build.run.cmd new file mode 100644 index 0000000000..c2fa057237 --- /dev/null +++ b/Sming/Arch/Rp2040/Tools/ci/build.run.cmd @@ -0,0 +1,12 @@ +REM Rp2040 build.run.cmd + +set RP2040_PROJECTS=Basic_Blink Basic_Serial Basic_Storage + +%MAKE_PARALLEL% %RP2040_PROJECTS% DEBUG_VERBOSE_LEVEL=3 || goto :error + +goto :EOF + + +:error +echo Failed with error #%errorlevel%. +exit /b %errorlevel% diff --git a/Sming/Arch/Rp2040/Tools/ci/build.run.sh b/Sming/Arch/Rp2040/Tools/ci/build.run.sh new file mode 100644 index 0000000000..6838fa42d1 --- /dev/null +++ b/Sming/Arch/Rp2040/Tools/ci/build.run.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# +# Rp2040 build.run.sh + +$MAKE_PARALLEL samples DEBUG_VERBOSE_LEVEL=3 STRICT=1 diff --git a/Sming/Arch/Rp2040/Tools/ci/build.setup.cmd b/Sming/Arch/Rp2040/Tools/ci/build.setup.cmd new file mode 100644 index 0000000000..ae04d410c7 --- /dev/null +++ b/Sming/Arch/Rp2040/Tools/ci/build.setup.cmd @@ -0,0 +1 @@ +REM Rp2040 build.setup.cmd diff --git a/Sming/Arch/Rp2040/Tools/ci/build.setup.sh b/Sming/Arch/Rp2040/Tools/ci/build.setup.sh new file mode 100755 index 0000000000..f9f33cc4fd --- /dev/null +++ b/Sming/Arch/Rp2040/Tools/ci/build.setup.sh @@ -0,0 +1,3 @@ +#!/bin/bash +# +# Rp2040 build.setup.sh diff --git a/Sming/Arch/Rp2040/Tools/install.cmd b/Sming/Arch/Rp2040/Tools/install.cmd new file mode 100644 index 0000000000..7fd04c4f7e --- /dev/null +++ b/Sming/Arch/Rp2040/Tools/install.cmd @@ -0,0 +1,19 @@ +REM Rp2040 install.cmd + +if exist "%PICO_TOOLCHAIN_PATH%/arm-none-eabi" goto :already_got +set TOOLCHAIN_VERSION=10.3-2021.07 +set TOOLCHAIN_BASE_URL=https://developer.arm.com/-/media/Files/downloads/gnu-rm +set TOOLCHAIN_NAME=gcc-arm-none-eabi-%TOOLCHAIN_VERSION% +set TOOLCHAIN_FILE=%TOOLCHAIN_NAME%-win32.zip +curl -Lo tmp.zip %TOOLCHAIN_BASE_URL%/%TOOLCHAIN_VERSION%/%TOOLCHAIN_FILE% || goto :EOF +7z -o"%PICO_TOOLCHAIN_PATH%-tmp" x tmp.zip || goto :EOF +del tmp.zip +move "%PICO_TOOLCHAIN_PATH%-tmp/%TOOLCHAIN_NAME%" "%PICO_TOOLCHAIN_PATH%" +rmdir "%PICO_TOOLCHAIN_PATH%-tmp" +goto :EOF + + +:already_got +echo. +echo ** Skipping Rp2040 tools installation: '%PICO_TOOLCHAIN_PATH%' exists +echo. diff --git a/Sming/Arch/Rp2040/Tools/install.sh b/Sming/Arch/Rp2040/Tools/install.sh new file mode 100755 index 0000000000..24f6b27359 --- /dev/null +++ b/Sming/Arch/Rp2040/Tools/install.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# +# Rp2040 install.sh + +$PKG_INSTALL ninja-build + +if [ -d "$PICO_TOOLCHAIN_PATH/arm-none-eabi" ]; then + printf "\n\n** Skipping Rp2040 tools installation: '$PICO_TOOLCHAIN_PATH' exists\n\n" +else + TOOLCHAIN_VERSION="10.3-2021.07" + TOOLCHAIN_BASE_URL="https://developer.arm.com/-/media/Files/downloads/gnu-rm" + TOOLCHAIN_NAME="gcc-arm-none-eabi-$TOOLCHAIN_VERSION" + TOOLCHAIN_FILE="$TOOLCHAIN_NAME-x86_64-linux.tar.bz2" + TOOLCHAIN_URL="$TOOLCHAIN_BASE_URL/$TOOLCHAIN_VERSION/$TOOLCHAIN_FILE" + $WGET "$TOOLCHAIN_URL" -O "$DOWNLOADS/$TOOLCHAIN_FILE" + mkdir -p "$PICO_TOOLCHAIN_PATH" + tar -jxf "$DOWNLOADS/$TOOLCHAIN_FILE" -C "$PICO_TOOLCHAIN_PATH" --totals --transform='s|^/*||' + mv "$PICO_TOOLCHAIN_PATH/$TOOLCHAIN_NAME/"* "$PICO_TOOLCHAIN_PATH" +fi diff --git a/Sming/Arch/Rp2040/Tools/memanalyzer.py b/Sming/Arch/Rp2040/Tools/memanalyzer.py new file mode 100644 index 0000000000..be2e1d79ab --- /dev/null +++ b/Sming/Arch/Rp2040/Tools/memanalyzer.py @@ -0,0 +1,72 @@ +#!/bin/python +######################################################## +# +# Memory Analyzer +# Author: Slavey Karadzhov +# Based on https://github.com/Sermus/ESP8266_memory_analyzer +# +######################################################## +from collections import OrderedDict +import os.path +import shlex +import subprocess +import sys + +TOTAL_RAM = 264 * 1024 + +sections = OrderedDict([ + ("data", "Initialized Data (RAM)"), + ("bss", "Uninitialized Data (RAM)"), + ("flash_binary", "Uncached Code (SPI)") +]) + +if len(sys.argv) < 2: + print("Usage: \n\t%s%s " % sys.argv[0]) + sys.exit(1) + +objectDumpBin = sys.argv[1] +appOut = sys.argv[2] + +if not os.path.exists(appOut): + print("Cannot find application out file: %s" % appOut) + sys.exit(1) + + +command = "%s -t '%s' " % (sys.argv[1], sys.argv[2]) +response = subprocess.check_output(shlex.split(command)) +if isinstance(response, bytes): + response = response.decode('utf-8') +lines = response.split('\n') + +print("{0: >12}|{1: >30}|{2: >12}|{3: >12}|{4: >8}".format("Section", "Description", "Start (hex)", "End (hex)", "Used space")); +print("------------------------------------------------------------------------------"); + +usedRAM = 0 + +i = 0 +for (name, descr) in list(sections.items()): + sectionStartToken = " __%s_start" % name + sectionEndToken = " __%s_end" % name + sectionStart = -1; + sectionEnd = -1; + for line in lines: + if sectionStartToken in line: + data = line.split(' ') + sectionStart = int(data[0], 16) + + if sectionEndToken in line: + data = line.split(' ') + sectionEnd = int(data[0], 16) + + if sectionStart != -1 and sectionEnd != -1: + break + + sectionLength = sectionEnd - sectionStart + if i < 2: + usedRAM += sectionLength + + print("{0: >12}|{1: >30}|{2:12X}|{3:12X}|{4:8}".format(name, descr, sectionStart, sectionEnd, sectionLength)) + i += 1 + +print("Total Used RAM : %d" % usedRAM) +print("Free RAM : %d" % (TOTAL_RAM - usedRAM)) diff --git a/Sming/Arch/Rp2040/app.mk b/Sming/Arch/Rp2040/app.mk new file mode 100644 index 0000000000..c8c0c32f0f --- /dev/null +++ b/Sming/Arch/Rp2040/app.mk @@ -0,0 +1,38 @@ +### +# +# SMING Application Makefile for RP2040 architecture +# +### + +# linker flags used to generate the main object file +LDFLAGS += \ + -Wl,--build-id=none \ + --specs=nosys.specs \ + -mcpu=cortex-m0plus \ + -mthumb + +TARGET_DIS = $(TARGET_OUT:.out=.dis) +TARGET_SYM = $(TARGET_OUT:.out=.sym) + +.PHONY: application +application: $(TARGET_BIN) + +$(TARGET_OUT): $(COMPONENTS_AR) + $(info $(notdir $(PROJECT_DIR)): Linking $@) + $(Q) $(LD) $(addprefix -L,$(LIBDIRS)) $(LDFLAGS) -Wl,--start-group $(COMPONENTS_AR) $(addprefix -l,$(LIBS)) -Wl,--end-group -o $@ $(BOOTLOADER) + $(Q) $(MEMANALYZER) $@ > $(FW_MEMINFO) + $(Q) cat $(FW_MEMINFO) + +$(TARGET_BIN): $(TARGET_OUT) + @# Disassembly + $(Q) $(OBJDUMP) -h -C $< > $(TARGET_DIS) + $(Q) $(OBJDUMP) -d -S -C $< >> $(TARGET_DIS) + @# Symbols + @printf "Symbols by name\n" > $(TARGET_SYM) + $(Q) $(NM) -S -l -C $< >> $(TARGET_SYM) + @printf "\n\nSymbols by address\n" >> $(TARGET_SYM) + $(Q) $(NM) -S -l -n -C $< >> $(TARGET_SYM) + @printf "\n\nSymbols by size\n">> $(TARGET_SYM) + $(Q) $(NM) -S -l --size-sort -C $< >> $(TARGET_SYM) + @# Binary output + $(Q) $(OBJCOPY) -O binary $< $@ diff --git a/Sming/Arch/Rp2040/build.mk b/Sming/Arch/Rp2040/build.mk new file mode 100644 index 0000000000..29d774c29e --- /dev/null +++ b/Sming/Arch/Rp2040/build.mk @@ -0,0 +1,50 @@ +############## +# +# Rp2040 Architecture build environment +# +############## + +CPPFLAGS += \ + -DARCH_RP2040 \ + -march=armv6-m \ + -mcpu=cortex-m0plus \ + -mthumb + +CXXFLAGS += \ + -fno-threadsafe-statics \ + -fno-use-cxa-atexit + +CONFIG_TOOLPREFIX := arm-none-eabi + +# This will differ based on platform +DEBUG_VARS += PICO_TOOLCHAIN_PATH +ifdef PICO_TOOLCHAIN_PATH +export PICO_TOOLCHAIN_PATH := $(call FixPath,$(PICO_TOOLCHAIN_PATH)) +TOOLSPEC := $(PICO_TOOLCHAIN_PATH)/bin/$(CONFIG_TOOLPREFIX)- +ifeq (,$(wildcard $(PICO_TOOLCHAIN_PATH)/$(CONFIG_TOOLPREFIX))) +$(error PICO_TOOLCHAIN_PATH not set correctly: $(PICO_TOOLCHAIN_PATH)) +endif +else +PICO_TOOLCHAIN_PATH := $(shell which $(CONFIG_TOOLPREFIX)-gcc) +ifeq (,$(PICO_TOOLCHAIN_PATH)) +$(error Toolchain not found, maybe set PICO_TOOLCHAIN_PATH) +endif +TOOLSPEC := $(dir $(PICO_TOOLCHAIN_PATH))$(CONFIG_TOOLPREFIX)- +endif + +# select which tools to use as assembler, compiler, librarian and linker +AS := $(TOOLSPEC)gcc +CC := $(TOOLSPEC)gcc +CXX := $(TOOLSPEC)g++ +AR := $(TOOLSPEC)ar +LD := $(TOOLSPEC)gcc +NM := $(TOOLSPEC)nm +OBJCOPY := $(TOOLSPEC)objcopy +OBJDUMP := $(TOOLSPEC)objdump +GDB := $(TOOLSPEC)gdb + +CPPFLAGS += \ + -nostdlib + +# => Tools +MEMANALYZER = $(PYTHON) $(ARCH_TOOLS)/memanalyzer.py $(OBJDUMP)$(TOOL_EXT) diff --git a/Sming/Arch/Rp2040/rp2040-soc.json b/Sming/Arch/Rp2040/rp2040-soc.json new file mode 100644 index 0000000000..214f361e03 --- /dev/null +++ b/Sming/Arch/Rp2040/rp2040-soc.json @@ -0,0 +1,4 @@ +{ + "variant": "rp2040", + "name": "RP2040" +} \ No newline at end of file diff --git a/Sming/Arch/Rp2040/standard.hw b/Sming/Arch/Rp2040/standard.hw new file mode 100644 index 0000000000..d143cd3ba0 --- /dev/null +++ b/Sming/Arch/Rp2040/standard.hw @@ -0,0 +1,19 @@ +{ + "name": "Standard config", + "comment": "Should work with any Rp2040 variant", + "arch": "Rp2040", + "bootloader_size": 0, + "partition_table_offset": "self.devices[0].size - 0x1000", + "options": [ + "2m" + ], + "partitions": { + "rom0": { + "address": 0, + "size": "0xC0000", + "type": "app", + "subtype": "factory", + "filename": "$(TARGET_BIN)" + } + } +} \ No newline at end of file diff --git a/Sming/Components/.patches/http-parser.patch b/Sming/Components/.patches/http-parser.patch index fca10d9133..ce1eee4d48 100644 --- a/Sming/Components/.patches/http-parser.patch +++ b/Sming/Components/.patches/http-parser.patch @@ -40,17 +40,17 @@ index df88252..5935bcf 100644 /** PRIVATE **/ unsigned int type : 2; /* enum http_parser_type */ diff --git a/http_parser.c b/http_parser.c -index 95ff42f..2c7510b 100644 +index 95ff42f..beaf1f7 100644 --- a/http_parser.c +++ b/http_parser.c -@@ -19,12 +19,19 @@ - * IN THE SOFTWARE. +@@ -20,11 +20,19 @@ */ #include "http_parser.h" --#include + #include -#include -+#include - #include +-#include ++#include ++#include #include #include @@ -65,7 +65,7 @@ index 95ff42f..2c7510b 100644 static uint32_t max_header_size = HTTP_MAX_HEADER_SIZE; #ifndef ULLONG_MAX -@@ -186,7 +193,7 @@ static const char *method_strings[] = +@@ -186,7 +194,7 @@ static const char *method_strings[] = * | "/" | "[" | "]" | "?" | "=" * | "{" | "}" | SP | HT */ @@ -74,7 +74,7 @@ index 95ff42f..2c7510b 100644 /* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */ 0, 0, 0, 0, 0, 0, 0, 0, /* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */ -@@ -220,19 +227,10 @@ static const char tokens[256] = { +@@ -220,19 +228,10 @@ static const char tokens[256] = { /* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */ 'x', 'y', 'z', 0, '|', 0, '~', 0 }; @@ -98,7 +98,7 @@ index 95ff42f..2c7510b 100644 #if HTTP_PARSER_STRICT # define T(v) 0 #else -@@ -428,14 +426,14 @@ enum http_host_state +@@ -428,14 +427,14 @@ enum http_host_state (c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \ (c) == '$' || (c) == ',') @@ -115,7 +115,7 @@ index 95ff42f..2c7510b 100644 #define IS_URL_CHAR(c) \ (BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80)) #define IS_HOST_CHAR(c) \ -@@ -467,16 +465,6 @@ do { \ +@@ -467,16 +466,6 @@ do { \ #endif @@ -132,7 +132,7 @@ index 95ff42f..2c7510b 100644 int http_message_needs_eof(const http_parser *parser); /* Our URL parser. -@@ -758,7 +746,7 @@ reexecute: +@@ -758,7 +747,7 @@ reexecute: } parser->type = HTTP_REQUEST; @@ -141,7 +141,7 @@ index 95ff42f..2c7510b 100644 parser->index = 2; UPDATE_STATE(s_req_method); } -@@ -938,23 +926,23 @@ reexecute: +@@ -938,23 +927,23 @@ reexecute: parser->method = (enum http_method) 0; parser->index = 1; switch (ch) { @@ -180,7 +180,7 @@ index 95ff42f..2c7510b 100644 default: SET_ERRNO(HPE_INVALID_METHOD); goto error; -@@ -983,8 +971,8 @@ reexecute: +@@ -983,8 +972,8 @@ reexecute: switch (parser->method << 16 | parser->index << 8 | ch) { #define XX(meth, pos, ch, new_meth) \ @@ -191,7 +191,7 @@ index 95ff42f..2c7510b 100644 XX(POST, 1, 'U', PUT) XX(POST, 1, 'A', PATCH) -@@ -1024,7 +1012,7 @@ reexecute: +@@ -1024,7 +1013,7 @@ reexecute: if (ch == ' ') break; MARK(url); @@ -200,7 +200,7 @@ index 95ff42f..2c7510b 100644 UPDATE_STATE(s_req_server_start); } -@@ -1100,7 +1088,7 @@ reexecute: +@@ -1100,7 +1089,7 @@ reexecute: UPDATE_STATE(s_req_http_H); break; case 'I': @@ -209,7 +209,7 @@ index 95ff42f..2c7510b 100644 UPDATE_STATE(s_req_http_I); break; } -@@ -1826,7 +1814,7 @@ reexecute: +@@ -1826,7 +1815,7 @@ reexecute: parser->upgrade = (parser->type == HTTP_REQUEST || parser->status_code == 101); } else { @@ -218,7 +218,7 @@ index 95ff42f..2c7510b 100644 } /* Here we call the headers_complete callback. This is somewhat -@@ -1874,7 +1862,7 @@ reexecute: +@@ -1874,7 +1863,7 @@ reexecute: hasBody = parser->flags & F_CHUNKED || (parser->content_length > 0 && parser->content_length != ULLONG_MAX); @@ -227,7 +227,7 @@ index 95ff42f..2c7510b 100644 (parser->flags & F_SKIPBODY) || !hasBody)) { /* Exit, the rest of the message is in a different protocol. */ UPDATE_STATE(NEW_MESSAGE()); -@@ -1991,7 +1979,7 @@ reexecute: +@@ -1991,7 +1980,7 @@ reexecute: assert(nread == 1); assert(parser->flags & F_CHUNKED); @@ -236,7 +236,7 @@ index 95ff42f..2c7510b 100644 if (UNLIKELY(unhex_val == -1)) { SET_ERRNO(HPE_INVALID_CHUNK_SIZE); goto error; -@@ -2013,7 +2001,7 @@ reexecute: +@@ -2013,7 +2002,7 @@ reexecute: break; } @@ -245,7 +245,7 @@ index 95ff42f..2c7510b 100644 if (unhex_val == -1) { if (ch == ';' || ch == ' ') { -@@ -2207,7 +2195,7 @@ const char * +@@ -2207,7 +2196,7 @@ const char * http_status_str (enum http_status s) { switch (s) { @@ -254,7 +254,7 @@ index 95ff42f..2c7510b 100644 HTTP_STATUS_MAP(XX) #undef XX default: return ""; -@@ -2231,18 +2219,6 @@ http_parser_settings_init(http_parser_settings *settings) +@@ -2231,18 +2220,6 @@ http_parser_settings_init(http_parser_settings *settings) memset(settings, 0, sizeof(*settings)); } @@ -273,4 +273,3 @@ index 95ff42f..2c7510b 100644 static enum http_host_state http_parse_host_char(enum http_host_state s, const char ch) { switch(s) { - diff --git a/Sming/Components/FlashString b/Sming/Components/FlashString index a443c0bc49..b99a4c516b 160000 --- a/Sming/Components/FlashString +++ b/Sming/Components/FlashString @@ -1 +1 @@ -Subproject commit a443c0bc49fbc74300d1082e1270400d7f6a9010 +Subproject commit b99a4c516b8c7c1c0f38985c50db12ed11b177cb diff --git a/Sming/Components/Hosted-Lib/README.rst b/Sming/Components/Hosted-Lib/README.rst new file mode 100644 index 0000000000..73c552d7de --- /dev/null +++ b/Sming/Components/Hosted-Lib/README.rst @@ -0,0 +1,8 @@ +Hosted-Lib +========== + +This library provides replacement implementations for low-level operations which may then be +accessed via the selected RPC interface. + +See :component:`Hosted` for further details. + diff --git a/Sming/Components/Hosted-Lib/component.mk b/Sming/Components/Hosted-Lib/component.mk index f2466e7923..4bc530aa9f 100644 --- a/Sming/Components/Hosted-Lib/component.mk +++ b/Sming/Components/Hosted-Lib/component.mk @@ -1,2 +1,3 @@ +COMPONENT_SOC := host COMPONENT_SRCDIRS := $(COMPONENT_PATH)/src COMPONENT_DEPENDS := Hosted \ No newline at end of file diff --git a/Sming/Components/Hosted/Kconfig b/Sming/Components/Hosted/Kconfig new file mode 100644 index 0000000000..2c06ba5ced --- /dev/null +++ b/Sming/Components/Hosted/Kconfig @@ -0,0 +1,37 @@ +menu "Hosted" + choice + depends on SMING_ARCH="Host" + default ENABLE_HOSTED_NONE + prompt "Hosted transport mechanism" + config ENABLE_HOSTED_NONE + bool "None" + config ENABLE_HOSTED_TCP + bool "TCP" + config ENABLE_HOSTED_SERIAL + bool "Serial" + endchoice + + config ENABLE_HOSTED + string + default "" if ENABLE_HOSTED_NONE + default "tcp" if ENABLE_HOSTED_TCP + default "serial" if ENABLE_HOSTED_SERIAL + + if ENABLE_HOSTED="tcp" + config HOSTED_SERVER_IP + depends on ENABLE_HOSTED="tcp" + string "Remote RPC server IP address" + default "192.168.13.1" + endif + + if ENABLE_HOSTED="serial" + config HOSTED_COM_PORT + string "COM port connected to remote RPC server" + default "$(COM_PORT)" + + config HOSTED_COM_SPEED + int "Baud rate for hosted COM port" + default 115200 + endif + +endmenu diff --git a/Sming/Components/Hosted/README.rst b/Sming/Components/Hosted/README.rst index 66f47eef3b..6acc1b9f58 100644 --- a/Sming/Components/Hosted/README.rst +++ b/Sming/Components/Hosted/README.rst @@ -16,15 +16,15 @@ we can compile the application using the following directives:: make SMING_ARCH=Host ENABLE_HOSTED=tcp HOSTED_SERVER_IP=192.168.4.1 -`SMING_ARCH=Host` instructs the build system to build the application for the Host architecture. -`ENABLE_HOSTED=tcp` instructs the host emulator to communication with the real microcontroller using TCP -`HOSTED_SERVER_IP=192.168.4.1` instructs the host emulator to connect to IP `192.168.4.1`. +- ``SMING_ARCH=Host`` instructs the build system to build the application for the Host architecture. +- ``ENABLE_HOSTED=tcp`` instructs the host emulator to communicate with the real microcontroller using TCP. +- ``HOSTED_SERVER_IP=192.168.4.1`` tells the host emulator where the server is running. We need to compile and flash also a special application on the desired microcontroller. This application will act as an RPC Server and will execute the commands from the host emulator on the microcontroller. -In the sub-directory ``samples`` inside this directory you will find the sample applications that will turn your microcontroller into -RCP server. +In the ``samples`` directory you will find the sample applications that will turn your microcontroller into +an RCP server. The compilation and flashing for ESP32, for example, can be done using the following commands:: @@ -39,17 +39,20 @@ Communication ------------- At the moment the communication between an application running on the Host and the RCP server running on a microcontroller can be done using TCP or serial interface. + The ``transport`` classes are located under ``include/Hosted/Transport``. Configuration ------------- + .. envvar:: ENABLE_HOSTED Default: empty (disabled) Enables the hosted component. Valid values for the moment are: - - tcp - for communication over TCP network. - - serial - for communication over serial interface + - ``tcp`` for communication over TCP network. + - ``serial`` for communication over serial interface + .. envvar:: HOSTED_SERVER_IP @@ -57,14 +60,23 @@ Configuration Used only when ENABLE_HOSTED=tcp is specified. Specifies the IP address of the remote RPC server. + .. envvar:: HOSTED_COM_PORT - Default: /dev/ttyUSB0 or the value of the environment variable COM_PORT if defined + Default: :envvar:`COM_PORT` Used only when ENABLE_HOSTED=serial is specified. Specifies which local communication port should be used to connect to the remote RPC server. + .. envvar:: HOSTED_COM_SPEED Default: 115200 Used only when ENABLE_HOSTED=serial is specified. Specifies the communication baud rate. + + +API Documentation +----------------- + +.. doxygennamespace:: Hosted + :members: diff --git a/Sming/Components/Hosted/component.mk b/Sming/Components/Hosted/component.mk index 3ae054f19c..3d8103475f 100644 --- a/Sming/Components/Hosted/component.mk +++ b/Sming/Components/Hosted/component.mk @@ -1,31 +1,27 @@ -COMPONENT_SRCDIRS := $(COMPONENT_PATH)/src -COMPONENT_INCDIRS := $(COMPONENT_SRCDIRS) $(COMPONENT_PATH)/include +COMPONENT_SRCDIRS := src +COMPONENT_INCDIRS := include +COMPONENT_DOXYGEN_INPUT := include COMPONENT_DEPENDS := simpleRPC # Architecture of the device where the hosted service will be flashed HOSTED_ARCH ?= Esp8266 -COMPONENT_RELINK_VARS += ENABLE_HOSTED COMPONENT_VARS := ENABLE_HOSTED - ENABLE_HOSTED ?= ifneq ($(ENABLE_HOSTED),) - COMPONENT_SRCDIRS += $(COMPONENT_PATH)/init/$(ENABLE_HOSTED) + COMPONENT_SRCDIRS += init/$(ENABLE_HOSTED) EXTRA_LDFLAGS := $(call Wrap,host_init) COMPONENT_DEPENDS += SerialLib endif -COMPONENT_VARS += HOSTED_SERVER_IP +COMPONENT_RELINK_VARS += HOSTED_SERVER_IP -COMPONENT_VARS += HOSTED_COM_PORT -HOSTED_COM_PORT := "/dev/ttyUSB0" -ifneq ($(COM_PORT),) - HOSTED_COM_PORT:=$(COM_PORT) -endif +COMPONENT_RELINK_VARS += HOSTED_COM_PORT +HOSTED_COM_PORT ?= $(COM_PORT) -COMPONENT_VARS += HOSTED_COM_SPEED -HOSTED_COM_SPEED := 115200 +COMPONENT_RELINK_VARS += HOSTED_COM_SPEED +HOSTED_COM_SPEED ?= 115200 COMPONENT_CFLAGS = -DHOSTED_SERVER_IP=$(HOSTED_SERVER_IP) -DHOSTED_COM_PORT="\"$(HOSTED_COM_PORT)"\" -DHOSTED_COM_SPEED=$(HOSTED_COM_SPEED) COMPONENT_CXXFLAGS := $(COMPONENT_CFLAGS) diff --git a/Sming/Components/Hosted/include/Hosted/Client.h b/Sming/Components/Hosted/include/Hosted/Client.h index d736e82c28..80f3e97dbb 100644 --- a/Sming/Components/Hosted/include/Hosted/Client.h +++ b/Sming/Components/Hosted/include/Hosted/Client.h @@ -127,7 +127,7 @@ class Client } if(result == ParserResult::error) { - debug_e("Invalid header"); + host_debug_e("Invalid header"); return false; } } while(true); diff --git a/Sming/Components/Hosted/include/Hosted/Serial.h b/Sming/Components/Hosted/include/Hosted/Serial.h index 8bdfc94b10..3f65340e8b 100644 --- a/Sming/Components/Hosted/include/Hosted/Serial.h +++ b/Sming/Components/Hosted/include/Hosted/Serial.h @@ -17,9 +17,10 @@ #error "Hosted::Serial can be used only on the Host architecture!" #endif +#include #include #include -#include +#include namespace Hosted { @@ -55,7 +56,7 @@ class Serial : public Stream return true; } - debug_w("Hosted::Serial:begin error: %d", result); + host_debug_w("Hosted::Serial:begin error: %d", result); return false; } diff --git a/Sming/Components/Hosted/init/serial/InitClient.cpp b/Sming/Components/Hosted/init/serial/InitClient.cpp index 9a9d22cf19..3b4c980548 100644 --- a/Sming/Components/Hosted/init/serial/InitClient.cpp +++ b/Sming/Components/Hosted/init/serial/InitClient.cpp @@ -11,9 +11,8 @@ * ****/ -#include -#include #include +#include #ifndef HOSTED_COM_PORT #define HOSTED_COM_PORT "/dev/ttyUSB0" @@ -36,14 +35,12 @@ Hosted::Serial hostedSerial(HOSTED_COM_PORT); void __wrap_host_init() { - Serial.begin(115200); - Serial.printf("Connecting to: %s ...\n", HOSTED_COM_PORT); + host_printf("Connecting to: %s ...\r\n", HOSTED_COM_PORT); bool serialReady = false; - do { - serialReady = hostedSerial.begin(HOSTED_COM_SPEED); - usleep(200); - } while(!serialReady); + while(!(serialReady = hostedSerial.begin(HOSTED_COM_SPEED))) { + msleep(50); + } hostedClient = new Hosted::Client(hostedSerial); hostedClient->getRemoteCommands(); diff --git a/Sming/Components/Hosted/samples/serial/README.rst b/Sming/Components/Hosted/samples/serial/README.rst index d1635d59fb..0bf048eb84 100644 --- a/Sming/Components/Hosted/samples/serial/README.rst +++ b/Sming/Components/Hosted/samples/serial/README.rst @@ -1,4 +1,4 @@ -Hosted RCP Server over Serial +Hosted RPC Server over Serial ============================= Overview diff --git a/Sming/Components/Hosted/samples/serial/app/application.cpp b/Sming/Components/Hosted/samples/serial/app/application.cpp index fab436ee0e..8faed12e44 100644 --- a/Sming/Components/Hosted/samples/serial/app/application.cpp +++ b/Sming/Components/Hosted/samples/serial/app/application.cpp @@ -1,5 +1,5 @@ /* - * This sample application demostrates RPC communication via the serial interface + * This sample application demonstrates RPC communication via the serial interface */ #include #include diff --git a/Sming/Components/Hosted/samples/serial/component.mk b/Sming/Components/Hosted/samples/serial/component.mk index a2140118b1..75ad616820 100644 --- a/Sming/Components/Hosted/samples/serial/component.mk +++ b/Sming/Components/Hosted/samples/serial/component.mk @@ -2,8 +2,8 @@ COMPONENT_DEPENDS := Hosted ENABLE_HOSTED := -## And does not require WIFI -DISABLE_WIFI := 1 +## And does not require networking +DISABLE_NETWORK := 1 ENABLE_HOST_UARTID := 0 HOST_NETWORK_OPTIONS := --pause \ No newline at end of file diff --git a/Sming/Components/Hosted/samples/tcp/Kconfig b/Sming/Components/Hosted/samples/tcp/Kconfig new file mode 100644 index 0000000000..e71cf8c6fc --- /dev/null +++ b/Sming/Components/Hosted/samples/tcp/Kconfig @@ -0,0 +1,7 @@ +menu "Hosted TCP sample" + config CONNECT_TO_WIFI + bool "Connect to WiFi access point" + help + Make sure to provide WIFI_SSID and WIFI_PWD values + +endmenu diff --git a/Sming/Components/Hosted/samples/tcp/README.rst b/Sming/Components/Hosted/samples/tcp/README.rst index 308e5757fb..1a1735d511 100644 --- a/Sming/Components/Hosted/samples/tcp/README.rst +++ b/Sming/Components/Hosted/samples/tcp/README.rst @@ -15,18 +15,8 @@ Configuration Default: 0 (disabled) - If set to 1 the application will try to connect to a WIFI access point. Make sure to provide also the WIFI_SSID and WIFI_PWD values. + If set to 1 the application will try to connect to a WIFI access point. + Make sure to provide also the :envvar:`WIFI_SSID` and :envvar:`WIFI_PWD` values. If set to 0 the application will start an access point to which the Host application can connect. -.. envvar:: WIFI_SSID - - Default: PleaseEnterSSID - - WIFI Access Point name. If you have enabled CONNECT_TO_WIFI then make sure to set also WIFI_SSID and WIFI_PWD values. - -.. envvar:: WIFI_PWD - - Default: PleaseEnterPass - - WIFI Access Point password. If you have enabled CONNECT_TO_WIFI then make sure to set also WIFI_SSID and WIFI_PWD values. diff --git a/Sming/Components/Hosted/samples/tcp/app/application.cpp b/Sming/Components/Hosted/samples/tcp/app/application.cpp index 3702dc2580..bfcc930d51 100644 --- a/Sming/Components/Hosted/samples/tcp/app/application.cpp +++ b/Sming/Components/Hosted/samples/tcp/app/application.cpp @@ -1,5 +1,5 @@ /* - * This sample application demostrates RPC communication via TCP. + * This sample application demonstrates RPC communication via TCP. * It will try to connect to create an existing Access Point (AP) or create to a new AP and start a TCP server. * The TCP server will listen on port 4031 for remote commands. */ @@ -58,7 +58,7 @@ void connectOk(IpAddress ip, IpAddress mask, IpAddress gateway) return true; }); - Serial.printf("Running RCP server on: %s:%u", ip.toString().c_str(), port); + Serial.printf("Running RPC server on: %s:%u", ip.toString().c_str(), port); } } // namespace @@ -75,7 +75,7 @@ void init() WifiEvents.onStationGotIP(connectOk); #else WifiAccessPoint.enable(true); - WifiAccessPoint.config(_F("RCP Server"), nullptr, AUTH_OPEN); + WifiAccessPoint.config(_F("RPC Server"), nullptr, AUTH_OPEN); connectOk(WifiAccessPoint.getIP(), WifiAccessPoint.getNetworkMask(), WifiAccessPoint.getNetworkGateway()); #endif } diff --git a/Sming/Components/Hosted/samples/tcp/component.mk b/Sming/Components/Hosted/samples/tcp/component.mk index a3b186f112..8883932d4c 100644 --- a/Sming/Components/Hosted/samples/tcp/component.mk +++ b/Sming/Components/Hosted/samples/tcp/component.mk @@ -4,7 +4,7 @@ ENABLE_HOSTED := # If set the application should connect to a WIFI access point # otherwise it will set its own access point -COMPONENT_VARS := CONNECT_TO_WIFI +COMPONENT_RELINK_VARS := CONNECT_TO_WIFI CONNECT_TO_WIFI ?= 0 APP_CFLAGS = -DCONNECT_TO_WIFI=$(CONNECT_TO_WIFI) diff --git a/Sming/Components/IFS b/Sming/Components/IFS index c7365f6b08..ea8765a968 160000 --- a/Sming/Components/IFS +++ b/Sming/Components/IFS @@ -1 +1 @@ -Subproject commit c7365f6b082c3c9b0da1be1940a9ec80e5960614 +Subproject commit ea8765a968a3e4a9d4bbf1eb240754c1f06c3131 diff --git a/Sming/Components/Network/Arch/Esp32/Network/DM9051.cpp b/Sming/Components/Network/Arch/Esp32/Network/DM9051.cpp index 3544fe0864..a64eb2d094 100644 --- a/Sming/Components/Network/Arch/Esp32/Network/DM9051.cpp +++ b/Sming/Components/Network/Arch/Esp32/Network/DM9051.cpp @@ -9,6 +9,7 @@ ****/ #include +#include #include "spi_config.h" namespace Ethernet diff --git a/Sming/Components/Network/Arch/Esp32/Network/W5500.cpp b/Sming/Components/Network/Arch/Esp32/Network/W5500.cpp index 49662df6b7..f888613859 100644 --- a/Sming/Components/Network/Arch/Esp32/Network/W5500.cpp +++ b/Sming/Components/Network/Arch/Esp32/Network/W5500.cpp @@ -9,6 +9,7 @@ ****/ #include +#include #include "spi_config.h" namespace Ethernet diff --git a/Sming/Components/Network/Arch/Esp32/Network/spi_config.h b/Sming/Components/Network/Arch/Esp32/Network/spi_config.h index 9ddea94d42..6fcc0f87ba 100644 --- a/Sming/Components/Network/Arch/Esp32/Network/spi_config.h +++ b/Sming/Components/Network/Arch/Esp32/Network/spi_config.h @@ -15,22 +15,22 @@ #include #include "driver/spi_master.h" -#if defined(SUBARCH_ESP32) +#if defined(SOC_ESP32) #define DEFAULT_HOST SPI2_HOST #define DEFAULT_PIN_CS 22 #define DEFAULT_PIN_INT 4 #define DEFAULT_PIN_RESET 5 -#elif defined(SUBARCH_ESP32S2) +#elif defined(SOC_ESP32S2) #define DEFAULT_HOST SPI2_HOST #define DEFAULT_PIN_CS 34 #define DEFAULT_PIN_INT 19 #define DEFAULT_PIN_RESET 18 -#elif defined(SUBARCH_ESP32C3) +#elif defined(SOC_ESP32C3) #define DEFAULT_HOST SPI2_HOST #define DEFAULT_PIN_CS 10 #define DEFAULT_PIN_INT 19 #define DEFAULT_PIN_RESET 18 -#elif defined(SUBARCH_ESP32S3) +#elif defined(SOC_ESP32S3) #define DEFAULT_HOST SPI2_HOST #define DEFAULT_PIN_CS 10 #define DEFAULT_PIN_INT 19 diff --git a/Sming/Components/Network/Arch/Esp32/Platform/EmbeddedEthernet.cpp b/Sming/Components/Network/Arch/Esp32/Platform/EmbeddedEthernet.cpp index c6ae63d901..ec6b028dbf 100644 --- a/Sming/Components/Network/Arch/Esp32/Platform/EmbeddedEthernet.cpp +++ b/Sming/Components/Network/Arch/Esp32/Platform/EmbeddedEthernet.cpp @@ -12,6 +12,7 @@ #include #include #include +#include using namespace Ethernet; diff --git a/Sming/Components/Network/Arch/Esp32/Platform/IdfService.cpp b/Sming/Components/Network/Arch/Esp32/Platform/IdfService.cpp index 05297312d5..c96171f05a 100644 --- a/Sming/Components/Network/Arch/Esp32/Platform/IdfService.cpp +++ b/Sming/Components/Network/Arch/Esp32/Platform/IdfService.cpp @@ -11,6 +11,7 @@ #include #include #include +#include namespace Ethernet { diff --git a/Sming/Components/Network/Arch/Esp32/Platform/WifiEventsImpl.cpp b/Sming/Components/Network/Arch/Esp32/Platform/WifiEventsImpl.cpp index af37053c58..dcadfad2b9 100644 --- a/Sming/Components/Network/Arch/Esp32/Platform/WifiEventsImpl.cpp +++ b/Sming/Components/Network/Arch/Esp32/Platform/WifiEventsImpl.cpp @@ -14,6 +14,7 @@ #include #include #include +#include static WifiEventsImpl events; WifiEventsClass& WifiEvents = events; diff --git a/Sming/Components/Network/Arch/Esp8266/Platform/StationImpl.cpp b/Sming/Components/Network/Arch/Esp8266/Platform/StationImpl.cpp index cbb7450312..37b61adc0e 100644 --- a/Sming/Components/Network/Arch/Esp8266/Platform/StationImpl.cpp +++ b/Sming/Components/Network/Arch/Esp8266/Platform/StationImpl.cpp @@ -213,7 +213,7 @@ bool StationImpl::setIP(IpAddress address, IpAddress netmask, IpAddress gateway) ipinfo.netmask = netmask; ipinfo.gw = gateway; if(wifi_set_ip_info(STATION_IF, &ipinfo)) { - debugf("Station IP succesfully updated"); + debugf("Station IP successfully updated"); } else { debugf("Station IP can't be updated"); enableDHCP(true); diff --git a/Sming/Components/Network/Arch/Host/Platform/StationImpl.cpp b/Sming/Components/Network/Arch/Host/Platform/StationImpl.cpp index 4128401682..bda2418983 100644 --- a/Sming/Components/Network/Arch/Host/Platform/StationImpl.cpp +++ b/Sming/Components/Network/Arch/Host/Platform/StationImpl.cpp @@ -10,8 +10,8 @@ #include "StationImpl.h" #include "WifiEventsImpl.h" -#include #include +#include StationImpl station; StationClass& WifiStation = station; diff --git a/Sming/Components/Network/Kconfig b/Sming/Components/Network/Kconfig new file mode 100644 index 0000000000..2d9d0e353a --- /dev/null +++ b/Sming/Components/Network/Kconfig @@ -0,0 +1,53 @@ +menu "Network" + depends on !DISABLE_NETWORK + + config DISABLE_WIFI + bool "Build without WiFi support" + default n + help + Keeps the core Network library but excludes WiFi code. + Applications using ethernet can use this to reduce code size. + + if !DISABLE_WIFI + config WIFI_SSID + string "Default WiFi SSID" + depends on !DISABLE_WIFI + + config WIFI_PWD + string "Default WiFi Passphrase" + depends on !DISABLE_WIFI + + if SMING_ARCH=Esp8266 + config ENABLE_WPS + bool "Enable WiFi Protected Setup (WPS)" + help + WPS is not enabled by default to preserve resources, and because + there may be security implications which you should consider carefully. + + config ENABLE_SMART_CONFIG + bool "Enable WiFi Smart Configuration API" + help + See :sample:`Basic_SmartConfig` sample application. + endif + endif + + config HTTP_SERVER_EXPOSE_NAME + bool "Add \"HttpServer/Sming\" to the SERVER field in response headers" + default y + help + If disabled, the SERVER field is omitted from all responses. + + config HTTP_SERVER_EXPOSE_VERSION + bool "Include Sming version in HTTP server headers" + depends on HTTP_SERVER_EXPOSE_NAME + help + Adds the current Sming build version to the SERVER field in response headers. + For example, "Sming/4.0.0-rc2". + + config ENABLE_CUSTOM_LWIP + int "LWIP version (0 for SDK, 1 or 2)" + range 0 2 + default 1 + depends on SMING_ARCH=Esp8266 + +endmenu diff --git a/Sming/Components/Network/component.mk b/Sming/Components/Network/component.mk index 69d0d4bb02..c6eec0041e 100644 --- a/Sming/Components/Network/component.mk +++ b/Sming/Components/Network/component.mk @@ -1,3 +1,5 @@ +COMPONENT_SOC := esp* host + COMPONENT_SRCDIRS := \ src \ $(call ListAllSubDirs,$(COMPONENT_PATH)/src) \ @@ -9,7 +11,10 @@ COMPONENT_INCDIRS := \ COMPONENT_DOXYGEN_INPUT := \ src \ - Arch/Esp32/Platform/include + Arch/Esp32/include + +COMPONENT_DOCFILES := \ + docs/http/* COMPONENT_DEPENDS := \ ssl \ @@ -19,6 +24,13 @@ COMPONENT_DEPENDS := \ mqtt-codec \ libyuarel +# WiFi settings may be provide via Environment variables +CONFIG_VARS += WIFI_SSID WIFI_PWD +ifdef WIFI_SSID + APP_CFLAGS += -DWIFI_SSID=\"$(WIFI_SSID)\" + APP_CFLAGS += -DWIFI_PWD=\"$(WIFI_PWD)\" +endif + # => WPS COMPONENT_VARS += ENABLE_WPS ifeq ($(ENABLE_WPS), 1) @@ -40,10 +52,6 @@ COMPONENT_VARS += HTTP_SERVER_EXPOSE_VERSION HTTP_SERVER_EXPOSE_VERSION ?= 0 GLOBAL_CFLAGS += -DHTTP_SERVER_EXPOSE_VERSION=$(HTTP_SERVER_EXPOSE_VERSION) -# => MQTT -COMPONENT_VARS += MQTT_NO_COMPAT -MQTT_NO_COMPAT ?= 1 - # => LWIP COMPONENT_VARS += ENABLE_CUSTOM_LWIP ifeq ($(SMING_ARCH),Esp8266) diff --git a/Sming/Components/Network/docs/http/client.rst b/Sming/Components/Network/docs/http/client.rst new file mode 100644 index 0000000000..489b5248f7 --- /dev/null +++ b/Sming/Components/Network/docs/http/client.rst @@ -0,0 +1,6 @@ +Client API +---------- + +.. doxygengroup:: httpclient + :content-only: + :members: diff --git a/Sming/Components/Network/docs/http/server.rst b/Sming/Components/Network/docs/http/server.rst new file mode 100644 index 0000000000..86d37fbe85 --- /dev/null +++ b/Sming/Components/Network/docs/http/server.rst @@ -0,0 +1,6 @@ +Server API +---------- + +.. doxygengroup:: httpserver + :content-only: + :members: diff --git a/Sming/Components/Network/docs/http/support.rst b/Sming/Components/Network/docs/http/support.rst new file mode 100644 index 0000000000..4bce1ffbc5 --- /dev/null +++ b/Sming/Components/Network/docs/http/support.rst @@ -0,0 +1,15 @@ +Support API +----------- + +.. doxygennamespace:: ContentType + +.. doxygenfile:: Network/Http/HttpCommon.h + +.. doxygenclass:: HttpHeaders + :members: + +.. doxygenclass:: HttpRequest + :members: + +.. doxygenclass:: HttpResponse + :members: diff --git a/Sming/Components/Network/http.rst b/Sming/Components/Network/http.rst index ae8a7d4083..f6669434fa 100644 --- a/Sming/Components/Network/http.rst +++ b/Sming/Components/Network/http.rst @@ -32,23 +32,10 @@ Build Variables Sets the DATE field in response headers. -Support API ------------ +API Documentation +----------------- -.. doxygennamespace:: ContentType +.. toctree:: + :glob: - -Client API ----------- - -.. doxygengroup:: httpclient - :content-only: - :members: - - -Server API ----------- - -.. doxygengroup:: httpserver - :content-only: - :members: + docs/http/* diff --git a/Sming/Core/Data/Stream/Base64OutputStream.cpp b/Sming/Components/Network/src/Data/Stream/Base64OutputStream.cpp similarity index 100% rename from Sming/Core/Data/Stream/Base64OutputStream.cpp rename to Sming/Components/Network/src/Data/Stream/Base64OutputStream.cpp diff --git a/Sming/Core/Data/Stream/Base64OutputStream.h b/Sming/Components/Network/src/Data/Stream/Base64OutputStream.h similarity index 94% rename from Sming/Core/Data/Stream/Base64OutputStream.h rename to Sming/Components/Network/src/Data/Stream/Base64OutputStream.h index a81af415a7..865f680571 100644 --- a/Sming/Core/Data/Stream/Base64OutputStream.h +++ b/Sming/Components/Network/src/Data/Stream/Base64OutputStream.h @@ -12,8 +12,8 @@ #pragma once -#include "../StreamTransformer.h" -#include "libb64/cencode.h" +#include +#include /** * @brief Read-only stream to emit base64-encoded content from source stream diff --git a/Sming/Core/Data/Stream/ChunkedStream.cpp b/Sming/Components/Network/src/Data/Stream/ChunkedStream.cpp similarity index 100% rename from Sming/Core/Data/Stream/ChunkedStream.cpp rename to Sming/Components/Network/src/Data/Stream/ChunkedStream.cpp diff --git a/Sming/Core/Data/Stream/ChunkedStream.h b/Sming/Components/Network/src/Data/Stream/ChunkedStream.h similarity index 95% rename from Sming/Core/Data/Stream/ChunkedStream.h rename to Sming/Components/Network/src/Data/Stream/ChunkedStream.h index 18488796d9..70b9ea6039 100644 --- a/Sming/Core/Data/Stream/ChunkedStream.h +++ b/Sming/Components/Network/src/Data/Stream/ChunkedStream.h @@ -12,7 +12,7 @@ #pragma once -#include "../StreamTransformer.h" +#include /** * @brief Read-only stream to obtain data using HTTP chunked encoding diff --git a/Sming/Components/Network/src/Data/Stream/MultipartStream.cpp b/Sming/Components/Network/src/Data/Stream/MultipartStream.cpp index a8393f81f2..bc4a16b824 100644 --- a/Sming/Components/Network/src/Data/Stream/MultipartStream.cpp +++ b/Sming/Components/Network/src/Data/Stream/MultipartStream.cpp @@ -12,6 +12,7 @@ #include #include +#include IDataSourceStream* MultipartStream::getNextStream() { diff --git a/Sming/Core/Data/Stream/MultipartStream.h b/Sming/Components/Network/src/Data/Stream/MultipartStream.h similarity index 80% rename from Sming/Core/Data/Stream/MultipartStream.h rename to Sming/Components/Network/src/Data/Stream/MultipartStream.h index 53a4a279a2..026e9f09a0 100644 --- a/Sming/Core/Data/Stream/MultipartStream.h +++ b/Sming/Components/Network/src/Data/Stream/MultipartStream.h @@ -12,8 +12,8 @@ #pragma once -#include "MultiStream.h" -#include "Network/Http/HttpHeaders.h" +#include +#include /** * @brief Read-only stream for creating HTTP multi-part content @@ -68,13 +68,3 @@ class MultipartStream : public MultiStream char boundary[16]{}; bool footerSent{false}; }; - -/** - * @deprecated Use `MultipartStream::BodyPart` instead - */ -typedef MultipartStream::BodyPart HttpPartResult SMING_DEPRECATED; - -/** - * @deprecated Use `MultipartStream::Producer` instead - */ -typedef MultipartStream::Producer HttpPartProducerDelegate SMING_DEPRECATED; diff --git a/Sming/Core/Data/Stream/QuotedPrintableOutputStream.cpp b/Sming/Components/Network/src/Data/Stream/QuotedPrintableOutputStream.cpp similarity index 100% rename from Sming/Core/Data/Stream/QuotedPrintableOutputStream.cpp rename to Sming/Components/Network/src/Data/Stream/QuotedPrintableOutputStream.cpp diff --git a/Sming/Core/Data/Stream/QuotedPrintableOutputStream.h b/Sming/Components/Network/src/Data/Stream/QuotedPrintableOutputStream.h similarity index 96% rename from Sming/Core/Data/Stream/QuotedPrintableOutputStream.h rename to Sming/Components/Network/src/Data/Stream/QuotedPrintableOutputStream.h index bdd19da8c3..c78a2730d6 100644 --- a/Sming/Core/Data/Stream/QuotedPrintableOutputStream.h +++ b/Sming/Components/Network/src/Data/Stream/QuotedPrintableOutputStream.h @@ -12,7 +12,7 @@ #pragma once -#include "../StreamTransformer.h" +#include /** * @brief Read-only stream that transforms bytes of data into quoted printable data stream diff --git a/Sming/Components/Network/src/Data/Stream/UrlencodedOutputStream.h b/Sming/Components/Network/src/Data/Stream/UrlencodedOutputStream.h index bd32391a7b..66615fa0a9 100644 --- a/Sming/Components/Network/src/Data/Stream/UrlencodedOutputStream.h +++ b/Sming/Components/Network/src/Data/Stream/UrlencodedOutputStream.h @@ -13,7 +13,7 @@ #pragma once #include -#include "Network/Http/HttpParams.h" +#include /** * @brief Represents key-value pairs as urlencoded string content diff --git a/Sming/Components/Network/src/IpAddress.h b/Sming/Components/Network/src/IpAddress.h index 0e5fe33c10..29a2102d83 100644 --- a/Sming/Components/Network/src/IpAddress.h +++ b/Sming/Components/Network/src/IpAddress.h @@ -19,7 +19,8 @@ #pragma once -#include +#include +#include #include "Printable.h" #include "WString.h" @@ -198,8 +199,5 @@ inline String toString(IpAddress address) return address.toString(); } -/** @deprecated Use `IpAddress` instead. */ -typedef IpAddress IPAddress SMING_DEPRECATED; - // Making this extern saves 100's of bytes; each usage otherwise incurs 4 bytes of BSS #define INADDR_NONE IpAddress() diff --git a/Sming/Components/Network/src/Network/DnsServer.cpp b/Sming/Components/Network/src/Network/DnsServer.cpp index fbf0a07de0..9890c92936 100644 --- a/Sming/Components/Network/src/Network/DnsServer.cpp +++ b/Sming/Components/Network/src/Network/DnsServer.cpp @@ -18,6 +18,8 @@ #include "DnsServer.h" #include "UdpConnection.h" #include "WString.h" +#include +#include bool DnsServer::start(uint16_t port, const String& domainName, const IpAddress& resolvedIP) { diff --git a/Sming/Components/Network/src/Network/DnsServer.h b/Sming/Components/Network/src/Network/DnsServer.h index 3f5eefc1cf..9c8bfdaf19 100644 --- a/Sming/Components/Network/src/Network/DnsServer.h +++ b/Sming/Components/Network/src/Network/DnsServer.h @@ -46,7 +46,7 @@ struct DnsHeader { uint16_t ID; // identification number char RD : 1; // recursion desired char TC : 1; // truncated message - char AA : 1; // authoritive answer + char AA : 1; // authoritative answer char OPCode : 4; // message_type char QR : 1; // query/response flag char RCode : 4; // response code @@ -58,6 +58,9 @@ struct DnsHeader { uint16_t ARCount; // number of resource entries }; +/** + * @brief DNS server class + */ class DnsServer : public UdpConnection { public: @@ -65,20 +68,34 @@ class DnsServer : public UdpConnection { } + /** + * @brief Set error reply code + */ void setErrorReplyCode(DnsReplyCode replyCode) { errorReplyCode = replyCode; } + /** + * @brief Set message Time-To-Live in seconds + */ void setTTL(uint32_t ttl) { this->ttl = ttl; } - // Returns true if successful, false if there are no sockets available + /** + * @brief Start the DNS server + * @param port + * @param domainName + * @param resolvedIP + * @retval bool true if successful, false if there are no sockets available. + */ bool start(uint16_t port, const String& domainName, const IpAddress& resolvedIP); - // stops the DNS server + /** + * @brief Stop the DNS server + */ void stop(); protected: @@ -98,7 +115,4 @@ class DnsServer : public UdpConnection bool requestIncludesOnlyOneQuestion(); }; -/** @deprecated Use `DnsServer` */ -typedef DnsServer DNSServer SMING_DEPRECATED; - /** @} */ diff --git a/Sming/Components/Network/src/Network/Ftp/FtpServerConnection.h b/Sming/Components/Network/src/Network/Ftp/FtpServerConnection.h index 85292cfd46..a3dcd14a27 100644 --- a/Sming/Components/Network/src/Network/Ftp/FtpServerConnection.h +++ b/Sming/Components/Network/src/Network/Ftp/FtpServerConnection.h @@ -80,6 +80,4 @@ class FtpServerConnection : public TcpConnection FtpDataStream* dataConnection{nullptr}; }; -typedef FtpServerConnection FTPServerConnection SMING_DEPRECATED; // @deprecated Use `FtpServerConnection` instead - /** @} */ diff --git a/Sming/Components/Network/src/Network/FtpServer.h b/Sming/Components/Network/src/Network/FtpServer.h index 78f947b938..e096311f2c 100644 --- a/Sming/Components/Network/src/Network/FtpServer.h +++ b/Sming/Components/Network/src/Network/FtpServer.h @@ -62,8 +62,8 @@ class CustomFtpServer : public TcpServer IFS::FileSystem* fileSystem; }; -/** @defgroup ftpserver FTP server - * @ingroup tcpserver +/** + * @ingroup ftpserver * @brief Provides FTP server */ class FtpServer : public CustomFtpServer @@ -72,15 +72,6 @@ class FtpServer : public CustomFtpServer void addUser(const String& login, const String& pass, IFS::UserRole userRole = IFS::UserRole::Admin); IFS::UserRole validateUser(const char* login, const char* pass) override; - /** - * @brief Legacy user validation - * @deprecated Use `validateUser()` instead - */ - bool checkUser(const String& login, const String& pass) SMING_DEPRECATED - { - return validateUser(login.c_str(), pass.c_str()) != IFS::UserRole::None; - } - protected: bool onCommand(String cmd, String data, FtpServerConnection& connection) override; @@ -92,8 +83,3 @@ class FtpServer : public CustomFtpServer using UserList = HashMap; UserList users; }; - -/** - * @deprecated Use `FtpServer` instead - */ -typedef FtpServer FTPServer SMING_DEPRECATED; diff --git a/Sming/Components/Network/src/Network/Http/HttpClientConnection.h b/Sming/Components/Network/src/Network/Http/HttpClientConnection.h index 0cf6301080..2720594f6a 100644 --- a/Sming/Components/Network/src/Network/Http/HttpClientConnection.h +++ b/Sming/Components/Network/src/Network/Http/HttpClientConnection.h @@ -19,7 +19,7 @@ /** * @brief Provides http client connection - * @ingroup http + * @ingroup httpclient * @{ */ diff --git a/Sming/Components/Network/src/Network/Http/HttpCommon.h b/Sming/Components/Network/src/Network/Http/HttpCommon.h index 8acb25fb19..6ee5181b36 100644 --- a/Sming/Components/Network/src/Network/Http/HttpCommon.h +++ b/Sming/Components/Network/src/Network/Http/HttpCommon.h @@ -98,17 +98,6 @@ using HttpFiles = ObjectMap; */ String toString(HttpError err); -/** - * @brief Return a string name of the given error - * @note This replaces the one in http_parser module which uses a load of RAM - * @deprecated Use `toString(HttpError)` - */ -inline String httpGetErrorName(HttpError err) SMING_DEPRECATED; -inline String httpGetErrorName(HttpError err) -{ - return toString(err); -} - /** * @brief Return a descriptive string for the given error */ diff --git a/Sming/Components/Network/src/Network/Http/HttpConnection.h b/Sming/Components/Network/src/Network/Http/HttpConnection.h index 99ab8e512d..7bcfa6135a 100644 --- a/Sming/Components/Network/src/Network/Http/HttpConnection.h +++ b/Sming/Components/Network/src/Network/Http/HttpConnection.h @@ -78,56 +78,6 @@ class HttpConnection : public TcpClient return &response; } - // Backported for compatibility reasons - - /** - * @deprecated Use `getResponse()->code` instead - */ - int getResponseCode() const SMING_DEPRECATED - { - return int(response.code); - } - - /** - * @deprecated Use `getResponse()->headers[]` instead - */ - String getResponseHeader(const String& headerName, const String& defaultValue = nullptr) const SMING_DEPRECATED - { - return response.headers[headerName] ?: defaultValue; - } - - /** - * @deprecated Use `getResponse()->headers` instead - */ - HttpHeaders& getResponseHeaders() SMING_DEPRECATED - { - return response.headers; - } - - /** - * @deprecated Use `getResponse()->headers.getLastModifiedDate()` instead - */ - DateTime getLastModifiedDate() const SMING_DEPRECATED - { - return response.headers.getLastModifiedDate(); - } - - /** - * @deprecated Use `getResponse()->headers.getServerDate()` instead - */ - DateTime getServerDate() const SMING_DEPRECATED - { - return response.headers.getServerDate(); - } - - /** - * @deprecated Use `getResponse()->getBody()` instead - */ - String getResponseString() SMING_DEPRECATED - { - return response.getBody(); - } - protected: /** @brief Called after all headers have been received and processed */ void resetHeaders(); diff --git a/Sming/Components/Network/src/Network/Http/HttpHeaders.h b/Sming/Components/Network/src/Network/Http/HttpHeaders.h index 0c3fd579e4..8d181c6eae 100644 --- a/Sming/Components/Network/src/Network/Http/HttpHeaders.h +++ b/Sming/Components/Network/src/Network/Http/HttpHeaders.h @@ -72,6 +72,9 @@ class HttpHeaders : public HttpHeaderFields, private HashMap(headers)[name]; } + /** + * @brief Get POST parameter value + * @param name Name of parameter + * @retval const String& Value, will be invalid (i.e. if() == false) if field not present + */ const String& getPostParameter(const String& name) { return static_cast(postParams)[name]; } - /** @deprecated Use `uri.Path` instead */ - String getPath() SMING_DEPRECATED - { - return uri.Path; - } - - /* @deprecated Use methods of `uri.Query` instead */ - String getQueryParameter(const String& parameterName, const String& defaultValue = nullptr) const + /** + * @brief Get parameter from query fields + * @param name Name of parameter + * @param defaultValue Optional default value to use if requested parameter not present + */ + String getQueryParameter(const String& name, const String& defaultValue = nullptr) const { - return static_cast(uri.Query)[parameterName] ?: defaultValue; + return static_cast(uri.Query)[name] ?: defaultValue; } /** @@ -195,16 +188,26 @@ class HttpRequest * @name Set request body content * @{ */ + + /// Set body from String object HttpRequest* setBody(const String& body) { return setBody(reinterpret_cast(body.c_str()), body.length()); } + /// Set body from String object using move semantics: body will be invalid on return HttpRequest* setBody(String&& body) noexcept; + /// Set body using given stream object, and retain ownership HttpRequest* setBody(IDataSourceStream* stream); + /** + * @brief Set body content by copying binary data + * @param rawData Data to copy + * @param length Number of bytes to copy + */ HttpRequest* setBody(const uint8_t* rawData, size_t length); + /** @} */ /** @@ -278,15 +281,15 @@ class HttpRequest } public: - Url uri; - HttpMethod method = HTTP_GET; - HttpHeaders headers; - HttpParams postParams; - HttpFiles files; + Url uri; ///< Request URL + HttpMethod method = HTTP_GET; ///< Request method + HttpHeaders headers; ///< Request headers + HttpParams postParams; ///< POST parameters + HttpFiles files; ///< Attached files - int retries = 0; // how many times the request should be send again... + int retries = 0; ///< how many times the request should be send again... - void* args = nullptr; // Used to store data that should be valid during a single request + void* args = nullptr; ///< Used to store data that should be valid during a single request protected: RequestHeadersCompletedDelegate headersCompletedDelegate; diff --git a/Sming/Components/Network/src/Network/Http/HttpResource.h b/Sming/Components/Network/src/Network/Http/HttpResource.h index 60824fb635..7556e6387a 100644 --- a/Sming/Components/Network/src/Network/Http/HttpResource.h +++ b/Sming/Components/Network/src/Network/Http/HttpResource.h @@ -28,7 +28,7 @@ using HttpResourceDelegate = /** * @brief Instances of this class are registered with an HttpServer for a specific URL - * @ingroup http + * @ingroup httpserver */ class HttpResource { diff --git a/Sming/Components/Network/src/Network/Http/HttpResourceTree.h b/Sming/Components/Network/src/Network/Http/HttpResourceTree.h index fb7aee3370..932d366d1e 100644 --- a/Sming/Components/Network/src/Network/Http/HttpResourceTree.h +++ b/Sming/Components/Network/src/Network/Http/HttpResourceTree.h @@ -21,7 +21,7 @@ using HttpPathDelegate = Delegate { @@ -59,6 +59,15 @@ class HttpResourceTree : public ObjectMap using ObjectMap::set; + template + HttpResource* set(const String& path, HttpResource* resource, HttpResourcePlugin* plugin, Tail... plugins) + { + registerPlugin(plugin, plugins...); + set(path, resource); + resource->addPlugin(plugin, plugins...); + return resource; + } + /** * @brief Set a callback to handle the given path * @param path URL path diff --git a/Sming/Components/Network/src/Network/Http/HttpResponse.cpp b/Sming/Components/Network/src/Network/Http/HttpResponse.cpp index 73222e8c51..dadcd817a1 100644 --- a/Sming/Components/Network/src/Network/Http/HttpResponse.cpp +++ b/Sming/Components/Network/src/Network/Http/HttpResponse.cpp @@ -14,6 +14,7 @@ #include #include "Data/Stream/MemoryDataStream.h" #include "Data/Stream/FileStream.h" +#include HttpResponse* HttpResponse::setCookie(const String& name, const String& value, bool append) { diff --git a/Sming/Components/Network/src/Network/Http/HttpResponse.h b/Sming/Components/Network/src/Network/Http/HttpResponse.h index b4579b810f..c7b848da8e 100644 --- a/Sming/Components/Network/src/Network/Http/HttpResponse.h +++ b/Sming/Components/Network/src/Network/Http/HttpResponse.h @@ -34,38 +34,6 @@ class HttpResponse bool sendString(String&& text) noexcept; - /** - * @deprecated Use `headers.contains()` instead - */ - bool hasHeader(const String& name) SMING_DEPRECATED - { - return headers.contains(name); - } - - /** - * @deprecated Use `headers[HTTP_HEADER_LOCATION]` instead - */ - void redirect(const String& location) SMING_DEPRECATED - { - headers[HTTP_HEADER_LOCATION] = location; - } - - /** - * @deprecated Use `response.code = HTTP_STATUS_FORBIDDEN` instead - */ - void forbidden() SMING_DEPRECATED - { - code = HTTP_STATUS_FORBIDDEN; - } - - /** - * @deprecated Use `response.code = HTTP_STATUS_NOT_FOUND` instead - */ - void notFound() SMING_DEPRECATED - { - code = HTTP_STATUS_NOT_FOUND; - } - HttpResponse* setContentType(const String& type) { headers[HTTP_HEADER_CONTENT_TYPE] = type; @@ -102,17 +70,6 @@ class HttpResponse */ bool sendFile(const String& fileName, bool allowGzipFileCheck = true); - /** - * @brief Parse and send template file - * @param newTemplateInstance - * @retval bool - * @deprecated Use `sendNamedStream()` instead - */ - bool sendTemplate(IDataSourceStream* newTemplateInstance) SMING_DEPRECATED - { - return sendNamedStream(newTemplateInstance); - } - /** * @brief Parse and send stream, using the name to determine the content type * @param newDataStream If not set already, the contentType will be obtained from the name of this stream @@ -185,23 +142,12 @@ class HttpResponse */ String toString() const; - /** - * @brief Tries to present a readable version of the response - * @param res - * @retval String - * @deprecated use `toString()` method or `toString(HttpResponse)` function - */ - static String toString(const HttpResponse& res) SMING_DEPRECATED - { - return res.toString(); - } - private: void setStream(IDataSourceStream* stream); public: - HttpStatus code = HTTP_STATUS_OK; ///< The HTTP status response code - HttpHeaders headers; + HttpStatus code = HTTP_STATUS_OK; ///< The HTTP status response code + HttpHeaders headers; ///< Response headers ReadWriteStream* buffer = nullptr; ///< Internal stream for storing strings and receiving responses IDataSourceStream* stream = nullptr; ///< The body stream }; diff --git a/Sming/Components/Network/src/Network/Http/HttpServerConnection.cpp b/Sming/Components/Network/src/Network/Http/HttpServerConnection.cpp index c6156fd1a5..2dacf1a12a 100644 --- a/Sming/Components/Network/src/Network/Http/HttpServerConnection.cpp +++ b/Sming/Components/Network/src/Network/Http/HttpServerConnection.cpp @@ -28,6 +28,7 @@ int HttpServerConnection::onMessageBegin(http_parser* parser) response.reset(); // ... and Request + request.reset(); request.setMethod((const HttpMethod)parser->method); // and temp data... diff --git a/Sming/Components/Network/src/Network/Http/HttpServerConnection.h b/Sming/Components/Network/src/Network/Http/HttpServerConnection.h index 7c76aeb76d..82a2fae9d5 100644 --- a/Sming/Components/Network/src/Network/Http/HttpServerConnection.h +++ b/Sming/Components/Network/src/Network/Http/HttpServerConnection.h @@ -18,7 +18,7 @@ #include -/** @ingroup http +/** @ingroup httpserver * @brief Provides http server connection * @{ */ diff --git a/Sming/Components/Network/src/Network/Http/Websocket/WebsocketConnection.h b/Sming/Components/Network/src/Network/Http/Websocket/WebsocketConnection.h index 6c285e95dd..fc5b32350f 100644 --- a/Sming/Components/Network/src/Network/Http/Websocket/WebsocketConnection.h +++ b/Sming/Components/Network/src/Network/Http/Websocket/WebsocketConnection.h @@ -43,6 +43,9 @@ using WebsocketDelegate = Delegate; using WebsocketMessageDelegate = Delegate; using WebsocketBinaryDelegate = Delegate; +/** + * @brief Current state of Websocket connection + */ enum WsConnectionState { eWSCS_Ready, eWSCS_Open, @@ -68,7 +71,7 @@ class WebsocketConnection /** * @brief Constructs a websocket connection on top of http client or server connection * @param connection the transport connection - * @param isClientConnection true when the passed connection is an http client conneciton + * @param isClientConnection true when the passed connection is an http client connection */ WebsocketConnection(HttpConnection* connection, bool isClientConnection = true); @@ -153,7 +156,7 @@ class WebsocketConnection } /** - * @brief Closes a websocket connection (without closing the underlying http connection + * @brief Closes a websocket connection (without closing the underlying http connection) */ void close(); @@ -266,7 +269,7 @@ class WebsocketConnection /** * @brief Sets the underlying (transport ) HTTP connection * @param connection the transport connection - * @param isClientConnection true when the passed connection is an http client conneciton + * @param isClientConnection true when the passed connection is an http client connection */ void setConnection(HttpConnection* connection, bool isClientConnection = true) { diff --git a/Sming/Components/Network/src/Network/HttpClient.h b/Sming/Components/Network/src/Network/HttpClient.h index 80a40fa6f8..9d1e86687b 100644 --- a/Sming/Components/Network/src/Network/HttpClient.h +++ b/Sming/Components/Network/src/Network/HttpClient.h @@ -111,12 +111,6 @@ class HttpClient */ bool send(HttpRequest* request); - /** @deprecated Use `createRequest()` instead */ - HttpRequest* request(const String& url) SMING_DEPRECATED - { - return createRequest(url); - } - /** @brief Helper function to create a new request on a URL * @param url * @retval HttpRequest* diff --git a/Sming/Components/Network/src/Network/HttpServer.h b/Sming/Components/Network/src/Network/HttpServer.h index 9f4ec11a50..7ca2b0b26b 100644 --- a/Sming/Components/Network/src/Network/HttpServer.h +++ b/Sming/Components/Network/src/Network/HttpServer.h @@ -76,36 +76,6 @@ class HttpServer : public TcpServer bodyParsers[toString(mimeType)] = parser; } - /** @deprecated Use `paths.set()` instead */ - void addPath(String path, const HttpPathDelegate& callback) SMING_DEPRECATED - { - paths.set(path, callback); - } - - /** @deprecated Use `paths.set()` instead */ - void addPath(const String& path, const HttpResourceDelegate& onRequestComplete) SMING_DEPRECATED - { - paths.set(path, onRequestComplete); - } - - /** @deprecated Use `paths.set()` instead */ - void addPath(const String& path, HttpResource* resource) SMING_DEPRECATED - { - paths.set(path, resource); - } - - /** @deprecated Use `paths.setDefault()` instead */ - void setDefaultHandler(const HttpPathDelegate& callback) SMING_DEPRECATED - { - paths.setDefault(callback); - } - - /** @deprecated Use `paths.setDefault()` instead */ - void setDefaultResource(HttpResource* resource) SMING_DEPRECATED - { - paths.setDefault(resource); - } - public: /** @brief Maps paths to resources which deal with incoming requests */ HttpResourceTree paths; diff --git a/Sming/Components/Network/src/Network/MqttClient.h b/Sming/Components/Network/src/Network/MqttClient.h index e648e0ea7e..4797229f03 100644 --- a/Sming/Components/Network/src/Network/MqttClient.h +++ b/Sming/Components/Network/src/Network/MqttClient.h @@ -38,23 +38,11 @@ enum MqttClientState { eMCS_Ready = 0, eMCS_SendingData }; #define MQTT_FLAG_RETAINED 1 -#ifndef MQTT_NO_COMPAT -#define MQTT_MAX_BUFFER_SIZE MQTT_PAYLOAD_LENGTH ///< @deprecated -#define MQTT_MSG_PUBREC MQTT_TYPE_PUBREC ///< @deprecated -#endif - class MqttClient; using MqttDelegate = Delegate; using MqttRequestQueue = ObjectQueue; -#ifndef MQTT_NO_COMPAT -/** @deprecated Use MqttDelegate instead */ -using MqttStringSubscriptionCallback = Delegate; -/** @deprecated Use MqttDelegate instead */ -using MqttMessageDeliveredCallback = Delegate; -#endif - class MqttClient : protected TcpClient { public: @@ -103,12 +91,43 @@ class MqttClient : protected TcpClient */ bool connect(const Url& url, const String& uniqueClientName); + /** + * @brief Publish a message + * @param topic + * @param message Message content as String + * @param flags Optional flags + * @retval bool + */ bool publish(const String& topic, const String& message, uint8_t flags = 0); + + /** + * @brief Publish a message + * @param topic + * @param message Message content as read-only stream + * @param flags Optional flags + * @retval bool + */ bool publish(const String& topic, IDataSourceStream* stream, uint8_t flags = 0); + /** + * @brief Subscribe to a topic + * @param topic + * @retval bool + */ bool subscribe(const String& topic); + + /** + * @brief Unsubscribe from a topic + * @param topic + * @retval bool + */ bool unsubscribe(const String& topic); + /** + * @brief Register a callback function to be invoked on incoming event notification + * @param type Type of event to be notified of + * @param handler The callback. Pass nullptr to cancel callback. + */ void setEventHandler(mqtt_type_t type, MqttDelegate handler) { eventHandlers[type] = handler; @@ -193,57 +212,6 @@ class MqttClient : protected TcpClient using TcpClient::getRemoteIp; using TcpClient::getRemotePort; -#ifndef MQTT_NO_COMPAT - /** - * @deprecated: Use setWill(const String& topic, const String& message,uint8_t flags) instead - */ - bool setWill(const String& topic, const String& message, int QoS, bool retained = false) SMING_DEPRECATED - { - uint8_t flags = (uint8_t)(retained + (QoS << 1)); - return setWill(topic, message, flags); - } - - /** - * @removed - * bool publish(String& topic, String& message, bool retained = false) - * Use publish(const String& topic, const String& message, uint8_t flags = 0) instead. - */ - - /** - * @deprecated: Use publish(const String& topic, const String& message, uint8_t flags = 0) instead. - * If you want to have a callback that should be triggered on successful delivery of messages - * then use setEventHandler(MQTT_TYPE_PUBACK, youCallback) instead. - */ - bool publishWithQoS(const String& topic, const String& message, int QoS, bool retained = false, - MqttMessageDeliveredCallback onDelivery = nullptr) SMING_DEPRECATED - { - if(onDelivery) { - if(QoS == 1) { - setEventHandler(MQTT_TYPE_PUBACK, onPuback); - this->onDelivery = onDelivery; - } else if(QoS == 2) { - setEventHandler(MQTT_TYPE_PUBREC, onPuback); - this->onDelivery = onDelivery; - } else { - debug_w("No callback is set for QoS == 0"); - } - } - - uint8_t flags = (uint8_t)(retained + (QoS << 1)); - return publish(topic, message, flags); - } - - /** - * @brief Provide a function to be called when a message is received from the broker - * @deprecated: Use setEventHandler(MQTT_TYPE_PUBLISH, MqttDelegate handler) instead. - */ - void setCallback(MqttStringSubscriptionCallback subscriptionCallback = nullptr) SMING_DEPRECATED - { - this->subscriptionCallback = subscriptionCallback; - setEventHandler(MQTT_TYPE_PUBLISH, onPublish); - } -#endif - protected: void onReadyToSendData(TcpConnectionEvent sourceEvent) override; void onFinished(TcpClientState finishState) override; @@ -260,54 +228,6 @@ class MqttClient : protected TcpClient static int staticOnMessageEnd(void* user_data, mqtt_message_t* message); int onMessageEnd(mqtt_message_t* message); -#ifndef MQTT_NO_COMPAT - /** @deprecated This method is only for compatibility with the previous release and will be removed soon. */ - static int onPuback(MqttClient& client, mqtt_message_t* message) - { - if(!message) { - return 1; - } - - if(client.onDelivery) { - uint16_t msgId = 0; - if(message->common.type == MQTT_TYPE_PUBACK) { - msgId = message->puback.message_id; - } else if(message->common.type == MQTT_TYPE_PUBREC) { - msgId = message->pubrec.message_id; - } - - if(msgId) { - client.onDelivery(msgId, (int)message->common.type); - } - } - - return 0; - } - - /** @deprecated This method is only for compatibility with the previous release and will be removed soon. */ - static int onPublish(MqttClient& client, mqtt_message_t* message) - { - if(message == nullptr) { - return -1; - } - - if(message->common.length > MQTT_PAYLOAD_LENGTH) { - return -2; - } - - if(client.subscriptionCallback) { - String topic = String((const char*)message->publish.topic_name.data, message->publish.topic_name.length); - String content; - if(message->publish.content.data) { - content.concat((const char*)message->publish.content.data, message->publish.content.length); - } - client.subscriptionCallback(topic, content); - } - - return 0; - } -#endif - private: Url url; @@ -320,7 +240,7 @@ class MqttClient : protected TcpClient MqttClientState state = eMCS_Ready; MqttPayloadParserState payloadState = {}; - // keep-alives and pings + // keep-alive and ping uint16_t keepAlive = 60; uint16_t pingRepeatTime = 20; ///< pingRepeatTime should be <= keepAlive OneShotElapseTimer pingTimer; @@ -343,11 +263,6 @@ class MqttClient : protected TcpClient * | * --- set when connected ... */ - -#ifndef MQTT_NO_COMPAT - SMING_DEPRECATED MqttMessageDeliveredCallback onDelivery = nullptr; ///< @deprecated - SMING_DEPRECATED MqttStringSubscriptionCallback subscriptionCallback = nullptr; ///< @deprecated -#endif }; /** @} */ diff --git a/Sming/Components/Network/src/Network/NetUtils.cpp b/Sming/Components/Network/src/Network/NetUtils.cpp index f8aed2765a..356b01735b 100644 --- a/Sming/Components/Network/src/Network/NetUtils.cpp +++ b/Sming/Components/Network/src/Network/NetUtils.cpp @@ -8,10 +8,10 @@ * ****/ -#include #include "NetUtils.h" #include #include +#include namespace { diff --git a/Sming/Components/Network/src/Network/NtpClient.cpp b/Sming/Components/Network/src/Network/NtpClient.cpp index ed49a6d819..ec75165867 100644 --- a/Sming/Components/Network/src/Network/NtpClient.cpp +++ b/Sming/Components/Network/src/Network/NtpClient.cpp @@ -11,7 +11,7 @@ #include "NtpClient.h" #include "Platform/Station.h" #include "SystemClock.h" -#include +#include NtpClient::NtpClient(const String& reqServer, unsigned reqIntervalSeconds, NtpTimeResultDelegate delegateFunction) { diff --git a/Sming/Components/Network/src/Network/SmtpClient.h b/Sming/Components/Network/src/Network/SmtpClient.h index 45be230ecc..91839a7b5c 100644 --- a/Sming/Components/Network/src/Network/SmtpClient.h +++ b/Sming/Components/Network/src/Network/SmtpClient.h @@ -141,7 +141,7 @@ class SmtpClient : protected TcpClient } /** - * @brief Sends a quit command to the server and closes the TCP conneciton + * @brief Sends a quit command to the server and closes the TCP connection */ void quit(); diff --git a/Sming/Components/Network/src/Network/TcpConnection.cpp b/Sming/Components/Network/src/Network/TcpConnection.cpp index 528abb68cd..0aae89fc2e 100644 --- a/Sming/Components/Network/src/Network/TcpConnection.cpp +++ b/Sming/Components/Network/src/Network/TcpConnection.cpp @@ -10,10 +10,10 @@ #include "TcpConnection.h" #include - #include #include "NetUtils.h" #include +#include #define debug_tcp_e(fmt, ...) debug_e("TCP %p " fmt, this, ##__VA_ARGS__) #define debug_tcp_w(fmt, ...) debug_w("TCP %p " fmt, this, ##__VA_ARGS__) diff --git a/Sming/Components/Network/src/Network/TcpConnection.h b/Sming/Components/Network/src/Network/TcpConnection.h index a930567559..d2f023df2f 100644 --- a/Sming/Components/Network/src/Network/TcpConnection.h +++ b/Sming/Components/Network/src/Network/TcpConnection.h @@ -17,6 +17,7 @@ #include #include +#include #define NETWORK_DEBUG @@ -29,7 +30,6 @@ enum TcpConnectionEvent { eTCE_Poll, //< Occurs on waiting }; -struct pbuf; class String; class IDataSourceStream; class TcpConnection; @@ -58,7 +58,7 @@ class TcpConnection : public IpConnection /** @brief Writes string data directly to the TCP buffer * @param data null terminated string * @param apiflags TCP_WRITE_FLAG_COPY, TCP_WRITE_FLAG_MORE - * @retval int negative on error, 0 when retry is needed or possitive on success + * @retval int negative on error, 0 when retry is needed or positive on success */ int writeString(const char* data, uint8_t apiflags = TCP_WRITE_FLAG_COPY) { @@ -68,7 +68,7 @@ class TcpConnection : public IpConnection /** @brief Writes string data directly to the TCP buffer * @param data * @param apiflags TCP_WRITE_FLAG_COPY, TCP_WRITE_FLAG_MORE - * @retval int negative on error, 0 when retry is needed or possitive on success + * @retval int negative on error, 0 when retry is needed or positive on success */ int writeString(const String& data, uint8_t apiflags = TCP_WRITE_FLAG_COPY) { @@ -79,14 +79,14 @@ class TcpConnection : public IpConnection * @param data * @param len * @param apiflags TCP_WRITE_FLAG_COPY, TCP_WRITE_FLAG_MORE - * @retval int negative on error, 0 when retry is needed or possitive on success + * @retval int negative on error, 0 when retry is needed or positive on success */ virtual int write(const char* data, int len, uint8_t apiflags = TCP_WRITE_FLAG_COPY); /** @brief Writes stream data directly to the TCP buffer * @param stream * @param apiflags TCP_WRITE_FLAG_COPY, TCP_WRITE_FLAG_MORE - * @retval int negative on error, 0 when retry is needed or possitive on success + * @retval int negative on error, 0 when retry is needed or positive on success */ int write(IDataSourceStream* stream); @@ -207,7 +207,7 @@ class TcpConnection : public IpConnection static err_t staticOnPoll(void* arg, tcp_pcb* tcp); static void closeTcpConnection(tcp_pcb* tpcb); - inline void checkSelfFree() + void checkSelfFree() { if(tcp == nullptr && autoSelfDestruct) { delete this; diff --git a/Sming/Components/Network/src/Network/TcpServer.cpp b/Sming/Components/Network/src/Network/TcpServer.cpp index 8e761c08b6..926a750c0e 100644 --- a/Sming/Components/Network/src/Network/TcpServer.cpp +++ b/Sming/Components/Network/src/Network/TcpServer.cpp @@ -96,7 +96,7 @@ err_t TcpServer::onAccept(tcp_pcb* clientTcp, err_t err) connections.add(client); debug_d("Opening connection. Total connections: %d", connections.count()); - onClient((TcpClient*)client); + onClient(reinterpret_cast(client)); return ERR_OK; } diff --git a/Sming/Components/Network/src/Network/TelnetServer.h b/Sming/Components/Network/src/Network/TelnetServer.h index d719c6346c..04942e3bac 100644 --- a/Sming/Components/Network/src/Network/TelnetServer.h +++ b/Sming/Components/Network/src/Network/TelnetServer.h @@ -19,7 +19,6 @@ #pragma once -#include #include "TcpClient.h" #include "TcpServer.h" #include "SystemClock.h" @@ -34,7 +33,6 @@ using TelnetServerCommandDelegate = Delegate bool UdpConnection::initialize(udp_pcb* pcb) { diff --git a/Sming/Components/Network/src/Network/UdpConnection.h b/Sming/Components/Network/src/Network/UdpConnection.h index 9406132e42..3cbf27490c 100644 --- a/Sming/Components/Network/src/Network/UdpConnection.h +++ b/Sming/Components/Network/src/Network/UdpConnection.h @@ -11,6 +11,7 @@ #pragma once #include +#include /** @defgroup udp UDP * @brief Provides base for UDP clients or services diff --git a/Sming/Components/Network/src/Network/Url.cpp b/Sming/Components/Network/src/Network/Url.cpp index 1eaa1c3515..b23df5aaac 100644 --- a/Sming/Components/Network/src/Network/Url.cpp +++ b/Sming/Components/Network/src/Network/Url.cpp @@ -13,7 +13,8 @@ #include "Url.h" #include "libyuarel/yuarel.h" #include -#include "Print.h" +#include +#include /** * @brief Common URI scheme strings diff --git a/Sming/Components/Network/src/Network/Url.h b/Sming/Components/Network/src/Network/Url.h index 9da50d6091..9a2f4977d5 100644 --- a/Sming/Components/Network/src/Network/Url.h +++ b/Sming/Components/Network/src/Network/Url.h @@ -32,7 +32,7 @@ * Common URL schemes (name, scheme, port) * name: Used for string identifier * scheme: String to be used in a URL, normalised (i.e. lower case) - * port: Offical default port definition for the scheme, 0 if not applicable + * port: Official default port definition for the scheme, 0 if not applicable */ #define URI_SCHEME_MAP(XX) \ XX(HTTP, http, 80) \ @@ -177,8 +177,6 @@ class Url String Fragment; ///< Without '#' }; -typedef Url URL SMING_DEPRECATED; ///< @deprecated Use `Url` instead - inline String toString(const Url& url) { return url.toString(); diff --git a/Sming/Components/Network/src/Network/WebsocketClient.h b/Sming/Components/Network/src/Network/WebsocketClient.h index a62e0996af..3952942e0f 100644 --- a/Sming/Components/Network/src/Network/WebsocketClient.h +++ b/Sming/Components/Network/src/Network/WebsocketClient.h @@ -90,14 +90,6 @@ class WebsocketClient : protected WebsocketConnection sslInitHandler = handler; } - /** @brief Disconnects websocket client from server - * @deprecated Use `close()` instead - */ - void disconnect() SMING_DEPRECATED - { - close(); - } - protected: int verifyKey(HttpConnection& connection, HttpResponse& response); diff --git a/Sming/Components/Network/src/Platform/AccessPoint.h b/Sming/Components/Network/src/Platform/AccessPoint.h index 929eff0f14..a6655c62de 100644 --- a/Sming/Components/Network/src/Platform/AccessPoint.h +++ b/Sming/Components/Network/src/Platform/AccessPoint.h @@ -66,7 +66,7 @@ class AccessPointClass */ virtual IpAddress getIP() const = 0; - /** @brief Set WiFi AP IP addres + /** @brief Set WiFi AP IP address * @param address New IP address for WiFi AP * @retval bool True on success */ diff --git a/Sming/Components/Network/src/Platform/Station.cpp b/Sming/Components/Network/src/Platform/Station.cpp index 350e0ad723..1327a176a4 100644 --- a/Sming/Components/Network/src/Platform/Station.cpp +++ b/Sming/Components/Network/src/Platform/Station.cpp @@ -9,6 +9,7 @@ ****/ #include "Station.h" +#include String toString(WpsStatus status) { diff --git a/Sming/Components/Network/src/Platform/Station.h b/Sming/Components/Network/src/Platform/Station.h index 19e68d40da..aa64fba07f 100644 --- a/Sming/Components/Network/src/Platform/Station.h +++ b/Sming/Components/Network/src/Platform/Station.h @@ -244,7 +244,7 @@ class StationClass /** @brief Set WiFi station IP parameters * @param address IP address * @param netmask Network mask - * @param gateway Default gatway + * @param gateway Default gateway * @retval bool True on success */ virtual bool setIP(IpAddress address, IpAddress netmask, IpAddress gateway) = 0; @@ -295,14 +295,6 @@ class StationClass */ virtual bool wpsConfigStart(WPSConfigDelegate callback = nullptr) = 0; - /** @brief Start WiFi station by WPS method - * @deprecated Use `wpsConfigStart()` - */ - bool beginWPSConfig() SMING_DEPRECATED - { - return wpsConfigStart(nullptr); - } - /** @brief Stop WiFi station WPS configuration */ virtual void wpsConfigStop() = 0; diff --git a/Sming/Components/Network/src/Platform/WifiEvents.h b/Sming/Components/Network/src/Platform/WifiEvents.h index faf8989972..c5efffad8b 100644 --- a/Sming/Components/Network/src/Platform/WifiEvents.h +++ b/Sming/Components/Network/src/Platform/WifiEvents.h @@ -150,7 +150,7 @@ using AccessPointDisconnectDelegate = Delegate; diff --git a/Sming/Arch/Esp8266/Components/esp8266/include/espinc/lwip_includes.h b/Sming/Components/Network/src/lwip_includes.h similarity index 58% rename from Sming/Arch/Esp8266/Components/esp8266/include/espinc/lwip_includes.h rename to Sming/Components/Network/src/lwip_includes.h index a711646608..ad2d0b5f9f 100644 --- a/Sming/Arch/Esp8266/Components/esp8266/include/espinc/lwip_includes.h +++ b/Sming/Components/Network/src/lwip_includes.h @@ -7,10 +7,26 @@ #pragma once +#ifdef ARCH_ESP8266 + +// ESP SDK config +#define LWIP_OPEN_SRC + +#ifdef ENABLE_ESPCONN +#include +#endif + +#endif + +#ifdef ARCH_ESP32 +#include +#endif + #include #include #include #include +#include #include #include #include diff --git a/Sming/Components/Storage/README.rst b/Sming/Components/Storage/README.rst index c4643c1408..4b86403ff0 100644 --- a/Sming/Components/Storage/README.rst +++ b/Sming/Components/Storage/README.rst @@ -308,7 +308,7 @@ Binary partition table ---------------------- Sming uses the same binary partition table structure as ESP-IDF, located immediately after the boot sector. -However, it is organised slighly differently to allow partitions to be registered for multiple storage devices. +However, it is organised slightly differently to allow partitions to be registered for multiple storage devices. Entries are fixed 32-byte structures, :cpp:class:`Storage::esp_partition_info_t`, organised as follows: @@ -355,7 +355,7 @@ It defines methods which should be used to read/write/erase the partition conten Each partition has an associated :cpp:class:`Storage::Device`. This is usually :cpp:var:`Storage::spiFlash` for the main flash device. -Other devices must be registed via :cpp:func:`Storage::PartitionTable::registerStorageDevice`. +Other devices must be registered via :cpp:func:`Storage::PartitionTable::registerStorageDevice`. You can query partition entries from a Storage object directly, for example:: diff --git a/Sming/Components/Storage/Tools/hwconfig/common.py b/Sming/Components/Storage/Tools/hwconfig/common.py index 8b644def8d..af10921d7c 100644 --- a/Sming/Components/Storage/Tools/hwconfig/common.py +++ b/Sming/Components/Storage/Tools/hwconfig/common.py @@ -11,27 +11,28 @@ quiet = False def status(msg): - """ Print status message to stderr """ + """Print status message to stderr.""" if not quiet: critical(msg) def critical(msg): - """ Print critical message to stderr """ + """Print critical message to stderr.""" sys.stderr.write(msg) sys.stderr.write('\n') def fixpath(path): - """ Paths in Windows can get a little weird """ + """Paths in Windows can get a little weird """ if len(path) > 2 and path[1] != ':' and platform.system() == 'Windows' and path[2] == '/': return path[1] + ':' + path[2:] return path def parse_int(v, keywords=None): - """Generic parser for integer fields - int(x,0) with provision for - k/m/K/M suffixes and 'keyword' value lookup. + """Generic parser for integer fields. + + int(x,0) with provision for k/m/K/M suffixes and 'keyword' value lookup. """ if not isinstance(v, str): return v @@ -50,8 +51,7 @@ def parse_int(v, keywords=None): def stringnum(s): - """Return number if s contains only digits, otherwise return the string - """ + """Return number if s contains only digits, otherwise return the string.""" return int(s) if s.isdigit() else s diff --git a/Sming/Components/Storage/Tools/hwconfig/config.py b/Sming/Components/Storage/Tools/hwconfig/config.py index cb273d7eb3..2056c49461 100644 --- a/Sming/Components/Storage/Tools/hwconfig/config.py +++ b/Sming/Components/Storage/Tools/hwconfig/config.py @@ -93,8 +93,7 @@ def __str__(self): @classmethod def from_name(cls, name): - """Create configuration given its name and resolve options - """ + """Create configuration given its name and resolve options.""" config = Config() config.load(name) options = os.environ.get('HWCONFIG_OPTS', '').replace(' ', '') @@ -105,28 +104,28 @@ def from_name(cls, name): return config @classmethod - def from_json(cls, json, options = []): + def from_json(cls, json, options = None): config = Config() config.parse_dict(copy.deepcopy(json)) - config.parse_options(options) + if options is not None: + config.parse_options(options) config.resolve_expressions() config.partitions.sort() return config def load(self, name): - """Load a configuration recursively - """ + """Load a configuration recursively.""" filename = find_config(name) self.depends.append(filename) data = json_load(filename) self.parse_dict(data) def parse_options(self, options): - """Apply any specified options, each option is applied only once + """Apply any specified options. + + Each option can be applied more than once to ensure overrides work as expected. """ for option in options: - if option in self.options: - continue self.options.append(option) data = self.option_library.get(option) if data is None: diff --git a/Sming/Components/Storage/Tools/hwconfig/editor.py b/Sming/Components/Storage/Tools/hwconfig/editor.py index 76ccead9d5..89f0c1a1a5 100644 --- a/Sming/Components/Storage/Tools/hwconfig/editor.py +++ b/Sming/Components/Storage/Tools/hwconfig/editor.py @@ -32,15 +32,13 @@ } def read_property(obj, name): - """Read an object property, preferring string representation - """ + """Read an object property, preferring string representation.""" value = getattr(obj, name + '_str', None) return getattr(obj, name, None) if value is None else value() def get_dict_value(dict, key, default): - """Read dictionary value, creating one if it doesn't exist - """ + """Read dictionary value, creating one if it doesn't exist.""" if not key in dict: dict[key] = default return dict[key] @@ -67,13 +65,6 @@ def __init__(self): # Don't need this information until user requests it threading.Thread(target=self._resolvePathVars).start() - def getRelativePath(self, path): - try: - res = os.path.relpath(path) - return res.replace('\\', '/') - except Exception: - return path - def resolve_path(self, path): tmp = str(path) while True: @@ -112,16 +103,14 @@ def checkProfilePath(filename): def get_id(obj): - """Get string identifier for a device or partition object - """ + """Get string identifier for a device or partition object.""" if isinstance(obj, partition.Entry): if obj.is_unused(): return obj.device.name + '/' + str(obj.address) return obj.name def resolve_id(config, id): - """Get corresponding device or partition object given the ID value provided from get_id - """ + """Get corresponding device or partition object given the ID value provided from get_id.""" elem = id.split('/') if len(elem) == 2: dev = config.devices.find_by_name(elem[0]) @@ -138,8 +127,7 @@ def resolve_device(config, id): return obj.device def resolve_key(obj, key): - """Resolve dotted key, e.g. 'build.target' refers to 'target' property of 'build' object - """ + """Resolve dotted key, e.g. 'build.target' refers to 'target' property of 'build' object.""" keys = key.split('.') while len(keys) > 1: k = keys.pop(0) @@ -150,9 +138,33 @@ def resolve_key(obj, key): return obj, keys[0] -class Field: - """Manages widget(s) and associated variable +def verify_config(json_config): + """Raises an exception if any problems are found in the configuration. + + On success, returns a consistently-ordered JSON configuration. """ + cfg = Config.from_json(json_config) + cfg.verify(False) + res = OrderedDict() + for key in config.schema['Config']['properties'].keys(): + if key in json_config: + value = json_config[key] + if key == 'devices': + names = list(dev.name for dev in cfg.devices) + elif key == 'partitions': + names = list(p.name for p in cfg.map()) + else: + res[key] = value + continue + output = res[key] = OrderedDict() + for n in names: + if n in value: + output[n] = value[n] + return res + + +class Field: + """Manages widget(s) and associated variable.""" def __init__(self, name, schema, var, widget): self.name = name self.schema = schema @@ -219,13 +231,12 @@ def setPath(self, path): except Exception: None values = list(values) - values.sort(key=lambda v: len(v)) + values.sort(key=len) self.widget.configure(values=values) return path def addScale(self, min, max, on_change): - """Add scale controls for address/size fields - """ + """Add scale controls for address/size fields.""" scale = self.scale = tk.Scale( self.widget.master, orient = tk.HORIZONTAL, @@ -305,8 +316,7 @@ def is_visible(self): class EditState(dict): - """Manage details of Config/Device/Partition editing using dictionary of Field objects - """ + """Manage details of Config/Device/Partition editing using dictionary of Field objects.""" def __init__(self, editor, objectType, dictName, obj): super().__init__(self) self.editor = editor @@ -645,7 +655,7 @@ def apply(self): if len(json_dict) == 0: del json_config[self.dictName] - self.editor.json = self.editor.verify_config(json_config) + self.editor.json = verify_config(json_config) if new_name is not None: self.name = new_name if self.objectType != 'Config': @@ -675,7 +685,7 @@ def delete(self): self.editor.reload() def get_property(self, name): - """Get field property from schema""" + """Get field property from schema.""" prop = self.schema['properties'].get(name, None) if prop is None: prop = virtual_fields[name] @@ -825,7 +835,7 @@ def is_small(p): # So, fix a limit for the drawn size of each partition (in bytes) # Marker ticks will be drawn according to this scale drawsize = 0 # Equivalent size (in bytes) for the partition - x_device_end = 0 # Determines final x co-ordinate for end of device memory + x_device_end = 0 # Determines final x coordinate for end of device memory MIN_TICK_SPACING = 100 def draw_tick(x, addr): @@ -847,7 +857,7 @@ def draw_tick(x, addr): self.items[get_id(self.device)] = device_item for p in partitions: - # Starting x co-ordinate for this partition depends on scale of previous partition + # Starting x coordinate for this partition depends on scale of previous partition r = copy.copy(r_prev) r.setHeight(ROW_HEIGHT) if part_prev is not None: @@ -1205,7 +1215,7 @@ def configure(event): def apply(*args): try: json_config = json_loads(self.jsonEditor.get('1.0', 'end')) - self.json = self.verify_config(json_config) + self.json = verify_config(json_config) self.updateWindowTitle() self.reload() except Exception as err: @@ -1241,13 +1251,11 @@ def user_error(self, err): messagebox.showerror(type(err).__name__, err) def getBaseConfig(self): - """Load the base configuration - """ + """Load the base configuration.""" return Config.from_json(self.json_base_config) - + def getOptionBaseConfig(self): - """Load the base configuration with currently selected options applied - """ + """Load the base configuration with currently selected options applied.""" return Config.from_json(self.json_base_config, self.json.get('options', [])) def loadConfig(self, filename): @@ -1278,29 +1286,6 @@ def updateWindowTitle(self): name = '"' + name + '"' self.main.title(self.config.arch + ' ' + name + ' - ' + app_name) - def verify_config(self, json_config): - """Raises an exception if any problems are found in the configuration. - On success, returns a consistently-ordered JSON configuration. - """ - cfg = Config.from_json(json_config) - cfg.verify(False) - res = OrderedDict() - for key in config.schema['Config']['properties'].keys(): - if key in json_config: - value = json_config[key] - if key == 'devices': - names = list(dev.name for dev in cfg.devices) - elif key == 'partitions': - names = list(p.name for p in cfg.map()) - else: - res[key] = value - continue - output = res[key] = OrderedDict() - for n in names: - if n in value: - output[n] = value[n] - return res - def reset(self): self.tree.clear() self.map.clear() @@ -1312,6 +1297,7 @@ def reset(self): self.updateWindowTitle() class Used: + """Stores space used for a file referenced by partition.""" def __init__(self): self.text = '' self.size = 0 diff --git a/Sming/Components/Storage/Tools/hwconfig/hwconfig.py b/Sming/Components/Storage/Tools/hwconfig/hwconfig.py index 5f195737a4..8da2897c33 100644 --- a/Sming/Components/Storage/Tools/hwconfig/hwconfig.py +++ b/Sming/Components/Storage/Tools/hwconfig/hwconfig.py @@ -3,7 +3,7 @@ # Sming hardware configuration tool # -import common, argparse, os, partition +import common, argparse, os, partition, json from common import * from config import Config from config import schema as config_schema @@ -49,7 +49,7 @@ def handle_flashcheck(args, config, part): raise InputError("No partition contains address 0x%08x" % addr) if part.address != addr: raise InputError("Address 0x%08x is within partition '%s', not at start (0x%08x)" % (addr, part.name, part.address)) - filesize = os.path.getsize(filename) + filesize = os.path.getsize(fixpath(filename)) if filesize > part.size: raise InputError("File '%s' is 0x%08x bytes, too big for partition '%s' (0x%08x bytes)" % (os.path.basename(filename), filesize, part.name, part.size)) @@ -64,7 +64,10 @@ def handle_partgen(args, config, part): def handle_expr(args, config, part): # Evaluate expression against configuration data - return str(eval(args.expr)).encode() + res = eval(args.expr) + if isinstance(res, dict): + return json.dumps(res).encode() + return str(res).encode() def main(): diff --git a/Sming/Components/Storage/Tools/hwconfig/partition.py b/Sming/Components/Storage/Tools/hwconfig/partition.py index bd275e430a..6585d81544 100644 --- a/Sming/Components/Storage/Tools/hwconfig/partition.py +++ b/Sming/Components/Storage/Tools/hwconfig/partition.py @@ -52,6 +52,9 @@ }, "Host": { APP_TYPE: 0x1000, + }, + "Rp2040": { + APP_TYPE: 0x1000, } } @@ -129,6 +132,7 @@ def parse_subtype(ptype, value): class Table(list): def __init__(self, devices): + """Create table of partitions against list of registered devices.""" super().__init__(self) self.devices = devices @@ -180,8 +184,7 @@ def buildVars(self): return dict def __getitem__(self, item): - """Allow partition table access by name or index - """ + """Allow partition table access by name or index.""" if isinstance(item, str): p = self.find_by_name(item) if p is None: @@ -190,8 +193,7 @@ def __getitem__(self, item): return super().__getitem__(item) def find_by_type(self, ptype, subtype): - """Return a partition by type & subtype, returns None if not found - """ + """Return a partition by type & subtype, returns None if not found.""" # convert ptype & subtypes names (if supplied this way) to integer values try: ptype = TYPES[ptype] @@ -228,8 +230,7 @@ def find_by_address(self, device, addr): return None def verify(self, config, secure): - """Verify partition layout - """ + """Verify partition layout.""" # verify each partition individually for p in self: p.verify(config.arch, secure) @@ -276,8 +277,7 @@ def verify(self, config, secure): last = p def parse_binary(self, b, devices): - """Construct partition table object from binary image - """ + """Construct partition table object from binary image.""" dev = None md5 = hashlib.md5() for o in range(0, len(b), PARTITION_ENTRY_SIZE): @@ -309,8 +309,7 @@ def parse_binary(self, b, devices): raise InputError("Partition table is missing an end-of-table marker") def to_binary(self, devices): - """Create binary image of partition table - """ + """Create binary image of partition table.""" dev_count = 0 dev = None result = b"" @@ -318,7 +317,7 @@ def to_binary(self, devices): if e.device != dev: if dev_count == 1: result += MD5_PARTITION_BEGIN + hashlib.md5(result).digest() - # esp32 bootloader will see this as end of partition table + # esp32 bootloader will see this as end of partition table result += struct.pack(Entry.STRUCT_FORMAT, b"\xff\xff", 0xff, 0xff, @@ -365,8 +364,7 @@ def __init__(self, device=None, name="", address=None, size=None, ptype=None, su self.unused_after = 0 def parse_dict(self, data, devices): - """Construct a partition object from JSON definition - """ + """Construct a partition object from JSON definition.""" try: # Sort out type information first v = data.pop('type', None) @@ -426,7 +424,7 @@ def buildVars(self): dict.pop('build', None) for k, v in dict.items(): k = "PARTITION_%s_%s" % (self.name, k.upper()) - res[k] = int(v) if type(v) is bool else v + res[k] = int(v) if isinstance(v, bool) else v return res @@ -558,8 +556,8 @@ def to_binary(self): class Map(Table): - """Contiguous map of flash memory - """ + + """Contiguous map of flash memory.""" def __init__(self, config): def add(table, device, name, address, size, subtype): entry = Entry(device, name, address, size, INTERNAL_TYPE, subtype) @@ -576,7 +574,8 @@ def add_unused(table, device, address, last_end): # Take copy of source partitions and add internal ones to appear in the map partitions = copy.copy(config.partitions) if config.partition_table_offset != 0: - add(partitions, device, 'Boot Sector', 0, config.bootloader_size, INTERNAL_BOOT_SECTOR) + if config.bootloader_size != 0: + add(partitions, device, 'Boot Sector', 0, config.bootloader_size, INTERNAL_BOOT_SECTOR) add(partitions, device, 'Partition Table', config.partition_table_offset, PARTITION_TABLE_SIZE, INTERNAL_PARTITION_TABLE) # Devices with no defined partitions diff --git a/Sming/Components/Storage/Tools/hwconfig/storage.py b/Sming/Components/Storage/Tools/hwconfig/storage.py index c72c0fddda..410e51486b 100644 --- a/Sming/Components/Storage/Tools/hwconfig/storage.py +++ b/Sming/Components/Storage/Tools/hwconfig/storage.py @@ -49,6 +49,7 @@ def buildVars(self): return dict def __getitem__(self, item): + """Access entries by name or index.""" if isinstance(item, str): d = self.find_by_name(item) if d is None: @@ -67,6 +68,8 @@ def verify(self): dev.verify() class Device(object): + + """Initialise a storage device.""" def __init__(self, name, stype = 0, size = 0): self.name = name self.type = parse_type(stype) diff --git a/Sming/Components/Storage/component.mk b/Sming/Components/Storage/component.mk index cc10fb3a10..b1691e2aaf 100644 --- a/Sming/Components/Storage/component.mk +++ b/Sming/Components/Storage/component.mk @@ -7,8 +7,10 @@ COMPONENT_RELINK_VARS := PARTITION_TABLE_OFFSET CONFIG_VARS += HWCONFIG HWCONFIG_OPTS ifndef HWCONFIG override HWCONFIG := standard +ifeq (,$(filter s,$(MAKEFLAGS))) $(info Using configuration '$(HWCONFIG)') endif +endif # Directories to search for hardware config HWCONFIG_DIRS := $(PROJECT_DIR) $(COMPONENT_SEARCH_DIRS) $(ARCH_BASE) $(SMING_HOME) @@ -70,7 +72,6 @@ $(error Hardware configuration error) else ifneq ($(SMING_ARCH),$(SMING_ARCH_HW)) $(error Hardware configuration is for arch $(SMING_ARCH_HW), does not match SMING_ARCH ($(SMING_ARCH))) endif -COMPONENT_CXXFLAGS := -DPARTITION_TABLE_OFFSET=$(PARTITION_TABLE_OFFSET) COMPONENT_CPPFLAGS := -DPARTITION_TABLE_OFFSET=$(PARTITION_TABLE_OFFSET) # Function to evaluate expression against config diff --git a/Sming/Components/Storage/src/SpiFlash.cpp b/Sming/Components/Storage/src/SpiFlash.cpp index ee62586b80..62a764600b 100644 --- a/Sming/Components/Storage/src/SpiFlash.cpp +++ b/Sming/Components/Storage/src/SpiFlash.cpp @@ -11,6 +11,7 @@ #include "include/Storage/SpiFlash.h" #include "include/Storage/partition_info.h" #include +#include namespace Storage { diff --git a/Sming/Components/Storage/src/include/Storage/Partition.h b/Sming/Components/Storage/src/include/Storage/Partition.h index bc9ddc69bf..d0f26c36e1 100644 --- a/Sming/Components/Storage/src/include/Storage/Partition.h +++ b/Sming/Components/Storage/src/include/Storage/Partition.h @@ -161,19 +161,25 @@ class Partition /** * @name Confirm partition is of the expected type + * @{ + */ + + /** + * @brief Strong C++ type value * @param type Expected partition type * @param subtype Expected partition sub-type * @retval bool true if type is OK, false if not. * Logs debug messages on failure. - * @{ */ bool verify(Type type, uint8_t subtype) const; + /// Weak 'type' value bool verify(uint8_t type, uint8_t subtype) const { return verify(Type(type), subtype); } + /// Derive type from subtype, expressed as strong C++ enum template bool verify(T subType) const { return verify(Type(T::partitionType), uint8_t(subType)); @@ -265,9 +271,9 @@ class Partition /** * @brief Obtain partition size - * @retval uint32_t Size in bytes + * @retval size_t Size in bytes */ - uint32_t size() const + size_t size() const { return mPart ? mPart->size : 0; } diff --git a/Sming/Components/Storage/src/include/Storage/PartitionTable.h b/Sming/Components/Storage/src/include/Storage/PartitionTable.h index 5acfc135bd..49cd59bf10 100644 --- a/Sming/Components/Storage/src/include/Storage/PartitionTable.h +++ b/Sming/Components/Storage/src/include/Storage/PartitionTable.h @@ -25,6 +25,9 @@ class PartitionTable /** * @name Partition search * @{ + */ + + /** * * @brief Find partitions based on one or more parameters * @param type Partition type @@ -36,6 +39,7 @@ class PartitionTable return Iterator(mDevice, type, subType); } + /// C++ subtype definition provides partition type template Iterator find(T subType) const { return find(Partition::Type(T::partitionType), uint8_t(subType)); diff --git a/Sming/Components/Storage/src/include/Storage/partition_info.h b/Sming/Components/Storage/src/include/Storage/partition_info.h index a4b54c7f62..1cb6fe4a2a 100644 --- a/Sming/Components/Storage/src/include/Storage/partition_info.h +++ b/Sming/Components/Storage/src/include/Storage/partition_info.h @@ -21,7 +21,7 @@ struct esp_partition_info_t { uint8_t subtype; ///< Sub-type for partition (interpretation dependent upon type) uint32_t offset; ///< Start offset uint32_t size; ///< Size of partition in bytes - Storage::Partition::Name name; ///< Unique identifer for entry + Storage::Partition::Name name; ///< Unique identifier for entry Storage::Partition::Flags flags; ///< Various option flags }; diff --git a/Sming/Components/arch_driver/src/include/driver/SerialBuffer.h b/Sming/Components/arch_driver/src/include/driver/SerialBuffer.h index 71a626c900..2fd02a6f64 100644 --- a/Sming/Components/arch_driver/src/include/driver/SerialBuffer.h +++ b/Sming/Components/arch_driver/src/include/driver/SerialBuffer.h @@ -12,7 +12,9 @@ #pragma once -#include +#include +#include +#include /** @brief FIFO buffer used for both receive and transmit data * @note For receive operations, data is written via ISR and read via task diff --git a/Sming/Components/arch_driver/src/include/driver/uart.h b/Sming/Components/arch_driver/src/include/driver/uart.h index 9df0d09753..e568bc606f 100644 --- a/Sming/Components/arch_driver/src/include/driver/uart.h +++ b/Sming/Components/arch_driver/src/include/driver/uart.h @@ -36,12 +36,14 @@ #pragma once +#include +#include +#include + #if defined(__cplusplus) extern "C" { #endif -#include - /** * @defgroup uart_driver UART Driver * @ingroup drivers @@ -53,48 +55,97 @@ extern "C" { #define UART_PIN_DEFAULT (255) ///< Use default pin assignments #define UART_PIN_NO_CHANGE (-1) ///< Use default pin assignments -// Options for `config` argument of uart_init -#define UART_NB_BIT_MASK 0B00001100 -#define UART_NB_BIT_5 0B00000000 -#define UART_NB_BIT_6 0B00000100 -#define UART_NB_BIT_7 0B00001000 -#define UART_NB_BIT_8 0B00001100 - -#define UART_PARITY_MASK 0B00000011 -#define UART_PARITY_NONE 0B00000000 -#define UART_PARITY_EVEN 0B00000010 -#define UART_PARITY_ODD 0B00000011 - -#define UART_NB_STOP_BIT_MASK 0B00110000 -#define UART_NB_STOP_BIT_0 0B00000000 -#define UART_NB_STOP_BIT_1 0B00010000 -#define UART_NB_STOP_BIT_15 0B00100000 -#define UART_NB_STOP_BIT_2 0B00110000 - -#define UART_5N1 (UART_NB_BIT_5 | UART_PARITY_NONE | UART_NB_STOP_BIT_1) -#define UART_6N1 (UART_NB_BIT_6 | UART_PARITY_NONE | UART_NB_STOP_BIT_1) -#define UART_7N1 (UART_NB_BIT_7 | UART_PARITY_NONE | UART_NB_STOP_BIT_1) -#define UART_8N1 (UART_NB_BIT_8 | UART_PARITY_NONE | UART_NB_STOP_BIT_1) -#define UART_5N2 (UART_NB_BIT_5 | UART_PARITY_NONE | UART_NB_STOP_BIT_2) -#define UART_6N2 (UART_NB_BIT_6 | UART_PARITY_NONE | UART_NB_STOP_BIT_2) -#define UART_7N2 (UART_NB_BIT_7 | UART_PARITY_NONE | UART_NB_STOP_BIT_2) -#define UART_8N2 (UART_NB_BIT_8 | UART_PARITY_NONE | UART_NB_STOP_BIT_2) -#define UART_5E1 (UART_NB_BIT_5 | UART_PARITY_EVEN | UART_NB_STOP_BIT_1) -#define UART_6E1 (UART_NB_BIT_6 | UART_PARITY_EVEN | UART_NB_STOP_BIT_1) -#define UART_7E1 (UART_NB_BIT_7 | UART_PARITY_EVEN | UART_NB_STOP_BIT_1) -#define UART_8E1 (UART_NB_BIT_8 | UART_PARITY_EVEN | UART_NB_STOP_BIT_1) -#define UART_5E2 (UART_NB_BIT_5 | UART_PARITY_EVEN | UART_NB_STOP_BIT_2) -#define UART_6E2 (UART_NB_BIT_6 | UART_PARITY_EVEN | UART_NB_STOP_BIT_2) -#define UART_7E2 (UART_NB_BIT_7 | UART_PARITY_EVEN | UART_NB_STOP_BIT_2) -#define UART_8E2 (UART_NB_BIT_8 | UART_PARITY_EVEN | UART_NB_STOP_BIT_2) -#define UART_5O1 (UART_NB_BIT_5 | UART_PARITY_ODD | UART_NB_STOP_BIT_1) -#define UART_6O1 (UART_NB_BIT_6 | UART_PARITY_ODD | UART_NB_STOP_BIT_1) -#define UART_7O1 (UART_NB_BIT_7 | UART_PARITY_ODD | UART_NB_STOP_BIT_1) -#define UART_8O1 (UART_NB_BIT_8 | UART_PARITY_ODD | UART_NB_STOP_BIT_1) -#define UART_5O2 (UART_NB_BIT_5 | UART_PARITY_ODD | UART_NB_STOP_BIT_2) -#define UART_6O2 (UART_NB_BIT_6 | UART_PARITY_ODD | UART_NB_STOP_BIT_2) -#define UART_7O2 (UART_NB_BIT_7 | UART_PARITY_ODD | UART_NB_STOP_BIT_2) -#define UART_8O2 (UART_NB_BIT_8 | UART_PARITY_ODD | UART_NB_STOP_BIT_2) +/** + * @brief Number of UART data bits + */ +enum smg_uart_bits_t { + UART_NB_BIT_5 = 0, + UART_NB_BIT_6 = 1, + UART_NB_BIT_7 = 2, + UART_NB_BIT_8 = 3, +}; + +/** + * @brief UART parity setting + * + * Actually combines two bits: + * bit 1 is set for parity enable, clear if disabled + * bit 0 is set for even parity, clear for odd parity + */ +enum smg_uart_parity_t { + UART_PARITY_NONE = 0, + UART_PARITY_EVEN = 2, + UART_PARITY_ODD = 3, +}; + +/** + * @brief Number of UART stop bits + */ +enum smg_uart_stop_bits_t { + UART_NB_STOP_BIT_0 = 0, + UART_NB_STOP_BIT_1 = 1, + UART_NB_STOP_BIT_15 = 2, + UART_NB_STOP_BIT_2 = 3, +}; + +enum smg_uart_format_settings_t { + UART_PARITY_MASK = 0B00000011, + UART_PARITY_SHIFT = 0, + UART_NB_BIT_MASK = 0B00001100, + UART_NB_BIT_SHIFT = 2, + UART_NB_STOP_BIT_MASK = 0B00110000, + UART_NB_STOP_BIT_SHIFT = 4, +}; + +static inline constexpr uint8_t SMG_UART_FORMAT(smg_uart_bits_t databits, smg_uart_stop_bits_t stopbits, + smg_uart_parity_t parity) +{ + return (databits << UART_NB_BIT_SHIFT) | (stopbits << UART_NB_STOP_BIT_SHIFT) | (parity << UART_PARITY_SHIFT); +} + +/** + * @brief Structure for easier decomposing of `config` value + * + * Used by drivers to read config values + */ +union smg_uart_config_format_t { + struct { + smg_uart_parity_t parity : 2; + smg_uart_bits_t bits : 2; + smg_uart_stop_bits_t stop_bits : 2; + }; + uint8_t val; +}; + +/** + * @brief Options for `config` argument of uart_init + */ +enum smg_uart_format_t { + UART_5N1 = SMG_UART_FORMAT(UART_NB_BIT_5, UART_NB_STOP_BIT_1, UART_PARITY_NONE), + UART_6N1 = SMG_UART_FORMAT(UART_NB_BIT_6, UART_NB_STOP_BIT_1, UART_PARITY_NONE), + UART_7N1 = SMG_UART_FORMAT(UART_NB_BIT_7, UART_NB_STOP_BIT_1, UART_PARITY_NONE), + UART_8N1 = SMG_UART_FORMAT(UART_NB_BIT_8, UART_NB_STOP_BIT_1, UART_PARITY_NONE), + UART_5N2 = SMG_UART_FORMAT(UART_NB_BIT_5, UART_NB_STOP_BIT_2, UART_PARITY_NONE), + UART_6N2 = SMG_UART_FORMAT(UART_NB_BIT_6, UART_NB_STOP_BIT_2, UART_PARITY_NONE), + UART_7N2 = SMG_UART_FORMAT(UART_NB_BIT_7, UART_NB_STOP_BIT_2, UART_PARITY_NONE), + UART_8N2 = SMG_UART_FORMAT(UART_NB_BIT_8, UART_NB_STOP_BIT_2, UART_PARITY_NONE), + UART_5E1 = SMG_UART_FORMAT(UART_NB_BIT_5, UART_NB_STOP_BIT_1, UART_PARITY_EVEN), + UART_6E1 = SMG_UART_FORMAT(UART_NB_BIT_6, UART_NB_STOP_BIT_1, UART_PARITY_EVEN), + UART_7E1 = SMG_UART_FORMAT(UART_NB_BIT_7, UART_NB_STOP_BIT_1, UART_PARITY_EVEN), + UART_8E1 = SMG_UART_FORMAT(UART_NB_BIT_8, UART_NB_STOP_BIT_1, UART_PARITY_EVEN), + UART_5E2 = SMG_UART_FORMAT(UART_NB_BIT_5, UART_NB_STOP_BIT_2, UART_PARITY_EVEN), + UART_6E2 = SMG_UART_FORMAT(UART_NB_BIT_6, UART_NB_STOP_BIT_2, UART_PARITY_EVEN), + UART_7E2 = SMG_UART_FORMAT(UART_NB_BIT_7, UART_NB_STOP_BIT_2, UART_PARITY_EVEN), + UART_8E2 = SMG_UART_FORMAT(UART_NB_BIT_8, UART_NB_STOP_BIT_2, UART_PARITY_EVEN), + UART_5O1 = SMG_UART_FORMAT(UART_NB_BIT_5, UART_NB_STOP_BIT_1, UART_PARITY_ODD), + UART_6O1 = SMG_UART_FORMAT(UART_NB_BIT_6, UART_NB_STOP_BIT_1, UART_PARITY_ODD), + UART_7O1 = SMG_UART_FORMAT(UART_NB_BIT_7, UART_NB_STOP_BIT_1, UART_PARITY_ODD), + UART_8O1 = SMG_UART_FORMAT(UART_NB_BIT_8, UART_NB_STOP_BIT_1, UART_PARITY_ODD), + UART_5O2 = SMG_UART_FORMAT(UART_NB_BIT_5, UART_NB_STOP_BIT_2, UART_PARITY_ODD), + UART_6O2 = SMG_UART_FORMAT(UART_NB_BIT_6, UART_NB_STOP_BIT_2, UART_PARITY_ODD), + UART_7O2 = SMG_UART_FORMAT(UART_NB_BIT_7, UART_NB_STOP_BIT_2, UART_PARITY_ODD), + UART_8O2 = SMG_UART_FORMAT(UART_NB_BIT_8, UART_NB_STOP_BIT_2, UART_PARITY_ODD), +}; // Status values enum smg_uart_status_t { diff --git a/Sming/Components/axtls-8266/axtls-8266.patch b/Sming/Components/axtls-8266/axtls-8266.patch index d3f5354189..35e032998e 100644 --- a/Sming/Components/axtls-8266/axtls-8266.patch +++ b/Sming/Components/axtls-8266/axtls-8266.patch @@ -84,10 +84,10 @@ index dca7e5f..5f4ec51 100644 { diff --git a/replacements/time.c b/replacements/time.c -index 4972119..d3f0d1e 100644 +index 4972119..3e7e407 100644 --- a/replacements/time.c +++ b/replacements/time.c -@@ -16,6 +16,9 @@ +@@ -16,29 +16,25 @@ * */ @@ -95,9 +95,11 @@ index 4972119..d3f0d1e 100644 +#include + #include - #include +-#include ++#include -@@ -24,21 +27,14 @@ extern uint64_t system_mktime(uint32_t year, uint32_t mon, uint32_t day, uint32_ + extern uint32_t system_get_time(void); + extern uint64_t system_mktime(uint32_t year, uint32_t mon, uint32_t day, uint32_t hour, uint32_t min, uint32_t sec); static int errno_var = 0; @@ -508,7 +510,7 @@ index 6e41f40..8e4055b 100644 /* decrypt using the key/iv */ diff --git a/ssl/x509.c b/ssl/x509.c -index a51b948..bd42b57 100644 +index a51b948..8e10d85 100644 --- a/ssl/x509.c +++ b/ssl/x509.c @@ -109,76 +109,52 @@ int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx) @@ -613,7 +615,16 @@ index a51b948..bd42b57 100644 break; } - +@@ -305,7 +281,7 @@ static int x509_v3_basic_constraints(const uint8_t *cert, int offset, + /* If the Sequence Length is greater than 3, it has more content than + the basic_constraint_cA bool, so grab the pathLenConstraint */ + if ((lenSeq>3) && (asn1_get_int(cert, &offset, +- &x509_ctx->basic_constraint_pathLenConstraint) < 0)) ++ (int32_t*)&x509_ctx->basic_constraint_pathLenConstraint) < 0)) + { + ret = X509_NOT_OK; + } + diff --git a/ssl/gen_cert.c b/ssl/gen_cert.c index 093ae9c..d611ab0 100644 --- a/ssl/gen_cert.c @@ -715,3 +726,16 @@ index da24d31..4de139b 100644 int key_len, uint8_t *digest); void hmac_sha1_v(const uint8_t **msg, int* length, int count, const uint8_t *key, +diff --git a/ssl/asn1.c b/ssl/asn1.c +index a08a618..273d08b 100644 +--- a/ssl/asn1.c ++++ b/ssl/asn1.c +@@ -405,7 +405,7 @@ static int asn1_get_utc_time(const uint8_t *buf, int *offset, time_t *t) + int asn1_version(const uint8_t *cert, int *offset, int *val) + { + (*offset) += 2; /* get past explicit tag */ +- return asn1_get_int(cert, offset, val); ++ return asn1_get_int(cert, offset, (int32_t*)val); + } + + /** diff --git a/Sming/Components/crypto/api.rst b/Sming/Components/crypto/api.rst index 6c8ee573af..d48a4bdf7d 100644 --- a/Sming/Components/crypto/api.rst +++ b/Sming/Components/crypto/api.rst @@ -2,3 +2,4 @@ API Documentation ================= .. doxygennamespace:: Crypto + :members: diff --git a/Sming/Components/crypto/include/Crypto/HashContext.h b/Sming/Components/crypto/include/Crypto/HashContext.h index d4d695e67a..6192c7b59c 100644 --- a/Sming/Components/crypto/include/Crypto/HashContext.h +++ b/Sming/Components/crypto/include/Crypto/HashContext.h @@ -59,11 +59,14 @@ template class HashContext * @name Update hash over a given block of data * @{ */ + + /// Data from Blob HashContext& update(const Blob& blob) { return update(blob.data(), blob.size()); } + /// Data from flash object HashContext& update(const FSTR::ObjectBase& obj) { uint8_t buf[256]; @@ -76,12 +79,18 @@ template class HashContext return *this; } + /** + * @brief Pointer to data + size + * @param data Data block + * @param size Length of data in bytes + */ HashContext& update(const void* data, size_t size) { engine.update(data, size); return *this; } + /// Data in ByteArray template HashContext& update(const ByteArray& array) { return update(array.data(), array.size()); diff --git a/Sming/Components/esptool/Kconfig b/Sming/Components/esptool/Kconfig new file mode 100644 index 0000000000..882992e93a --- /dev/null +++ b/Sming/Components/esptool/Kconfig @@ -0,0 +1,9 @@ +menu "esptool" + config COM_PORT_ESPTOOL + string "Port to use for flashing device" + default COM_PORT + + config COM_SPEED_ESPTOOL + string "Baud rate to use for flashing device" + default COM_SPEED +endmenu diff --git a/Sming/Components/esptool/component.mk b/Sming/Components/esptool/component.mk index ba8df84f7a..934bbf0805 100644 --- a/Sming/Components/esptool/component.mk +++ b/Sming/Components/esptool/component.mk @@ -1,3 +1,4 @@ +COMPONENT_SOC := esp* COMPONENT_LIBNAME := DEBUG_VARS += SPI_SPEED SPI_MODE SPI_SIZE @@ -19,17 +20,9 @@ ESPTOOL_SUBMODULE := $(COMPONENT_PATH)/esptool $(ESPTOOL): $(ESPTOOL_SUBMODULE)/.submodule -ifeq ($(SMING_ARCH),Esp8266) -ESP_CHIP := esp8266 -else ifeq ($(SMING_ARCH),Esp32) -ESP_CHIP := $(ESP_VARIANT) -else ifeq ($(MAKE_DOCS),) -$(error esptool unsupported arch: $(SMING_ARCH)) -endif - ESPTOOL_CMDLINE := $(PYTHON) $(ESPTOOL) \ -p $(COM_PORT_ESPTOOL) -b $(COM_SPEED_ESPTOOL) \ - --chip $(ESP_CHIP) --before default_reset --after hard_reset + --chip $(SMING_SOC) --before default_reset --after hard_reset # # USB serial ports are not available under WSL2, diff --git a/Sming/Components/libb64/README.md b/Sming/Components/libb64/README.md index 132f02f508..f0f227142b 100644 --- a/Sming/Components/libb64/README.md +++ b/Sming/Components/libb64/README.md @@ -132,7 +132,7 @@ Also, in situations where this coroutine is used by more than one other coroutines, the consistency is disturbed. What is needed is a structure for storing these variabled, which is passed to -the routine seperately. This obviously breaks the modularity of the function, +the routine separately. This obviously breaks the modularity of the function, since now the caller has to worry about and care for the internal state of the routine (the callee). This allows for a fast, multithreading-enabled implementation, which may (obviously) be wrapped in a C++ object for ease of diff --git a/Sming/Components/malloc_count/README.md b/Sming/Components/malloc_count/README.md index d3ee05ad7d..63adc56d81 100644 --- a/Sming/Components/malloc_count/README.md +++ b/Sming/Components/malloc_count/README.md @@ -17,7 +17,7 @@ facilities to The code tool works by intercepting the standard `malloc()`, `free()`, etc functions. Thus **no changes** are necessary to the inspected source code. -See for the current verison. +See for the current version. ## Intercepting Heap Allocation Functions ## @@ -57,7 +57,7 @@ more complex example of a memory profile. ## Downloads ## -See for the current verison. +See for the current version. The source code is published under the [MIT License (MIT)](http://opensource.org/licenses/MIT), which is also found in @@ -129,3 +129,8 @@ The idea for this augmenting interception method is not my own, it was borrowed from Jeremy Kerr . Written 2013-01-21, 2013-03-16, and 2014-09-10 by Timo Bingmann + +## API Documentation + +.. doxygennamespace:: MallocCount + :members: diff --git a/Sming/Components/malloc_count/component.mk b/Sming/Components/malloc_count/component.mk index 4306eb9552..06023a9f35 100644 --- a/Sming/Components/malloc_count/component.mk +++ b/Sming/Components/malloc_count/component.mk @@ -1,4 +1,5 @@ COMPONENT_RELINK_VARS += ENABLE_MALLOC_COUNT +COMPONENT_DOXYGEN_INPUT := include ENABLE_MALLOC_COUNT ?= 1 @@ -7,14 +8,8 @@ ifeq ($(ENABLE_MALLOC_COUNT),1) COMPONENT_CXXFLAGS += -DENABLE_MALLOC_COUNT=1 # Hook all the memory allocation functions we need to monitor heap activity -MC_WRAP_FUNCS := \ - malloc \ - calloc \ - realloc \ - free - ifeq ($(SMING_ARCH),Esp8266) -MC_WRAP_FUNCS += \ +MC_WRAP_FUNCS := \ pvPortMalloc \ pvPortCalloc \ pvPortRealloc \ @@ -22,10 +17,14 @@ MC_WRAP_FUNCS += \ pvPortZallocIram \ vPortFree else -MC_WRAP_FUNCS += \ +MC_WRAP_FUNCS := \ + malloc \ + calloc \ + realloc \ + free \ strdup endif -EXTRA_LDFLAGS := $(call Wrap,$(MC_WRAP_FUNCS)) +EXTRA_LDFLAGS := $(call UndefWrap,$(MC_WRAP_FUNCS)) endif diff --git a/Sming/Components/malloc_count/malloc_count.cpp b/Sming/Components/malloc_count/malloc_count.cpp index 315cca5f65..f094888c72 100644 --- a/Sming/Components/malloc_count/malloc_count.cpp +++ b/Sming/Components/malloc_count/malloc_count.cpp @@ -42,31 +42,20 @@ #include // Names for the actual implementations -#ifdef ARCH_HOST - -#define F_MALLOC malloc -#define F_CALLOC calloc -#define F_REALLOC realloc -#define F_FREE free - -#elif defined(ARCH_ESP8266) +#ifdef ARCH_ESP8266 #define F_MALLOC pvPortMalloc #define F_CALLOC pvPortCalloc #define F_REALLOC pvPortRealloc #define F_FREE vPortFree -#elif defined(ARCH_ESP32) +#else #define F_MALLOC malloc #define F_CALLOC calloc #define F_REALLOC realloc #define F_FREE free -#else - -#error Unsupported Architecture - #endif #define CONCAT(a, b) a##b @@ -369,7 +358,7 @@ extern "C" void* WRAP(pvPortZalloc)(size_t) __attribute__((alias("mc_zalloc"))); extern "C" void* WRAP(pvPortZallocIram)(size_t) __attribute__((alias("mc_zalloc"))); extern "C" void WRAP(vPortFree)(void*) __attribute__((alias("mc_free"))); -#elif defined(ARCH_HOST) || defined(ARCH_ESP32) +#else using namespace MallocCount; @@ -425,10 +414,6 @@ extern "C" char* WRAP(strdup)(const char* s) return dup; } -#else - -static_assert(false, "ARCH not supported"); - #endif #endif // ENABLE_MALLOC_COUNT diff --git a/Sming/Components/mqtt-codec b/Sming/Components/mqtt-codec index 3767dfce41..34971c30b9 160000 --- a/Sming/Components/mqtt-codec +++ b/Sming/Components/mqtt-codec @@ -1 +1 @@ -Subproject commit 3767dfce416ebb0ea42903a4bbd93f5675be6cdb +Subproject commit 34971c30b93ffce34782e4a10569aeb121322c81 diff --git a/Sming/Components/rboot/Kconfig b/Sming/Components/rboot/Kconfig new file mode 100644 index 0000000000..730b474ff0 --- /dev/null +++ b/Sming/Components/rboot/Kconfig @@ -0,0 +1,22 @@ +menu "rBoot" + depends on SMING_ARCH = "Esp8266" + + config RBOOT_RTC_ENABLED + bool "Enable extended boot information via RTC memory" + + choice + prompt "GPIO boot behaviour" + default RBOOT_GPIO_DISABLED + config RBOOT_GPIO_DISABLED + bool "Disable GPIO features" + config RBOOT_GPIO_ENABLED + bool "Enable GPIO boot slot 2" + help + rBoot supports booting into a third slot upon explicit user request, + e.g. by pressing a button during reset/power up. + This is especially useful for implementing some sort of recovery mechanism. + config RBOOT_GPIO_SKIP_ENABLED + bool "Use GPIO to skip between boot roms" + endchoice + +endmenu diff --git a/Sming/Components/rboot/component.mk b/Sming/Components/rboot/component.mk index f432ac460c..3a99722dfc 100644 --- a/Sming/Components/rboot/component.mk +++ b/Sming/Components/rboot/component.mk @@ -1,3 +1,4 @@ +COMPONENT_SOC := esp8266 host COMPONENT_DOXYGEN_INPUT := rboot ifeq ($(SMING_ARCH),Esp8266) diff --git a/Sming/Components/rboot/include/Data/Stream/RbootOutputStream.h b/Sming/Components/rboot/include/Data/Stream/RbootOutputStream.h index 1873d01885..fca76c75a5 100644 --- a/Sming/Components/rboot/include/Data/Stream/RbootOutputStream.h +++ b/Sming/Components/rboot/include/Data/Stream/RbootOutputStream.h @@ -97,6 +97,3 @@ class RbootOutputStream : public ReadWriteStream protected: virtual bool init(); }; - -/** @deprecated Use `RbootOutputStream` */ -typedef RbootOutputStream rBootOutputStream SMING_DEPRECATED; diff --git a/Sming/Components/rboot/include/Network/RbootHttpUpdater.h b/Sming/Components/rboot/include/Network/RbootHttpUpdater.h index 2100626770..3816d914b7 100644 --- a/Sming/Components/rboot/include/Network/RbootHttpUpdater.h +++ b/Sming/Components/rboot/include/Network/RbootHttpUpdater.h @@ -143,15 +143,6 @@ class RbootHttpUpdater : protected HttpClient baseRequest = request; } - /** - * @brief Allow reading items - * @deprecated Access list directly using `getItems()` - */ - const Item& getItem(unsigned int index) const SMING_DEPRECATED - { - return items[index]; - } - /** * @brief Allow read access to item list */ @@ -175,9 +166,3 @@ class RbootHttpUpdater : protected HttpClient uint8_t currentItem{0}; rboot_write_status rbootWriteStatus{}; }; - -/** @deprecated Use `RbootHttpUpdater` */ -typedef RbootHttpUpdater rBootHttpUpdate SMING_DEPRECATED; - -/** @deprecated Use 'auto' in expressions or `RbootHttpUpdater::Item` */ -typedef RbootHttpUpdater::Item RbootHttpUpdaterItem SMING_DEPRECATED; diff --git a/Sming/Components/rboot/rboot b/Sming/Components/rboot/rboot index 4ad3ba2a8f..cc00071f59 160000 --- a/Sming/Components/rboot/rboot +++ b/Sming/Components/rboot/rboot @@ -1 +1 @@ -Subproject commit 4ad3ba2a8f6d48d8ab90e0e7c67d42cac49f4da3 +Subproject commit cc00071f593ef7d55c0c0a7b97828173f9cda89b diff --git a/Sming/Components/rboot/src/RbootOutputStream.cpp b/Sming/Components/rboot/src/RbootOutputStream.cpp index e7b71e4eb5..c5819145b0 100644 --- a/Sming/Components/rboot/src/RbootOutputStream.cpp +++ b/Sming/Components/rboot/src/RbootOutputStream.cpp @@ -14,6 +14,7 @@ */ #include +#include bool RbootOutputStream::init() { diff --git a/Sming/Components/simpleRPC/README.rst b/Sming/Components/simpleRPC/README.rst new file mode 100644 index 0000000000..2be17919af --- /dev/null +++ b/Sming/Components/simpleRPC/README.rst @@ -0,0 +1,5 @@ +Simple RPC +========== + +Sming wrapper for the Arduino simpleRPC library. +This provides a way to export functions as remote procedure calls. diff --git a/Sming/Components/simpleRPC/component.mk b/Sming/Components/simpleRPC/component.mk new file mode 100644 index 0000000000..4fd217ca80 --- /dev/null +++ b/Sming/Components/simpleRPC/component.mk @@ -0,0 +1,6 @@ +COMPONENT_SUBMODULES += simpleRPC + +SIMPLE_RPC_ROOT := $(COMPONENT_PATH)/simpleRPC + +COMPONENT_SRCDIRS := $(SIMPLE_RPC_ROOT)/src $(COMPONENT_PATH)/src +COMPONENT_INCDIRS := $(COMPONENT_SRCDIRS) $(COMPONENT_PATH)/include diff --git a/Sming/Components/simpleRPC/include/simpleRPC/.cs b/Sming/Components/simpleRPC/include/simpleRPC/.cs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Sming/Components/simpleRPC/include/simpleRPC/parser.h b/Sming/Components/simpleRPC/include/simpleRPC/parser.h new file mode 100644 index 0000000000..a1ce2e336e --- /dev/null +++ b/Sming/Components/simpleRPC/include/simpleRPC/parser.h @@ -0,0 +1,63 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * parser.h + * + * @author 2021 Slavey Karadzhov + * + * + ****/ + +#pragma once + +#include + +namespace simpleRPC +{ +enum class ParserResult { finished = 0, more, error }; + +enum class ParserState { + ready = 0, + header_s, + header_si, + header_sim, + header_simp, + header_simpl, + header_simple, + header_simpleR, + header_simpleRP, + header_simpleRPC, + header_end, + version_major, + version_minor, + version_patch, + ness, + type, + type_end, + start_methods, + extract_method_start, + extract_method_name, + extract_method, + extract_method_end, + end_methods, + finished +}; + +struct ParserSettings { + using SimpleMethod = Delegate; + using CharMethod = Delegate; + + SimpleMethod startMethods; + SimpleMethod startMethod; + CharMethod methodName; + SimpleMethod endMethod; + SimpleMethod endMethods; + ParserState state = ParserState::ready; +}; + +ParserResult parse(ParserSettings& settings, const char* buffer, size_t length); + +} // namespace simpleRPC diff --git a/Sming/Components/simpleRPC/simpleRPC b/Sming/Components/simpleRPC/simpleRPC new file mode 160000 index 0000000000..d76e9fa54e --- /dev/null +++ b/Sming/Components/simpleRPC/simpleRPC @@ -0,0 +1 @@ +Subproject commit d76e9fa54ef816519693322c832af8bb9f186fd7 diff --git a/Sming/Components/simpleRPC/simpleRPC.patch b/Sming/Components/simpleRPC/simpleRPC.patch new file mode 100644 index 0000000000..5657d6fc78 --- /dev/null +++ b/Sming/Components/simpleRPC/simpleRPC.patch @@ -0,0 +1,78 @@ +diff --git a/src/read.tcc b/src/read.tcc +index 2e5810f..513d691 100644 +--- a/src/read.tcc ++++ b/src/read.tcc +@@ -3,7 +3,6 @@ + + #include "defs.h" + #include "tuple.tcc" +-#include "vector.tcc" + + //! \defgroup read + +diff --git a/src/signature.tcc b/src/signature.tcc +index 00f5eb1..f3a675d 100644 +--- a/src/signature.tcc ++++ b/src/signature.tcc +@@ -25,7 +25,7 @@ void _parameterTypes(Stream& io, void (*f_)(H, Tail...)) { + * `rpcTypeOf()` to encode its type. The first parameter type `H` is removed + * from function pointer `*f_` in the recursive call. + */ +- H data; ++ H data{}; + + rpcPrint(io, ' '); + rpcTypeOf(io, data); +@@ -49,13 +49,13 @@ void _parameterTypes(Stream& io, void (*f_)(H&, Tail...)) { + */ + template + void signature(Stream& io, R (*f)(FArgs...)) { +- /* ++ /* + * A dummy function pointer is prepared, referred to as `f_` in the template + * functions above, which will be used to isolate parameter types. The return + * type of this function pointer is removed to avoid unneeded template + * expansion. + */ +- R data; ++ R data{}; + + rpcTypeOf(io, data); + rpcPrint(io, ':'); +diff --git a/src/types.tcc b/src/types.tcc +index 651fb38..8a7cfa5 100644 +--- a/src/types.tcc ++++ b/src/types.tcc +@@ -3,7 +3,6 @@ + + #include "print.tcc" + #include "tuple.tcc" +-#include "vector.tcc" + + //! \defgroup types + +diff --git a/src/write.tcc b/src/write.tcc +index d51cdd1..abf1e7b 100644 +--- a/src/write.tcc ++++ b/src/write.tcc +@@ -3,7 +3,6 @@ + + #include "print.tcc" + #include "tuple.tcc" +-#include "vector.tcc" + + //! \defgroup write + +diff --git a/src/defs.h b/src/defs.h +index 8d2ec2a..93edaf5 100644 +--- a/src/defs.h ++++ b/src/defs.h +@@ -1,7 +1,7 @@ + #ifndef SIMPLE_RPC_DEFS_H_ + #define SIMPLE_RPC_DEFS_H_ + +-#include ++#include + + #define _PROTOCOL "simpleRPC" + #define _VERSION "\3\0\0" diff --git a/Sming/Components/simpleRPC/src/.cs b/Sming/Components/simpleRPC/src/.cs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Sming/Components/simpleRPC/src/parser.cpp b/Sming/Components/simpleRPC/src/parser.cpp new file mode 100644 index 0000000000..7be4f8183c --- /dev/null +++ b/Sming/Components/simpleRPC/src/parser.cpp @@ -0,0 +1,195 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * parser.cpp + * + * @author 2021 Slavey Karadzhov + * + * + ****/ + +#include "../include/simpleRPC/parser.h" + +namespace simpleRPC +{ +#define EXPECT(X, NEW_STATE) \ + { \ + if(ch != X) { \ + hasError = true; \ + goto ERROR; \ + } \ + state = NEW_STATE; \ + break; \ + } + +#define SKIP_UNTIL(X, NEW_STATE) \ + { \ + if(ch != X) { \ + break; \ + } \ + state = NEW_STATE; \ + } + +ParserResult parse(ParserSettings& settings, const char* buffer, size_t length) +{ + auto& state = settings.state; + /* + * See: https://simplerpc.readthedocs.io/en/latest/protocol.html# +00000000 ff . + 00000000 73 s + 00000001 69 i + 00000002 6d m + 00000003 70 p + 00000004 6c l + 00000005 65 e + 00000006 52 R + 00000007 50 P + 00000008 43 C + 00000009 00 . + 0000000A 03 00 00 ... + 3c < + 49 I + 00 . + 3a 20 : + 3a 20 48 20 42 3b 70 69 6e 4d ...> x509_device.pem # set default key/cert for use in the server xxd -i x509_1024.cer | sed -e \ - "s/x509_1024_cer/default_certificate/" > $SSL_INCLUDE_DIR/cert.h + "s/x509_1024_cer/default_certificate/" > "$SSL_INCLUDE_DIR/cert.h" xxd -i key_1024 | sed -e \ - "s/key_1024/default_private_key/" > $SSL_INCLUDE_DIR/private_key.h + "s/key_1024/default_private_key/" > "$SSL_INCLUDE_DIR/private_key.h" diff --git a/Sming/Components/ssl/certificates.rst b/Sming/Components/ssl/certificates.rst index eab1a23196..cb2d460ea9 100644 --- a/Sming/Components/ssl/certificates.rst +++ b/Sming/Components/ssl/certificates.rst @@ -2,6 +2,17 @@ Certificates ============ .. doxygenclass:: Ssl::Certificate + :members: + .. doxygenclass:: Ssl::ValidatorList + :members: + .. doxygenclass:: Ssl::Validator + :members: + .. doxygenunion:: Ssl::Fingerprint + +.. doxygenclass:: Ssl::KeyCertPair + :members: + +.. doxygentypedef:: Ssl::ValidatorCallback diff --git a/Sming/Components/ssl/include/Network/Ssl/Certificate.h b/Sming/Components/ssl/include/Network/Ssl/Certificate.h index a02d4a94be..837d1c2e65 100644 --- a/Sming/Components/ssl/include/Network/Ssl/Certificate.h +++ b/Sming/Components/ssl/include/Network/Ssl/Certificate.h @@ -98,8 +98,3 @@ class Certificate String toString(Certificate::RDN rdn); } // namespace Ssl - -/** - * @deprecated Use `Ssl::Certificate` instead - */ -typedef Ssl::Certificate SslCertificate SMING_DEPRECATED; diff --git a/Sming/Components/ssl/include/Network/Ssl/Connection.h b/Sming/Components/ssl/include/Network/Ssl/Connection.h index 2085661691..972b77694c 100644 --- a/Sming/Components/ssl/include/Network/Ssl/Connection.h +++ b/Sming/Components/ssl/include/Network/Ssl/Connection.h @@ -17,6 +17,7 @@ #include "InputBuffer.h" #include "CipherSuite.h" #include "Alert.h" +#include namespace Ssl { diff --git a/Sming/Components/ssl/include/Network/Ssl/InputBuffer.h b/Sming/Components/ssl/include/Network/Ssl/InputBuffer.h index beb25105d6..4843abed62 100644 --- a/Sming/Components/ssl/include/Network/Ssl/InputBuffer.h +++ b/Sming/Components/ssl/include/Network/Ssl/InputBuffer.h @@ -10,7 +10,9 @@ #pragma once -#include +#include +#include +#include namespace Ssl { diff --git a/Sming/Components/ssl/include/Network/Ssl/KeyCertPair.h b/Sming/Components/ssl/include/Network/Ssl/KeyCertPair.h index 2082b4f517..b3fa85444c 100644 --- a/Sming/Components/ssl/include/Network/Ssl/KeyCertPair.h +++ b/Sming/Components/ssl/include/Network/Ssl/KeyCertPair.h @@ -99,13 +99,3 @@ class KeyCertPair }; } // namespace Ssl - -/** - * @deprecated Use Ssl::KeyCertPair instead - */ -typedef Ssl::KeyCertPair SslKeyCertPair SMING_DEPRECATED; - -/** - * @deprecated Use Ssl::KeyCertPair instead - */ -typedef Ssl::KeyCertPair SSLKeyCertPair SMING_DEPRECATED; diff --git a/Sming/Components/ssl/include/Network/Ssl/SessionId.h b/Sming/Components/ssl/include/Network/Ssl/SessionId.h index 05119f428b..9b39d33e9b 100644 --- a/Sming/Components/ssl/include/Network/Ssl/SessionId.h +++ b/Sming/Components/ssl/include/Network/Ssl/SessionId.h @@ -63,13 +63,3 @@ __forceinline String toString(const SessionId& id) } } // namespace Ssl - -/** - * @deprecated Use Ssl::SessionId instead - */ -typedef Ssl::SessionId SslSessionId SMING_DEPRECATED; - -/** - * @deprecated Use Ssl::SessionId instead - */ -typedef Ssl::SessionId SSLSessionId SMING_DEPRECATED; diff --git a/Sming/Components/ssl/include/Network/Ssl/Validator.h b/Sming/Components/ssl/include/Network/Ssl/Validator.h index b6faa9a80e..a1bef660d4 100644 --- a/Sming/Components/ssl/include/Network/Ssl/Validator.h +++ b/Sming/Components/ssl/include/Network/Ssl/Validator.h @@ -103,8 +103,3 @@ class CallbackValidator : public Validator }; } // namespace Ssl - -/** - * @deprecated Use `Ssl::ValidatorCallback` instead - */ -typedef Ssl::ValidatorCallback SslValidatorCallback SMING_DEPRECATED; diff --git a/Sming/Components/terminal/Kconfig b/Sming/Components/terminal/Kconfig new file mode 100644 index 0000000000..59906f3609 --- /dev/null +++ b/Sming/Components/terminal/Kconfig @@ -0,0 +1,33 @@ +menu "Terminal" + + config COM_PORT + string "Default port for device communications" + help + Default value depends on the development platform being used. + default "/dev/cuaU0" if ("$UNAME" = "FreeBSD") + default "/dev/tty.usbserial" if "$UNAME" = "MacOS" + default "/dev/ttyUSB0" if "$UNAME" = "Linux" + default "COM3" if "$UNAME" = "Windows" + + config COM_SPEED_SERIAL + int "Default baud rate to use for serial communication within application" + default COM_SPEED + + config COM_OPTS + string "Additional options to pass to the terminal" + default "--raw --encoding ascii --rts 0 --dtr 0" + + config TERMINAL + string "Command line to use when running `make terminal`" + help + Redefine if you want to use a different terminal application + default "powershell.exe -Command \"python -m serial.tools.miniterm $(COM_OPTS) $(COM_PORT) $(COM_SPEED_SERIAL)\"" if $WSL_ROOT + default "$(PYTHON) -m serial.tools.miniterm $(COM_OPTS) $(COM_PORT) $(COM_SPEED_SERIAL)" if !$WSL_ROOT + + config KILL_TERM + string "Command line to use to kill the running terminal process" + help + If the terminal never runs in the background and the warnings annoy you, just clear it + default "pkill -9 -f \"$(COM_PORT) $(COM_SPEED_SERIAL)\" || exit 0" + +endmenu diff --git a/Sming/Core/Clock.cpp b/Sming/Core/Clock.cpp index 4f399319a7..63cf0ab31d 100644 --- a/Sming/Core/Clock.cpp +++ b/Sming/Core/Clock.cpp @@ -9,7 +9,7 @@ ****/ #include "Clock.h" -#include +#include #define MAX_SAFE_DELAY 1000 diff --git a/Sming/Core/Data/Buffer/CircularBuffer.h b/Sming/Core/Data/Buffer/CircularBuffer.h index 6ccd41a7af..fad71b793e 100644 --- a/Sming/Core/Data/Buffer/CircularBuffer.h +++ b/Sming/Core/Data/Buffer/CircularBuffer.h @@ -87,7 +87,7 @@ class CircularBuffer : public ReadWriteStream /** @brief Write chars to stream * @param data Pointer to buffer to write to the stream - * @param size Quantity of chars to writen + * @param size Quantity of chars to written * @retval size_t Quantity of chars written to stream */ size_t write(const uint8_t* data, size_t size) override; diff --git a/Sming/Core/Data/Buffer/LineBuffer.h b/Sming/Core/Data/Buffer/LineBuffer.h index 88dd6cf62a..e23186b483 100644 --- a/Sming/Core/Data/Buffer/LineBuffer.h +++ b/Sming/Core/Data/Buffer/LineBuffer.h @@ -12,7 +12,8 @@ #pragma once -#include +#include +#include /** * @brief Class to enable buffering of a single line of text, with simple editing diff --git a/Sming/Core/Data/CsvReader.cpp b/Sming/Core/Data/CsvReader.cpp new file mode 100644 index 0000000000..569ce02a0b --- /dev/null +++ b/Sming/Core/Data/CsvReader.cpp @@ -0,0 +1,124 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * CsvReader.cpp + * + * @author: 2021 - Mikee47 + * + ****/ + +#include "CsvReader.h" +#include + +void CsvReader::reset() +{ + source->seekFrom(0, SeekOrigin::Start); + if(!userHeadingsProvided) { + readRow(); + headings = row; + } + row = nullptr; +} + +bool CsvReader::readRow() +{ + constexpr size_t blockSize{512}; + + String buffer(std::move(reinterpret_cast(row))); + constexpr char quoteChar{'"'}; + enum class FieldKind { + unknown, + quoted, + unquoted, + }; + FieldKind fieldKind{}; + bool escape{false}; + bool quote{false}; + char lc{'\0'}; + unsigned writepos{0}; + + while(true) { + if(buffer.length() == maxLineLength) { + debug_w("[CSV] Line buffer limit reached %u", maxLineLength); + return false; + } + size_t buflen = std::min(writepos + blockSize, maxLineLength); + if(!buffer.setLength(buflen)) { + debug_e("[CSV] Out of memory %u", buflen); + return false; + } + auto len = source->readBytes(buffer.begin() + writepos, buflen - writepos); + if(len == 0) { + if(writepos == 0) { + return false; + } + buffer.setLength(writepos); + row = std::move(buffer); + return true; + } + buflen = writepos + len; + unsigned readpos = writepos; + + for(; readpos < buflen; ++readpos) { + char c = buffer[readpos]; + if(escape) { + switch(c) { + case 'n': + c = '\n'; + break; + case 'r': + c = '\r'; + break; + case 't': + c = '\t'; + break; + default:; + // Just accept character + } + escape = false; + } else { + if(fieldKind == FieldKind::unknown) { + if(c == quoteChar) { + fieldKind = FieldKind::quoted; + quote = true; + lc = '\0'; + continue; + } + fieldKind = FieldKind::unquoted; + } + if(c == quoteChar) { + quote = !quote; + if(fieldKind == FieldKind::quoted) { + if(lc == quoteChar) { + buffer[writepos++] = c; + lc = '\0'; + } else { + lc = c; + } + continue; + } + } else if(c == '\\') { + escape = true; + continue; + } else if(!quote) { + if(c == fieldSeparator) { + c = '\0'; + fieldKind = FieldKind::unknown; + } else if(c == '\r') { + continue; + } else if(c == '\n') { + source->seekFrom(readpos + 1 - buflen, SeekOrigin::Current); + buffer.setLength(writepos); + row = std::move(buffer); + return true; + } + } + } + buffer[writepos++] = c; + lc = c; + } + } +} diff --git a/Sming/Core/Data/CsvReader.h b/Sming/Core/Data/CsvReader.h new file mode 100644 index 0000000000..b257596acf --- /dev/null +++ b/Sming/Core/Data/CsvReader.h @@ -0,0 +1,144 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * CsvReader.h + * + * @author: 2021 - Mikee47 + * + ****/ + +#pragma once + +#include "Stream/DataSourceStream.h" +#include "CStringArray.h" +#include + +/** + * @brief Class to parse a CSV file + * + * Spec: https://www.ietf.org/rfc/rfc4180.txt + * + * 1. Each record is located on a separate line + * 2. Line ending for last record in the file is optional + * 3. Field headings are provided either in the source data or in constructor (but not both) + * 4. Fields separated with ',' and whitespace considered part of field content + * 5. Fields may or may not be quoted - if present, will be removed during parsing + * 6. Fields may contain line breaks, quotes or commas + * 7. Quotes may be escaped thus "" if field itself is quoted + * + * Additional features: + * + * - Line breaks can be \n or \r\n + * - Escapes codes within fields will be converted: \n \r \t \", \\ + * - Field separator can be changed in constructor + */ +class CsvReader +{ +public: + /** + * @brief Construct a CSV reader + * @param source Stream to read CSV text from + * @param fieldSeparator + * @param headings Required if source data does not contain field headings as first row + * @param maxLineLength Limit size of buffer to guard against malformed data + */ + CsvReader(IDataSourceStream* source, char fieldSeparator = ',', const CStringArray& headings = nullptr, + size_t maxLineLength = 2048) + : fieldSeparator(fieldSeparator), userHeadingsProvided(headings), maxLineLength(maxLineLength), + headings(headings) + { + this->source.reset(source); + reset(); + } + + /** + * @brief Reset reader to start of CSV file + * + * Cursor is set to 'before start'. + * Call 'next()' to fetch first record. + */ + void reset(); + + /** + * @brief Seek to next record + */ + bool next() + { + return readRow(); + } + + /** + * @brief Get number of columns + */ + unsigned count() const + { + return headings.count(); + } + + /** + * @brief Get a value from the current row + * @param index Column index, starts at 0 + * @retval const char* nullptr if index is not valid + */ + const char* getValue(unsigned index) + { + return row[index]; + } + + /** + * @brief Get a value from the current row + * @param index Column name + * @retval const char* nullptr if name is not found + */ + const char* getValue(const char* name) + { + return getValue(getColumn(name)); + } + + /** + * @brief Get index of columnn given its name + * @param name Column name to find + * @retval int -1 if name is not found + */ + int getColumn(const char* name) + { + return headings.indexOf(name); + } + + /** + * @brief Determine if row is valid + */ + explicit operator bool() const + { + return bool(row); + } + + /** + * @brief Get headings + */ + const CStringArray& getHeadings() const + { + return headings; + } + + /** + * @brief Get current row + */ + const CStringArray& getRow() const + { + return row; + } + +private: + bool readRow(); + + std::unique_ptr source; + char fieldSeparator; + bool userHeadingsProvided; + size_t maxLineLength; + CStringArray headings; + CStringArray row; +}; diff --git a/Sming/Core/Data/Format.h b/Sming/Core/Data/Format.h index 0d44f8a3f7..e630366bc1 100644 --- a/Sming/Core/Data/Format.h +++ b/Sming/Core/Data/Format.h @@ -17,5 +17,6 @@ #include "Format/Standard.h" #include "Format/Html.h" #include "Format/Json.h" +#include "Format/Xml.h" using Formatter = Format::Formatter; diff --git a/Sming/Core/Data/Format/Formatter.h b/Sming/Core/Data/Format/Formatter.h index 3ba6790c65..993e0dd61c 100644 --- a/Sming/Core/Data/Format/Formatter.h +++ b/Sming/Core/Data/Format/Formatter.h @@ -39,7 +39,7 @@ class Formatter virtual void unQuote(String& value) const = 0; /** - * @brief Correspdoning MIME type for this format + * @brief Corresponding MIME type for this format * @note New types must be added to WebConstants.h */ virtual MimeType mimeType() const = 0; diff --git a/Sming/Core/Data/Format/Json.cpp b/Sming/Core/Data/Format/Json.cpp index f594bc7eb2..01404fbaca 100644 --- a/Sming/Core/Data/Format/Json.cpp +++ b/Sming/Core/Data/Format/Json.cpp @@ -62,7 +62,7 @@ bool IsValidUtf8(const char* str, unsigned length) * operation otherwise. * * This can occur if filenames become corrupted, so here we just - * subsitute an underscore _ for anything which fails to match UTF8. + * substitute an underscore _ for anything which fails to match UTF8. * * TODO: Perform ANSI -> UTF8 conversion? */ @@ -76,6 +76,8 @@ void Json::escape(String& value) const c = '_'; } } + + value.replace("\"", "\\\""); } } // namespace Format diff --git a/Sming/Core/Data/Format/Standard.cpp b/Sming/Core/Data/Format/Standard.cpp index 14eaa47d75..450b6b04bc 100644 --- a/Sming/Core/Data/Format/Standard.cpp +++ b/Sming/Core/Data/Format/Standard.cpp @@ -15,4 +15,28 @@ namespace Format { Standard standard; + +void Standard::quote(String& value) const +{ + value.replace("\"", "\"\""); + char cQuote{'"'}; + auto len = value.length(); + value.setLength(len + 2); + memmove(&value[1], value.c_str(), len); + value[0] = cQuote; + value[len + 1] = cQuote; +} + +void Standard::unQuote(String& value) const +{ + char quote = value[0]; + if(quote == '"' || quote == '\'') { + auto len = value.length(); + if(len > 1 && value[len - 1] == quote) { + value.remove(len - 1, 1); + value.remove(0, 1); + } + } } + +} // namespace Format diff --git a/Sming/Core/Data/Format/Standard.h b/Sming/Core/Data/Format/Standard.h index 82b44c2132..7d6a1a71c1 100644 --- a/Sming/Core/Data/Format/Standard.h +++ b/Sming/Core/Data/Format/Standard.h @@ -23,27 +23,8 @@ class Standard : public Formatter { } - void quote(String& value) const override - { - char cQuote{'"'}; - auto len = value.length(); - value.setLength(len + 2); - memmove(&value[1], value.c_str(), len); - value[0] = cQuote; - value[len + 1] = cQuote; - } - - void unQuote(String& value) const override - { - char quote = value[0]; - if(quote == '"' || quote == '\'') { - auto len = value.length(); - if(len > 1 && value[len - 1] == quote) { - value.remove(len - 1, 1); - value.remove(0, 1); - } - } - } + void quote(String& value) const override; + void unQuote(String& value) const override; MimeType mimeType() const override { diff --git a/Sming/Core/Data/Format/Xml.cpp b/Sming/Core/Data/Format/Xml.cpp new file mode 100644 index 0000000000..440a4826a4 --- /dev/null +++ b/Sming/Core/Data/Format/Xml.cpp @@ -0,0 +1,28 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * Xml.cpp + * + * @author mikee47 Oct 2021 + * + ****/ + +#include "Xml.h" + +namespace Format +{ +Xml xml; + +void Xml::escape(String& value) const +{ + value.replace("&", "&"); + value.replace("<", "<"); + value.replace(">", ">"); + value.replace("'", "'"); + value.replace("\"", """); +} + +} // namespace Format diff --git a/Sming/Core/Data/Format/Xml.h b/Sming/Core/Data/Format/Xml.h new file mode 100644 index 0000000000..0e5409b697 --- /dev/null +++ b/Sming/Core/Data/Format/Xml.h @@ -0,0 +1,32 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * Xml.h + * + * @author mikee47 Oct 2021 + * + ****/ + +#pragma once + +#include "Standard.h" + +namespace Format +{ +class Xml : public Standard +{ +public: + void escape(String& value) const override; + + MimeType mimeType() const override + { + return MIME_XML; + } +}; + +extern Xml xml; + +} // namespace Format diff --git a/Sming/Core/Data/LinkedObjectList.h b/Sming/Core/Data/LinkedObjectList.h index 4c31b02308..b9f5e75767 100644 --- a/Sming/Core/Data/LinkedObjectList.h +++ b/Sming/Core/Data/LinkedObjectList.h @@ -171,6 +171,7 @@ template class OwnedLinkedObjectListTemplate : public Link OwnedLinkedObjectListTemplate() = default; OwnedLinkedObjectListTemplate(const OwnedLinkedObjectListTemplate& other) = delete; + OwnedLinkedObjectListTemplate& operator=(const OwnedLinkedObjectListTemplate& other) = delete; ~OwnedLinkedObjectListTemplate() { diff --git a/Sming/Core/Data/Stream/DataSourceStream.cpp b/Sming/Core/Data/Stream/DataSourceStream.cpp index 3af18606f1..4a7e0e41bd 100644 --- a/Sming/Core/Data/Stream/DataSourceStream.cpp +++ b/Sming/Core/Data/Stream/DataSourceStream.cpp @@ -41,13 +41,17 @@ size_t IDataSourceStream::readBytes(char* buffer, size_t length) String IDataSourceStream::readString(size_t maxLen) { - size_t avail = available(); - size_t len = std::min(avail, maxLen); - String s; - if(s.setLength(len)) { - len = readBytes(s.begin(), len); - s.setLength(len); + size_t remain = maxLen; + while(remain != 0) { + char buffer[256]; + size_t len = readBytes(buffer, remain); + if(len == 0) { + break; + } + s.concat(buffer, len); + remain -= len; } + return s; } diff --git a/Sming/Core/Data/Stream/DataSourceStream.h b/Sming/Core/Data/Stream/DataSourceStream.h index 8c77cd559d..a57e12400d 100644 --- a/Sming/Core/Data/Stream/DataSourceStream.h +++ b/Sming/Core/Data/Stream/DataSourceStream.h @@ -10,7 +10,6 @@ #pragma once -#include #include #include #include "SeekOrigin.h" @@ -34,6 +33,8 @@ enum StreamType { eSST_User, ///< User defined data stream eSST_Chain, ///< A stream (chain) containing multiple streams eSST_Transform, ///< A stream that is transforming the data + eSST_Wrapper, ///< A stream that is a wrapper around a source stream + eSST_HeaderChecker, ///< A stream that receives HTTP headers in Stream::checkHeaders() eSST_Unknown ///< Unknown data stream type }; @@ -131,17 +132,6 @@ class IDataSourceStream : public Stream return 0; } - /** - * @brief Return the total length of the stream - * @retval int -1 is returned when the size cannot be determined - * - * @deprecated Use `available()` instead - */ - int length() SMING_DEPRECATED - { - return available(); - } - /* * @brief Flushes the stream */ diff --git a/Sming/Core/Data/Stream/FileStream.h b/Sming/Core/Data/Stream/FileStream.h index f42aaaac6d..1e03feeef3 100644 --- a/Sming/Core/Data/Stream/FileStream.h +++ b/Sming/Core/Data/Stream/FileStream.h @@ -39,10 +39,4 @@ class FileStream : public IFS::FileStream } using IFS::FileStream::attach; - - /** @deprecated Use `open()` instead */ - bool attach(const String& fileName, FileOpenFlags openFlags = File::ReadOnly) SMING_DEPRECATED - { - return open(fileName, openFlags); - } }; diff --git a/Sming/Core/Data/Stream/IFS/JsonDirectoryTemplate.h b/Sming/Core/Data/Stream/IFS/JsonDirectoryTemplate.h index 61ec5bc438..2b19349f75 100644 --- a/Sming/Core/Data/Stream/IFS/JsonDirectoryTemplate.h +++ b/Sming/Core/Data/Stream/IFS/JsonDirectoryTemplate.h @@ -25,7 +25,6 @@ class JsonDirectoryTemplate : public DirectoryTemplate public: JsonDirectoryTemplate(IDataSourceStream* source, Directory* dir) : DirectoryTemplate(source, dir) { - setDoubleBraces(true); setFormatter(Format::json); } }; diff --git a/Sming/Core/Data/Stream/LimitedWriteStream.h b/Sming/Core/Data/Stream/LimitedWriteStream.h new file mode 100644 index 0000000000..a2d0bae843 --- /dev/null +++ b/Sming/Core/Data/Stream/LimitedWriteStream.h @@ -0,0 +1,56 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * LimitedWriteStream.h + * + * @author: 2021 - Slavey Karadzhov + * + ****/ + +#pragma once + +#include + +/** + * @brief A stream wrapper class that limits the number of bytes that can be written. + * Helpful when writing on a file system or memory should be limited to the available size of the media. + * @ingroup stream + */ +class LimitedWriteStream : public StreamWrapper +{ +public: + LimitedWriteStream(ReadWriteStream* source, size_t maxBytes) : StreamWrapper(source), maxBytes(maxBytes) + { + } + + bool isValid() + { + return writePos <= maxBytes; + } + + /** @brief Writes characters from a buffer to output stream + * + * @param buffer Pointer to character buffer + * @param size Quantity of characters to write + * + * @retval size_t Quantity of characters written to stream. + * @note Surplus characters will be discarded. + * + */ + size_t write(const uint8_t* buffer, size_t size) override + { + writePos += size; + if(writePos > maxBytes) { + return size; + } + + return getSource()->write(buffer, size); + } + +private: + const size_t maxBytes; + size_t writePos{0}; +}; diff --git a/Sming/Core/Data/Stream/MemoryDataStream.cpp b/Sming/Core/Data/Stream/MemoryDataStream.cpp index 03d700ff0a..8d38750901 100644 --- a/Sming/Core/Data/Stream/MemoryDataStream.cpp +++ b/Sming/Core/Data/Stream/MemoryDataStream.cpp @@ -9,6 +9,7 @@ ****/ #include "MemoryDataStream.h" +#include MemoryDataStream::MemoryDataStream(String&& string) noexcept { diff --git a/Sming/Core/Data/Stream/ReadWriteStream.cpp b/Sming/Core/Data/Stream/ReadWriteStream.cpp index af972a11a8..d4e36bf76d 100644 --- a/Sming/Core/Data/Stream/ReadWriteStream.cpp +++ b/Sming/Core/Data/Stream/ReadWriteStream.cpp @@ -21,9 +21,8 @@ size_t ReadWriteStream::copyFrom(IDataSourceStream* source, size_t size) auto bufSize = std::min(size, maxBufferSize); char buffer[bufSize]; size_t total = 0; - size_t count; while(!source->isFinished()) { - count = source->readMemoryBlock(buffer, bufSize); + size_t count = source->readMemoryBlock(buffer, bufSize); if(count == 0) { continue; } diff --git a/Sming/Core/Data/Stream/SectionStream.cpp b/Sming/Core/Data/Stream/SectionStream.cpp index 7eef06378f..56e663e52f 100644 --- a/Sming/Core/Data/Stream/SectionStream.cpp +++ b/Sming/Core/Data/Stream/SectionStream.cpp @@ -11,16 +11,19 @@ ****/ #include "SectionStream.h" +#include /* * Scan through entire source stream to map location and size of sections. * Called once by constructor. */ -void SectionStream::scanSource() +void SectionStream::scanSource(uint8_t maxSections) { constexpr size_t bufSize{512}; char buffer[bufSize]; + sections.reset(new Section[maxSections]{}); + size_t offset{0}; while(sectionCount < maxSections && !stream->isFinished()) { auto& sect = sections[sectionCount]; diff --git a/Sming/Core/Data/Stream/SectionStream.h b/Sming/Core/Data/Stream/SectionStream.h index b5b3fb2ee7..3cb0230570 100644 --- a/Sming/Core/Data/Stream/SectionStream.h +++ b/Sming/Core/Data/Stream/SectionStream.h @@ -13,21 +13,18 @@ #pragma once #include "DataSourceStream.h" +#include /** * @brief Presents each section within a source stream as a separate stream * - * Sections are marked {!SECTION} ... {/SECTION} + * Sections are (by default) marked {!SECTION} ... {/SECTION} * This is typically used with templating but can be used with any stream type provided * the tags do not conflict with content. - * - * TODO: Allow tags to be changed. */ class SectionStream : public IDataSourceStream { public: - static constexpr uint8_t maxSections = 5; - struct Section { uint32_t start; // Within stream uint32_t size; @@ -51,14 +48,25 @@ class SectionStream : public IDataSourceStream */ using NextRecord = Delegate; - SectionStream(IDataSourceStream* source) : stream(source), startTag(F("{SECTION}")), endTag(F("{/SECTION}")) + /** + * @brief Construct a section stream with default options + */ + SectionStream(IDataSourceStream* source, uint8_t maxSections = 5) + : SectionStream(source, maxSections, F("{SECTION}"), F("{/SECTION}")) { - scanSource(); } - ~SectionStream() + /** + * @brief Construct a section stream + * @param source Contains all section data, must support random seeking + * @param startTag Unique text used to mark start of a section + * @param endTag Marks end of a section + */ + SectionStream(IDataSourceStream* source, uint8_t maxSections, const String& startTag, const String& endTag) + : startTag(startTag), endTag(endTag) { - delete stream; + stream.reset(source); + scanSource(maxSections); } int available() override @@ -86,16 +94,27 @@ class SectionStream : public IDataSourceStream return section ? section->recordIndex : -1; } + /** + * @brief Get number of sections in this stream + */ size_t count() const { return sectionCount; } + /** + * @brief Get description of the current section + * @retval Section* The section information, or nullptr if there is no current section + */ const Section* getSection() const { return getSection(currentSectionIndex); } + /** + * @brief Get description for any section given its index + * @retval Section* The section information, or nullptr if section was not found + */ const Section* getSection(unsigned index) const { if(index < sectionCount) { @@ -105,11 +124,17 @@ class SectionStream : public IDataSourceStream } } + /** + * @brief Register a callback to be invoked when moving to a new section + */ void onNextSection(NextSection callback) { nextSectionCallback = callback; } + /** + * @brief Register a callback to be invoked when moving to a new record + */ void onNextRecord(NextRecord callback) { nextRecordCallback = callback; @@ -120,6 +145,9 @@ class SectionStream : public IDataSourceStream */ bool gotoSection(uint8_t index); + /** + * @brief Goto a new section after current tag has been processed + */ bool setNewSection(int8_t index) { if(index < 0 || index >= sectionCount) { @@ -150,14 +178,14 @@ class SectionStream : public IDataSourceStream } private: - void scanSource(); + void scanSource(uint8_t maxSections); - IDataSourceStream* stream{nullptr}; + std::unique_ptr stream; NextSection nextSectionCallback; NextRecord nextRecordCallback; String startTag; String endTag; - Section sections[maxSections]{}; + std::unique_ptr sections; uint32_t readOffset{0}; uint32_t sectionOffset{0}; uint8_t sectionCount{0}; diff --git a/Sming/Core/Data/Stream/SectionTemplate.cpp b/Sming/Core/Data/Stream/SectionTemplate.cpp index 999aad8cfb..8f1d179a67 100644 --- a/Sming/Core/Data/Stream/SectionTemplate.cpp +++ b/Sming/Core/Data/Stream/SectionTemplate.cpp @@ -14,6 +14,7 @@ #include "TemplateStream.h" #include #include "../WebConstants.h" +#include namespace { @@ -244,8 +245,8 @@ class ArgList } // namespace -SectionTemplate::SectionTemplate(IDataSourceStream* source) - : TemplateStream(§ionStream, false), sectionStream(source) +SectionTemplate::SectionTemplate(IDataSourceStream* source, uint8_t maxSections) + : TemplateStream(§ionStream, false), sectionStream(source, maxSections) { setFormatter(Format::standard); sectionStream.onNextSection([this]() { seekFrom(0, SeekOrigin::Start); }); @@ -272,7 +273,7 @@ String SectionTemplate::closeTag() enableOutput(enable); if(conditionalLevel == 0 && newSection >= 0) { - debug_e("NewSection: %d", newSection); + debug_d("NewSection: %d", newSection); sectionStream.setNewSection(newSection); newSection = -1; } @@ -283,7 +284,7 @@ String SectionTemplate::closeTag() String SectionTemplate::elseTag() { if(newSection >= 0) { - debug_e("NewSection: %d", newSection); + debug_d("NewSection: %d", newSection); sectionStream.setNewSection(newSection); newSection = -1; } @@ -457,7 +458,7 @@ String SectionTemplate::evaluate(char*& expr) if(unsigned(n) >= sectionStream.count()) { return nullptr; } - debug_e("goto: %d, recordIndex = %d", n, recordIndex()); + debug_d("goto: %d, recordIndex = %d", n, recordIndex()); newSection = n; } return ""; diff --git a/Sming/Core/Data/Stream/SectionTemplate.h b/Sming/Core/Data/Stream/SectionTemplate.h index d396952c98..77d82b0612 100644 --- a/Sming/Core/Data/Stream/SectionTemplate.h +++ b/Sming/Core/Data/Stream/SectionTemplate.h @@ -28,6 +28,8 @@ * Anything else is treated as a variable name. * Separator is : * + * Conditional if/else/endif statements may be nested. + * * @note Command tags are prefixed with 'Q' to allow use of reserved words * in the Command enumeration. This represents the ! prefix in actual use. */ @@ -42,8 +44,8 @@ "{!pad:A:B:C} Copy of A padded to at least B characters with C (default is space). Use -ve B to left-pad. C") \ XX(Qrepeat, "{!repeat:A:B} Repeat A, number of iterations is B") \ XX(Qkb, "{!kb:A} Convert A to KB") \ - XX(Qifdef, "{!ifdef:A}block{/if} emit block if A is not zero-length") \ - XX(Qifndef, "{!ifdef:A}block{/if} emit block if A is zero-length") \ + XX(Qifdef, "{!ifdef:A} emit block if A is not zero-length") \ + XX(Qifndef, "{!ifdef:A} emit block if A is zero-length") \ XX(Qifeq, "{!ifeq:A:B} emit block if A == B") \ XX(Qifneq, "{!ifneq:A:B} emit block if A != B") \ XX(Qifgt, "{!ifgt:A:B} emit block if A > B") \ @@ -55,7 +57,7 @@ XX(Qifnin, "{!ifin:A:B} emit block if A does not contain B") \ XX(Qelse, "{!else}") \ XX(Qendif, "{!endif}") \ - XX(Qadd, "{!add:A:B} A - B") \ + XX(Qadd, "{!add:A:B} A + B") \ XX(Qsub, "{!sub:A:B} A - B") \ XX(Qgoto, "{!goto:A} move to section A") \ XX(Qcount, "{!count:A} emit number of records in section A") \ @@ -85,7 +87,7 @@ class SectionTemplate : public TemplateStream #undef XX }; - SectionTemplate(IDataSourceStream* source); + SectionTemplate(IDataSourceStream* source, uint8_t maxSections = 5); /** * @brief Application callback to process additional fields @@ -93,54 +95,99 @@ class SectionTemplate : public TemplateStream * @param name Field name, never null * @retval String The field value * @note Applications should call `escape()` if required before returning content. - * Use `stream.state()` to determine the current section being processed. */ using GetValue = Delegate; using NextRecord = SectionStream::NextRecord; + /** + * @brief Set a callback to be invoked + * + * Alternative to subclassing. + */ void onGetValue(GetValue callback) { getValueCallback = callback; } + /** + * @brief Associate a text format with this template stream + * @param formatter Provide formatter so we can call escape(), etc. as required + */ void setFormatter(Formatter& formatter) { activeFormatter = &formatter; } + /** + * @brief Get the stream format + * @retval Formatter& The formatter in effect. Default is :cpp:class:Format::Standard. + */ Formatter& formatter() const { return *activeFormatter; } + /** + * @brief Get the MIME type associated with this template stream + * @retval MimeType As defined by the formatter. Default is MIME_TEXT. + */ MimeType getMimeType() const override { return activeFormatter->mimeType(); } + /** + * @brief Access the underlying section stream + * @retval SectionStream& Wraps source stream provided in constructor + * + * Provided for debugging and other purposes. + * Applications should not use this method. + */ const SectionStream& stream() const { return sectionStream; } + /** + * @brief Get the index for the current section + * @retval int Indices are 0-based, returns -1 if 'Before Start' + */ int sectionIndex() const { return sectionStream.sectionIndex(); } + /** + * @brief Get number of sections in source stream + * @retval uint8_t Source is scanned in constructor so this is always valid + */ uint8_t sectionCount() const { return sectionStream.count(); } + /** + * @brief Get current record index + * @retval int Indices are 0-based, returns -1 if 'Before Start' + */ int recordIndex() const { return sectionStream.recordIndex(); } + /** + * @brief Discard current output and change current section + * @param uint8_t Index of section to move to + * @retval bool true on success, false if section index invalid + */ bool gotoSection(uint8_t index); + /** + * @brief Set a callback to be invoked when a new record is required + * + * Can be used as alternative to subclassing. + */ void onNextRecord(NextRecord callback) { nextRecordCallback = callback; diff --git a/Sming/Core/Data/Stream/StreamWrapper.h b/Sming/Core/Data/Stream/StreamWrapper.h new file mode 100644 index 0000000000..51cc1419fe --- /dev/null +++ b/Sming/Core/Data/Stream/StreamWrapper.h @@ -0,0 +1,51 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * StreamWrapper.h + * + * @author: 2021 - Slavey Karadzhov + * + ****/ + +#pragma once + +#include "ReadWriteStream.h" +#include + +/** + * @brief An abstract class that provides a wrapper around a stream + * @ingroup stream + */ +class StreamWrapper : public ReadWriteStream +{ +public: + StreamWrapper(ReadWriteStream* source) : source(source) + { + } + + StreamType getStreamType() const override + { + return eSST_Wrapper; + } + + uint16_t readMemoryBlock(char* data, int bufSize) override + { + return source ? source->readMemoryBlock(data, bufSize) : 0; + } + + ReadWriteStream* getSource() const + { + return source.get(); + } + + bool isFinished() override + { + return source ? source->isFinished() : true; + } + +private: + std::unique_ptr source; +}; diff --git a/Sming/Core/Data/Stream/TemplateStream.cpp b/Sming/Core/Data/Stream/TemplateStream.cpp index a3fe30d7a1..35ad5a5be0 100644 --- a/Sming/Core/Data/Stream/TemplateStream.cpp +++ b/Sming/Core/Data/Stream/TemplateStream.cpp @@ -9,6 +9,7 @@ ****/ #include "TemplateStream.h" +#include String TemplateStream::evaluate(char*& expr) { @@ -66,9 +67,16 @@ uint16_t TemplateStream::readMemoryBlock(char* data, int bufSize) return 0; } - auto findStartTag = [this](char* buf) { - auto p = doubleBraces ? strstr(buf, "{{") : strchr(buf, '{'); - return static_cast(p); + auto findStartTag = [this](char* buf) -> char* { + if(doubleBraces) { + return strstr(buf, "{{"); + } + + char* p = buf; + while((p = strchr(p, '{')) != nullptr && (p[1] <= ' ' || p[1] == '"')) { + ++p; + } + return p; }; auto start = data; diff --git a/Sming/Core/Data/Stream/TemplateStream.h b/Sming/Core/Data/Stream/TemplateStream.h index 824fb134d3..5e8839efab 100644 --- a/Sming/Core/Data/Stream/TemplateStream.h +++ b/Sming/Core/Data/Stream/TemplateStream.h @@ -26,13 +26,29 @@ * @brief Stream which performs variable-value substitution on-the-fly * * Template uses {varname} style markers which are replaced as the stream is read. + * + * Note: There must be no whitespace after the opening brace. + * For example, `{ varname }` will be emitted as-is without modification. + * + * This allows inclusion of CSS fragments such as `td { padding: 0 10px; }` in HTML. + * + * If necessary, use double-braces `{{varname}}` in templates and enable by calling `setDoubleBraces(true)`. + * + * Invalid tags, such as `{"abc"}` will be ignored, so JSON templates do not require special treatment. * * @ingroup stream */ class TemplateStream : public IDataSourceStream { public: + /** + * @brief Maps variable names to values + */ using Variables = HashMap; + + /** + * @brief Callback type to return calculated or externally stored values + */ using GetValueDelegate = Delegate; /** @brief Create a template stream @@ -116,6 +132,11 @@ class TemplateStream : public IDataSourceStream enableNextState = enable; } + /** + * @brief Determine if stream output is active + * + * Used by SectionTemplate class when processing conditional tags. + */ bool isOutputEnabled() const { return outputEnabled; @@ -130,8 +151,31 @@ class TemplateStream : public IDataSourceStream doubleBraces = enable; } + /** + * @brief Evaluate a template expression + * @param expr IN: First character after the opening brace(s) + * OUT: First character after the closing brace(s) + * @retval String + * + * Called internally and an opening brace ("{" or "{{") has been found. + * Default behaviour is to locate the closing brace(s) and interpret the + * bounded text as a variable name, which is passsed to `getValue`. + * + * This method is overridden by SectionTemplate to support more complex expressions. + */ virtual String evaluate(char*& expr); + /** + * @brief Evaluate an expression in-situ + * @param expr Expression to evaluate + * @retval String + */ + String eval(String expr) + { + char* p = expr.begin(); + return evaluate(p); + } + /** * @brief Fetch a templated value * @param name The variable name @@ -166,8 +210,3 @@ class TemplateStream : public IDataSourceStream bool enableNextState : 1; bool doubleBraces : 1; }; - -/** - * @deprecated Use `TemplateStream::Variables` instead - */ -typedef TemplateStream::Variables TemplateVariables; diff --git a/Sming/Core/Data/Stream/XorOutputStream.h b/Sming/Core/Data/Stream/XorOutputStream.h index cd4434b09d..831a1df2a6 100644 --- a/Sming/Core/Data/Stream/XorOutputStream.h +++ b/Sming/Core/Data/Stream/XorOutputStream.h @@ -16,6 +16,7 @@ /** * @brief Xors original stream content with the specified mask + * @ingroup stream */ class XorOutputStream : public IDataSourceStream { diff --git a/Sming/Core/Data/StreamTransformer.cpp b/Sming/Core/Data/StreamTransformer.cpp index f719e4698f..81f1ca1f2a 100644 --- a/Sming/Core/Data/StreamTransformer.cpp +++ b/Sming/Core/Data/StreamTransformer.cpp @@ -48,6 +48,7 @@ void StreamTransformer::fillTempStream(char* buffer, size_t bufSize) } auto written = tempStream->write(result, outLength); + (void)written; assert(written == outLength); sourceStream->seek(chunkSize); diff --git a/Sming/Core/Data/StreamTransformer.h b/Sming/Core/Data/StreamTransformer.h index fe293ec88e..d8f1178660 100644 --- a/Sming/Core/Data/StreamTransformer.h +++ b/Sming/Core/Data/StreamTransformer.h @@ -15,18 +15,8 @@ #include "Buffer/CircularBuffer.h" /** - * @brief Class that can be used to transform streams of data on the fly - * @ingroup stream data - * - * @{ - */ - -/** - * @brief Callback specification for the stream transformers - * @see See `StreamTransformer::transform()` method for details + * @brief Class that can be used to transform streams of data on the fly */ -using StreamTransformerCallback = Delegate; - class StreamTransformer : public IDataSourceStream { public: @@ -35,18 +25,6 @@ class StreamTransformer : public IDataSourceStream { } - /** @brief Constructor with external callback function - * @deprecated Create inherited class, override `transform()` method and use alternative constructor instead - */ - StreamTransformer(IDataSourceStream* stream, const StreamTransformerCallback& callback, size_t resultSize = 256, - size_t blockSize = 64) SMING_DEPRECATED : transformCallback(callback), - sourceStream(stream), - result(new uint8_t[resultSize]), - resultSize(resultSize), - blockSize(blockSize) - { - } - ~StreamTransformer() { delete[] result; @@ -106,15 +84,7 @@ class StreamTransformer : public IDataSourceStream * @retval size_t number of output bytes written * @note Called with `in = nullptr` and `inLength = 0` at end of input stream */ - virtual size_t transform(const uint8_t* in, size_t inLength, uint8_t* out, size_t outLength) - { - return (transformCallback == nullptr) ? 0 : transformCallback(in, inLength, out, outLength); - } - - /** @brief Callback function to perform transformation - * @deprecated Create inherited class and override transform() method instead - */ - StreamTransformerCallback transformCallback = nullptr; + virtual size_t transform(const uint8_t* in, size_t inLength, uint8_t* out, size_t outLength) = 0; private: void fillTempStream(char* buffer, size_t bufSize); @@ -125,5 +95,3 @@ class StreamTransformer : public IDataSourceStream size_t resultSize; size_t blockSize; }; - -/** @} */ diff --git a/Sming/Core/Data/WebConstants.h b/Sming/Core/Data/WebConstants.h index 748107a46b..d44fde5123 100644 --- a/Sming/Core/Data/WebConstants.h +++ b/Sming/Core/Data/WebConstants.h @@ -107,26 +107,39 @@ inline MimeType fromString(const String& str) return fromString(str.c_str()); } -/** @brief Obtain MIME type value from file name or path, with extension - * @param fileName - * @param unknown Value to return if type cannot be determined - * @retval MimeType +/** + * @name Obtain MIME type value from file name or path, with extension + * @{ + */ + +/** + * @param fileName As NUL-terminated string + * @param unknown Value to return if type cannot be determined + * @retval MimeType */ MimeType fromFullFileName(const char* fileName, MimeType unknown); +/** + * @param fileName As wiring String + */ inline MimeType fromFullFileName(const String& fileName, MimeType unknown) { return fromFullFileName(fileName.c_str(), unknown); } -/** @name Obtain content type string from file name or path, with extension - * @param fileName - * @retval String - * @{ +/** + * @name Obtain content type string from file name or path, with extension + * @{ + */ + +/** + * @param fileName as NUL-terminated string + * @retval String */ String fromFullFileName(const char* fileName); -/** @brief Obtain content type string from file name or path, with extension +/** + * @param fileName as wiring String */ inline String fromFullFileName(const String& fileName) { diff --git a/Sming/Core/Data/WebHelpers/escape.cpp b/Sming/Core/Data/WebHelpers/escape.cpp index ef9e0002df..4fc9221854 100644 --- a/Sming/Core/Data/WebHelpers/escape.cpp +++ b/Sming/Core/Data/WebHelpers/escape.cpp @@ -17,7 +17,7 @@ static unsigned safe_append(char* dest, size_t len, const char* str) return len2; } -/* return true if 2 characters are valid hexidecimal */ +/* return true if 2 characters are valid hexadecimal */ static bool ishex(const char code[2]) { return isxdigit(code[0]) && isxdigit(code[1]); diff --git a/Sming/Core/Data/WebHelpers/escape.h b/Sming/Core/Data/WebHelpers/escape.h index d7b874392b..fa1b6b38dd 100644 --- a/Sming/Core/Data/WebHelpers/escape.h +++ b/Sming/Core/Data/WebHelpers/escape.h @@ -1,7 +1,6 @@ #pragma once -#include -#include "WString.h" +#include /** @brief Obtain number of characters required to escape the given text * @param s source text diff --git a/Sming/Core/DateTime.h b/Sming/Core/DateTime.h index 6a759def5f..d07047f1dc 100644 --- a/Sming/Core/DateTime.h +++ b/Sming/Core/DateTime.h @@ -68,10 +68,12 @@ enum dtDays_t { /** @brief Date and time class * - * Date and time functions mostly work with Unix time, the quantity of seconds since 00:00:00 1970-01-01. - * There is no support for leap seconds which are added (and in theory, removed) occasionally to compensate for earth rotation variation. - * This means that timespan calculation and free-running clocks may be inaccurate if they span leap seconds. - * To facilitate leap seconds, reference must be made to leap second table. This will not be done within the Sming framework and must be handled by application code if required. + * Date and time functions mostly work with Unix time, the quantity of seconds since 00:00:00 1970-01-01. + * There is no support for leap seconds which are added (and in theory, removed) occasionally to compensate for earth rotation variation. + * This means that timespan calculation and free-running clocks may be inaccurate if they span leap seconds. + * To facilitate leap seconds, reference must be made to leap second table. + * This will not be done within the Sming framework and must be handled by application code if required. + * * @note Sming uses 32-bit signed integer for its time_t data type which supports a range of +/-68 years. This means Sming is susceptible to Year 2038 problem. */ class DateTime @@ -132,18 +134,6 @@ class DateTime */ bool fromHttpDate(const String& httpDate); - /** @brief Parse a HTTP full date and set time and date - * @param httpDate HTTP full date in RFC 1123 format, e.g. Sun, 06 Nov 1994 08:49:37 GMT - * @retval bool True on success - * @note Also supports obsolete RFC 850 date format, e.g. Sunday, 06-Nov-94 08:49:37 GMT where 2 digit year represents range 1970-2069 - * @note GMT suffix is optional and is always assumed / ignored - * @deprecated Use `fromHttpDate()` instead - */ - bool parseHttpDate(const String& httpDate) SMING_DEPRECATED - { - return fromHttpDate(httpDate); - } - /** @brief Check if time date object is initialised * @retval True if object has no value. False if initialised. */ @@ -206,43 +196,7 @@ class DateTime static void fromUnixTime(time_t timep, uint8_t* psec, uint8_t* pmin, uint8_t* phour, uint8_t* pday, uint8_t* pwday, uint8_t* pmonth, uint16_t* pyear); - /** @deprecated Use unsigned version instead - * `fromUnixTime(time_t, uint8_t*, uint8_t*, uint8_t*, uint8_t*, uint8_t*, uint8_t*, uint16_t*)` */ - static void fromUnixTime(time_t timep, int8_t* psec, int8_t* pmin, int8_t* phour, int8_t* pday, int8_t* pwday, - int8_t* pmonth, int16_t* pyear) SMING_DEPRECATED - { - fromUnixTime(timep, reinterpret_cast(psec), reinterpret_cast(pmin), - reinterpret_cast(phour), reinterpret_cast(pday), - reinterpret_cast(pwday), reinterpret_cast(pmonth), - reinterpret_cast(pyear)); - } - // functions to convert to and from time components (hrs, secs, days, years etc) to time_t - /** @brief Convert from Unix time to individual time components - * @param timep Unix time date value to convert - * @param psec Pointer to integer to hold resulting seconds - * @param pmin Pointer to integer to hold resulting minutes - * @param phour Pointer to integer to hold resulting hour - * @param pday Pointer to integer to hold resulting day of month - * @param pwday Pointer to integer to hold resulting day of week - * @param pmonth Pointer to integer to hold resulting month - * @param pyear Pointer to integer to hold resulting year - * @note This is a more compact version of the C library localtime function - * @note Pass the Unix timedate value and pointers to existing integers. The integers are updated with the converted values - * @note This static function may be used without instantiating a DateTime object, e.g. DateTime::convertFromUnixTime(...); - * @note 32-bit Unix time has year 2036 issue. - * @note Unix time does not account for leap seconds. To convert Unix time to UTC requires reference to a leap second table. - * @note All of the return values are optional, specify nullptr if not required - * @deprecated Use `fromUnixTime(time_t, uint8_t*, uint8_t*, uint8_t*, uint8_t*, uint8_t*, uint8_t*, uint16_t*)` instead - */ - static void convertFromUnixTime(time_t timep, int8_t* psec, int8_t* pmin, int8_t* phour, int8_t* pday, - int8_t* pwday, int8_t* pmonth, int16_t* pyear) SMING_DEPRECATED - { - fromUnixTime(timep, reinterpret_cast(psec), reinterpret_cast(pmin), - reinterpret_cast(phour), reinterpret_cast(pday), - reinterpret_cast(pwday), reinterpret_cast(pmonth), - reinterpret_cast(pyear)); - } /** @brief Convert from individual time components to Unix time * @param sec Seconds @@ -258,25 +212,6 @@ class DateTime */ static time_t toUnixTime(uint8_t sec, uint8_t min, uint8_t hour, uint8_t day, uint8_t month, uint16_t year); - /** @brief Convert from individual time components to Unix time - * @param sec Seconds - * @param min Minutes - * @param hour Hours - * @param day Days - * @param month Month (0-11, Jan=0, Feb=1, ...Dec=11) - * @param year Year (1901-2036), either full 4 digit year or 2 digits for 1970-2036 - * @note Seconds, minutes, hours and days may be any value, e.g. to calculate the value for 300 days since 1970 (epoch), set day=300 - * @note This static function may be used without instantiating a DateTime object, e.g. time_t unixTime = DateTime::convertToUnixTime(...); - * @note 32-bit Unix time is valid between 1901-12-13 and 03:14:07 2038-01-19 - * @note Unix time does not account for leap seconds. To convert Unix time to UTC requires reference to a leap second table. - * @deprecated Use 'toUnixTime()' instead - */ - static time_t convertToUnixTime(uint8_t sec, uint8_t min, uint8_t hour, uint8_t day, uint8_t month, - uint16_t year) SMING_DEPRECATED - { - return toUnixTime(sec, min, hour, day, month, year); - } - /** @brief Create string formatted with time and date placeholders * @param formatString String including date and time formatting * @retval String Formatted string diff --git a/Sming/Core/Debug.cpp b/Sming/Core/Debug.cpp index d698fe1492..b95d9c1ea8 100644 --- a/Sming/Core/Debug.cpp +++ b/Sming/Core/Debug.cpp @@ -9,6 +9,7 @@ ****/ #include "Debug.h" +#include DebugClass::DebugClass() { diff --git a/Sming/Core/FileSystem.cpp b/Sming/Core/FileSystem.cpp index 7b10808d0e..92f1e08ea6 100644 --- a/Sming/Core/FileSystem.cpp +++ b/Sming/Core/FileSystem.cpp @@ -58,21 +58,6 @@ bool fwfs_mount(Storage::Partition partition) return fileMountFileSystem(fs); } -Vector fileList() -{ - Vector result; - - DirHandle dir; - if(fileOpenDir(nullptr, dir) == FS_OK) { - FileNameStat stat; - while(fileReadDir(dir, stat) >= 0) { - result.add(stat.name.buffer); - } - fileCloseDir(dir); - } - return result; -} - IFS::IFileSystem::Type fileSystemType() { if(SmingInternal::activeFileSystem == nullptr) { diff --git a/Sming/Core/FileSystem.h b/Sming/Core/FileSystem.h index ff4c72f4af..8c968d5701 100644 --- a/Sming/Core/FileSystem.h +++ b/Sming/Core/FileSystem.h @@ -19,10 +19,8 @@ #include #include #include -#include "WVector.h" ///< @deprecated see fileList() using file_t = IFS::FileHandle; -typedef SeekOrigin SeekOriginFlags; ///< @deprecated Use `SeekOrigin` instead using FileHandle = IFS::FileHandle; using DirHandle = IFS::DirHandle; using FileOpenFlag = IFS::OpenFlag; @@ -33,10 +31,6 @@ using FileStat = IFS::Stat; using FileNameStat = IFS::NameStat; constexpr int FS_OK = IFS::FS_OK; -constexpr SeekOrigin eSO_FileStart{SeekOrigin::Start}; ///< @deprecated use SeekOrigin::Start -constexpr SeekOrigin eSO_CurrentPos{SeekOrigin::Current}; ///< @deprecated use SeekOrigin::Current -constexpr SeekOrigin eSO_FileEnd{SeekOrigin::End}; ///< @deprecated use SeekOrigin::End - namespace SmingInternal { /** @brief Global file system instance @@ -71,15 +65,6 @@ class Directory : public IFS::Directory } }; -// Various file flag combinations -constexpr FileOpenFlags eFO_ReadOnly{File::ReadOnly}; ///< @deprecated use File::ReadOnly -constexpr FileOpenFlags eFO_WriteOnly{File::WriteOnly}; ///< @deprecated use File::WriteOnly -constexpr FileOpenFlags eFO_ReadWrite{File::ReadWrite}; ///< @deprecated use File::ReadWrite -constexpr FileOpenFlags eFO_CreateIfNotExist{File::Create}; ///< @deprecated use File::Create -constexpr FileOpenFlags eFO_Append{File::Append}; ///< @deprecated use File::Append -constexpr FileOpenFlags eFO_Truncate{File::Truncate}; ///< @deprecated use File::Truncate -constexpr FileOpenFlags eFO_CreateNewAlways{File::CreateNewAlways}; ///< @deprecated use File::CreateNewAlways - /* * Boilerplate check for file function wrappers to catch undefined filesystem. */ @@ -104,11 +89,11 @@ inline IFS::FileSystem* getFileSystem() /** @brief Sets the currently active file system * @param fileSystem - * @note Any existing filing system is freed first. + * @note Any existing filing system is destroyed. * Typically the filing system implementation has helper functions which * create and initialise the file system to a valid state. The last step * is to call this function to make it active. - * Call this function with nullptr to inactivate the filing system. + * Call this function with nullptr to deactivate the filing system. */ void fileSetFileSystem(IFS::IFileSystem* fileSystem); @@ -325,13 +310,6 @@ inline int fileRename(const String& oldName, const String& newName) return fileRename(oldName.c_str(), newName.c_str()); } -/** @brief Get list of files on file system - * @retval Vector Vector of strings. - Each string element contains the name of a file on the file system - @deprecated use `Directory` object (or fileOpenDir / fileReadDir / fileCloseDir) - */ -Vector fileList() SMING_DEPRECATED; - /** @brief Read content of a file * @param fileName Name of file to read from * @retval String String variable in to which to read the file content @@ -548,24 +526,17 @@ inline int fileSetACL(FileHandle file, const IFS::ACL& acl) return fileSystem->setacl(file, acl); } -/** @name Set file attributes +/** @brief Set file attributes * @param filename * @param attr * @retval int Error code - * @{ */ -inline int fileSetAttr(const char* filename, FileAttributes attr) +template int fileSetAttr(const T& filename, FileAttributes attr) { CHECK_FS(setattr) return fileSystem->setattr(filename, attr); } -inline int fileSetAttr(const String& filename, FileAttributes attr) -{ - return fileSetAttr(filename.c_str(), attr); -} -/** @} */ - /** @brief Set access control information for file * @param file handle to open file, must have write access * @retval int Error code diff --git a/Sming/Core/HardwarePWM.h b/Sming/Core/HardwarePWM.h index 69c8875882..78b27476fb 100644 --- a/Sming/Core/HardwarePWM.h +++ b/Sming/Core/HardwarePWM.h @@ -15,7 +15,7 @@ * Calculate the Duty as per the formulae give in ESP8266 SDK * Duty = (Period *1000)/45 * - * PWM can be generated on upto 8 pins (ie All pins except pin 16) + * PWM can be generated on up to 8 pins (ie All pins except pin 16) * Created on August 17, 2015, 2:27 PM * ****/ diff --git a/Sming/Core/HardwareSerial.h b/Sming/Core/HardwareSerial.h index c2fe0cc17c..a76a5dc22e 100644 --- a/Sming/Core/HardwareSerial.h +++ b/Sming/Core/HardwareSerial.h @@ -339,16 +339,6 @@ class HardwareSerial : public ReadWriteStream */ void commandProcessing(bool reqEnable); - /** @brief Set handler for received data - * @param dataReceivedDelegate Function to handle received data - * @retval bool Returns true if the callback was set correctly - * @deprecated Use `onDataReceived` instead - */ - bool setCallback(StreamDataReceivedDelegate dataReceivedDelegate) SMING_DEPRECATED - { - return onDataReceived(dataReceivedDelegate); - } - /** @brief Set handler for received data * @param dataReceivedDelegate Function to handle received data * @retval bool Returns true if the callback was set correctly @@ -373,7 +363,7 @@ class HardwareSerial : public ReadWriteStream * @brief Set callback ISR for received data * @param callback Function to handle received data * @param param Set as return value for `uart_get_callback_param()` - * @note callback is invoked directly from serial ISR and bypasses any registered delgates + * @note callback is invoked directly from serial ISR and bypasses any registered delegates */ __forceinline void setUartCallback(smg_uart_callback_t callback, void* param = nullptr) { diff --git a/Sming/Core/HardwareTimer.h b/Sming/Core/HardwareTimer.h index bf3677e0a2..364f21ea50 100644 --- a/Sming/Core/HardwareTimer.h +++ b/Sming/Core/HardwareTimer.h @@ -153,9 +153,4 @@ using HardwareTimer1 = CallbackTimer>; */ using HardwareTimer = HardwareTimer1<>; -/** - * @deprecated Use HardwareTimer class instead - */ -typedef HardwareTimer Hardware_Timer SMING_DEPRECATED; - /** @} */ diff --git a/Sming/Core/Interrupts.h b/Sming/Core/Interrupts.h index 42be9770f7..446d8e2387 100644 --- a/Sming/Core/Interrupts.h +++ b/Sming/Core/Interrupts.h @@ -32,9 +32,9 @@ __forceinline GPIO_INT_TYPE ConvertArduinoInterruptMode(uint8_t mode) switch(mode) { case LOW: // to trigger the interrupt whenever the pin is low, return GPIO_PIN_INTR_LOLEVEL; - case CHANGE: // to trigger the interrupt whenever the pin changes value - return (GPIO_INT_TYPE)3; // GPIO_PIN_INTR_ANYEDGE - case RISING: // to trigger when the pin goes from low to high, + case CHANGE: // to trigger the interrupt whenever the pin changes value + return GPIO_PIN_INTR_ANYEDGE; + case RISING: // to trigger when the pin goes from low to high, return GPIO_PIN_INTR_POSEDGE; case FALLING: // for when the pin goes from high to low. return GPIO_PIN_INTR_NEGEDGE; diff --git a/Sming/Core/SPISettings.h b/Sming/Core/SPISettings.h index ff9947a779..1e4d60b8a9 100644 --- a/Sming/Core/SPISettings.h +++ b/Sming/Core/SPISettings.h @@ -14,6 +14,9 @@ #pragma once #include "Digital.h" +#ifdef SPI_DEBUG +#include +#endif /** @ingroup base_spi * @{ @@ -105,7 +108,7 @@ class SPISettings #endif } - // overload operator to check wheter the settings are equal + // overload operator to check whether the settings are equal bool operator==(const SPISettings& other) const { return (speed == other.speed) && (byteOrder == other.byteOrder) && (dataMode == other.dataMode); diff --git a/Sming/Core/SmingCore.h b/Sming/Core/SmingCore.h index 9e06713097..afbb1c2407 100644 --- a/Sming/Core/SmingCore.h +++ b/Sming/Core/SmingCore.h @@ -62,6 +62,4 @@ #include "DateTime.h" -#include "fatfs/ff.h" - #include diff --git a/Sming/Core/SmingLocale.h b/Sming/Core/SmingLocale.h index 481a1af8f2..cfd7b56dd8 100644 --- a/Sming/Core/SmingLocale.h +++ b/Sming/Core/SmingLocale.h @@ -48,7 +48,7 @@ #elif LOCALE == LOCALE_EN_AU -// Austrailia is same as GB +// Australia is same as GB #endif // LOCALE diff --git a/Sming/Core/SmingVersion.h b/Sming/Core/SmingVersion.h index 76ce1b43ac..11a8c06c8b 100644 --- a/Sming/Core/SmingVersion.h +++ b/Sming/Core/SmingVersion.h @@ -6,8 +6,8 @@ */ #define SMING_MAJOR_VERSION 4 -#define SMING_MINOR_VERSION 4 -#define SMING_PATCH_VERSION 1 +#define SMING_MINOR_VERSION 5 +#define SMING_PATCH_VERSION 0 #define SMING_PRE_RELEASE "" #define MACROQUOT(x) #x diff --git a/Sming/Core/Timer.h b/Sming/Core/Timer.h index e22c9581e4..192314dc84 100644 --- a/Sming/Core/Timer.h +++ b/Sming/Core/Timer.h @@ -20,9 +20,6 @@ * @{ */ -/** @deprecated Use `TimerDelegate` */ -typedef std::function TimerDelegateStdFunction SMING_DEPRECATED; - /** * @brief Class template implementing an extended OS Timer with 64-bit microsecond times and delegate callback support */ diff --git a/Sming/Core/Wire.cpp b/Sming/Core/Wire.cpp index b04c587fae..738b554c79 100644 --- a/Sming/Core/Wire.cpp +++ b/Sming/Core/Wire.cpp @@ -2,6 +2,10 @@ TwoWire.cpp - TWI/I2C library for Arduino & Wiring Copyright (c) 2006 Nicholas Zambetti. All right reserved. + si2c.c - Software I2C library for esp8266 + Copyright (c) 2015 Hristo Gochkov. All rights reserved. + This file is part of the esp8266 core for Arduino environment. + This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either @@ -21,144 +25,150 @@ Modified April 2015 by Hrsto Gochkov (ficeto@ficeto.com) - alternative esp8266 support */ -extern "C" { -#include -#include -#include -} - -#include "twi.h" #include "Wire.h" +#include "Digital.h" +#include -// Initialize Class Variables ////////////////////////////////////////////////// - -uint8_t TwoWire::rxBuffer[BUFFER_LENGTH]; -uint8_t TwoWire::rxBufferIndex = 0; -uint8_t TwoWire::rxBufferLength = 0; - -uint8_t TwoWire::txAddress = 0; -uint8_t TwoWire::txBuffer[BUFFER_LENGTH]; -uint8_t TwoWire::txBufferIndex = 0; -uint8_t TwoWire::txBufferLength = 0; - -uint8_t TwoWire::transmitting = 0; -void (*TwoWire::user_onRequest)(void); -void (*TwoWire::user_onReceive)(int); - -static int default_sda_pin = 2; -static int default_scl_pin = 0; +#ifndef FCPU80 +#define FCPU80 80000000L +#endif -// Constructors //////////////////////////////////////////////////////////////// +#if F_CPU == FCPU80 +#define TWI_CLOCK_STRETCH_MULTIPLIER 3 +#else +#define TWI_CLOCK_STRETCH_MULTIPLIER 6 +#endif -TwoWire::TwoWire() +void TwoWire::begin(uint8_t sda, uint8_t scl) { + twi_sda = sda; + twi_scl = scl; + begin(); } -// Public Methods ////////////////////////////////////////////////////////////// - -void TwoWire::begin(int sda, int scl) +void TwoWire::pins(uint8_t sda, uint8_t scl) { - default_sda_pin = sda; - default_scl_pin = scl; - twi_init(sda, scl); - flush(); -} + debug_d("[TWI] pins(%u, %u)", sda, scl); -void TwoWire::pins(int sda, int scl) -{ - default_sda_pin = sda; - default_scl_pin = scl; + twi_sda = sda; + twi_scl = scl; } -void TwoWire::begin(void) +void TwoWire::begin() { - begin(default_sda_pin, default_scl_pin); -} + debug_d("[TWI] begin(%u, %u)", twi_sda, twi_scl); + pinMode(twi_sda, INPUT_PULLUP); + pinMode(twi_scl, INPUT_PULLUP); + setClock(100000); + setClockStretchLimit(230); // default value is 230 uS -void TwoWire::begin(uint8_t address) -{ - // twi_setAddress(address); - // twi_attachSlaveTxEvent(onRequestService); - // twi_attachSlaveRxEvent(onReceiveService); - begin(); + flush(); } -uint8_t TwoWire::status() +void TwoWire::end() { - return twi_status(); + debug_d("[TWI] end(%u, %u)", twi_sda, twi_scl); + pinMode(twi_sda, INPUT); + pinMode(twi_scl, INPUT); } -void TwoWire::begin(int address) +TwoWire::Status TwoWire::status() { - begin((uint8_t)address); -} + if(SCL_READ() == 0) { + // SCL held low by another device, no procedure available to recover + return I2C_SCL_HELD_LOW; + } -void TwoWire::setClock(uint32_t frequency) -{ - twi_setClock(frequency); -} + int clockCount = 20; -void TwoWire::setClockStretchLimit(uint32_t limit) -{ - twi_setClockStretchLimit(limit); -} + // if SDA low, read the bits slaves have to sent to a max + while(SDA_READ() == 0 && clockCount-- > 0) { + twi_read_bit(); + if(SCL_READ() == 0) { + // SCL held low beyond slave clock stretch time + return I2C_SCL_HELD_LOW_AFTER_READ; + } + } -size_t TwoWire::requestFrom(uint8_t address, size_t size, bool sendStop) -{ - if(size > BUFFER_LENGTH) { - size = BUFFER_LENGTH; + if(SDA_READ() == 0) { + // SDA line held low by slave/another_master after n bits + return I2C_SDA_HELD_LOW; } - size_t read = (twi_readFrom(address, rxBuffer, size, sendStop) == 0) ? size : 0; - rxBufferIndex = 0; - rxBufferLength = read; - return read; -} -uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop) -{ - return requestFrom(address, static_cast(quantity), static_cast(sendStop)); + if(!twi_write_start()) { + // Line busy. SDA again held low by another device. 2nd master? + return I2C_SDA_HELD_LOW_AFTER_INIT; + } + + return I2C_OK; } -uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity) +void TwoWire::setClock(uint32_t freq) { - return requestFrom(address, static_cast(quantity), true); + auto sys = System.getCpuFrequency(); + if(sys == eCF_80MHz) { + if(freq <= 100000) { + twi_dcount = 16; //about 100KHz + } else if(freq <= 200000) { + twi_dcount = 5; //about 200KHz + } else if(freq <= 300000) { + twi_dcount = 2; //about 300KHz + } else { + twi_dcount = 0; //about 400KHz + } + } else { // Assume eCF_160MHz + if(freq <= 100000) { + twi_dcount = 28; //about 100KHz + } else if(freq <= 200000) { + twi_dcount = 12; //about 200KHz + } else if(freq <= 300000) { + twi_dcount = 5; //about 300KHz + } else if(freq <= 400000) { + twi_dcount = 3; //about 400KHz + } else if(freq <= 500000) { + twi_dcount = 1; //about 500KHz + } else { + twi_dcount = 0; //about 600KHz + } + } } -uint8_t TwoWire::requestFrom(int address, int quantity) +void TwoWire::setClockStretchLimit(uint32_t limit) { - return requestFrom(static_cast(address), static_cast(quantity), true); + twi_clockStretchLimit = limit * TWI_CLOCK_STRETCH_MULTIPLIER; } -uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop) +uint8_t TwoWire::requestFrom(uint8_t address, uint8_t size, bool sendStop) { - return requestFrom(static_cast(address), static_cast(quantity), static_cast(sendStop)); + if(size == 0) { + return 0; + } + + if(size > BUFFER_LENGTH) { + size = BUFFER_LENGTH; + } + + auto err = twi_readFrom(address, rxBuffer, size, sendStop); + rxBufferIndex = 0; + rxBufferLength = err ? 0 : size; + return rxBufferLength; } void TwoWire::beginTransmission(uint8_t address) { - transmitting = 1; + transmitting = true; txAddress = address; txBufferIndex = 0; txBufferLength = 0; } -void TwoWire::beginTransmission(int address) -{ - beginTransmission((uint8_t)address); -} - -uint8_t TwoWire::endTransmission(uint8_t sendStop) +TwoWire::Error TwoWire::endTransmission(bool sendStop) { - int8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, sendStop); + auto err = twi_writeTo(txAddress, txBuffer, txBufferLength, sendStop); txBufferIndex = 0; txBufferLength = 0; - transmitting = 0; - return ret; -} - -uint8_t TwoWire::endTransmission(void) -{ - return endTransmission(true); + transmitting = false; + return err; } size_t TwoWire::write(uint8_t data) @@ -181,8 +191,9 @@ size_t TwoWire::write(const uint8_t* data, size_t quantity) { if(transmitting) { for(size_t i = 0; i < quantity; ++i) { - if(!write(data[i])) + if(write(data[i]) != 1) { return i; + } } } else { // i2c_slave_transmit(data, quantity); @@ -190,13 +201,12 @@ size_t TwoWire::write(const uint8_t* data, size_t quantity) return quantity; } -int TwoWire::available(void) +int TwoWire::available() { - int result = rxBufferLength - rxBufferIndex; - return result; + return rxBufferLength - rxBufferIndex; } -int TwoWire::read(void) +int TwoWire::read() { int value = -1; if(rxBufferIndex < rxBufferLength) { @@ -206,16 +216,12 @@ int TwoWire::read(void) return value; } -int TwoWire::peek(void) +int TwoWire::peek() { - int value = -1; - if(rxBufferIndex < rxBufferLength) { - value = rxBuffer[rxBufferIndex]; - } - return value; + return (rxBufferIndex < rxBufferLength) ? rxBuffer[rxBufferIndex] : -1; } -void TwoWire::flush(void) +void TwoWire::flush() { rxBufferIndex = 0; rxBufferLength = 0; @@ -226,7 +232,7 @@ void TwoWire::flush(void) void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes) { // don't bother if user hasn't registered a callback - // if(!user_onReceive){ + // if(!userReceiveCallback){ // return; // } // // don't bother if rx buffer is in use by a master requestFrom() op @@ -247,10 +253,10 @@ void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes) // user_onReceive(numBytes); } -void TwoWire::onRequestService(void) +void TwoWire::onRequestService() { // // don't bother if user hasn't registered a callback - // if(!user_onRequest){ + // if(!userRequestCallback){ // return; // } // // reset tx buffer iterator vars @@ -261,17 +267,151 @@ void TwoWire::onRequestService(void) // user_onRequest(); } -void TwoWire::onReceive(void (*function)(int)) +void TwoWire::twi_delay(uint8_t v) +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" + for(unsigned i = 0; i < v; i++) { + (void)SCL_READ(); + } +#pragma GCC diagnostic pop +} + +bool TwoWire::twi_write_start() +{ + SCL_HIGH(); + SDA_HIGH(); + if(SDA_READ() == 0) { + return false; + } + twi_delay(twi_dcount); + SDA_LOW(); + twi_delay(twi_dcount); + return true; +} + +bool TwoWire::twi_write_stop() +{ + SCL_LOW(); + SDA_LOW(); + twi_delay(twi_dcount); + SCL_HIGH(); + for(unsigned i = 0; SCL_READ() == 0 && i++ < twi_clockStretchLimit;) { + // Clock stretching + } + twi_delay(twi_dcount); + SDA_HIGH(); + twi_delay(twi_dcount); + + return true; +} + +bool TwoWire::twi_write_bit(bool bit) +{ + SCL_LOW(); + if(bit) { + SDA_HIGH(); + } else { + SDA_LOW(); + } + twi_delay(twi_dcount + 1); + SCL_HIGH(); + for(unsigned i = 0; SCL_READ() == 0 && i++ < twi_clockStretchLimit;) { + // Clock stretching + } + twi_delay(twi_dcount); + return true; +} + +bool TwoWire::twi_read_bit() { - //user_onReceive = function; + SCL_LOW(); + SDA_HIGH(); + twi_delay(twi_dcount + 2); + SCL_HIGH(); + for(unsigned i = 0; SCL_READ() == 0 && i++ < twi_clockStretchLimit;) { + // Clock stretching + } + bool bit = SDA_READ(); + twi_delay(twi_dcount); + return bit; } -void TwoWire::onRequest(void (*function)(void)) +bool TwoWire::twi_write_byte(uint8_t byte) { - //user_onRequest = function; + for(uint8_t mask = 0x80; mask != 0; mask >>= 1) { + twi_write_bit(byte & mask); + } + return !twi_read_bit(); //NACK/ACK +} + +uint8_t TwoWire::twi_read_byte(bool nack) +{ + uint8_t res{0}; + for(uint8_t mask = 0x80; mask != 0; mask >>= 1) { + res |= twi_read_bit() ? mask : 0; + } + twi_write_bit(nack); + return res; } -// Preinstantiate Objects ////////////////////////////////////////////////////// +TwoWire::Error TwoWire::twi_writeTo(uint8_t address, const uint8_t* buf, size_t len, bool sendStop) +{ + if(!twi_write_start()) { + return I2C_ERR_LINE_BUSY; + } + if(!twi_write_byte(((address << 1) | 0) & 0xFF)) { + if(sendStop) { + twi_write_stop(); + } + return I2C_ERR_ADDR_NACK; + } + for(unsigned i = 0; i < len; i++) { + if(!twi_write_byte(buf[i])) { + if(sendStop) { + twi_write_stop(); + } + return I2C_ERR_DATA_NACK; + } + } + if(sendStop) { + twi_write_stop(); + } + for(unsigned i = 0; SDA_READ() == 0 && i++ < 10;) { + SCL_LOW(); + twi_delay(twi_dcount); + SCL_HIGH(); + twi_delay(twi_dcount); + } + return I2C_ERR_SUCCESS; +} + +TwoWire::Error TwoWire::twi_readFrom(uint8_t address, uint8_t* buf, size_t len, bool sendStop) +{ + if(!twi_write_start()) { + return I2C_ERR_LINE_BUSY; + } + if(!twi_write_byte(((address << 1) | 1) & 0xFF)) { + if(sendStop) { + twi_write_stop(); + } + return I2C_ERR_ADDR_NACK; + } + for(unsigned i = 0; i + 1 < len; i++) { + buf[i] = twi_read_byte(false); + } + buf[len - 1] = twi_read_byte(true); + if(sendStop) { + twi_write_stop(); + } + for(unsigned i = 0; SDA_READ() == 0 && i++ < 10;) { + SCL_LOW(); + twi_delay(twi_dcount); + SCL_HIGH(); + twi_delay(twi_dcount); + } + return I2C_ERR_SUCCESS; +} #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_TWOWIRE) TwoWire Wire; diff --git a/Sming/Core/Wire.h b/Sming/Core/Wire.h index 0e34ce8e55..498c0cf36e 100644 --- a/Sming/Core/Wire.h +++ b/Sming/Core/Wire.h @@ -23,34 +23,98 @@ #pragma once -#include -#include "Stream.h" - -#define BUFFER_LENGTH 32 +#include +#include class TwoWire : public Stream { public: - TwoWire(); + static constexpr size_t BUFFER_LENGTH{32}; + + enum Status { + I2C_OK = 0, + I2C_SCL_HELD_LOW = 1, + I2C_SCL_HELD_LOW_AFTER_READ = 2, + I2C_SDA_HELD_LOW = 3, + I2C_SDA_HELD_LOW_AFTER_INIT = 4, + }; + + enum Error { + I2C_ERR_SUCCESS = 0, + I2C_ERR_ADDR_NACK = 2, + I2C_ERR_DATA_NACK = 3, + I2C_ERR_LINE_BUSY = 4, + }; + + using UserRequest = void (*)(); + using UserReceive = void (*)(int len); + + TwoWire() : Stream() + { + } - void begin(int sda, int scl); - void pins(int sda, int scl); + /** + * @brief Initialise using selected pins + */ + void begin(uint8_t sda, uint8_t scl); + + /** + * @brief Switch to selected pins + * + * If `begin()` has already been called then pins will change immediately, + * otherwise will be used by next call to `begin()`. + */ + void pins(uint8_t sda, uint8_t scl); + + /** + * @brief Initialise using current pin values + * + * Default pins depend on selected architecture. + */ void begin(); - void begin(uint8_t); - void begin(int); - void setClock(uint32_t); - void setClockStretchLimit(uint32_t); - void beginTransmission(uint8_t); - void beginTransmission(int); - uint8_t endTransmission(); - uint8_t endTransmission(uint8_t); - size_t requestFrom(uint8_t address, size_t size, bool sendStop); - uint8_t status(); - - uint8_t requestFrom(uint8_t, uint8_t); - uint8_t requestFrom(uint8_t, uint8_t, uint8_t); - uint8_t requestFrom(int, int); - uint8_t requestFrom(int, int, int); + + /** + * @brief End TwoWire operation + */ + void end(); + + /** + * @brief Set approximate clock frequency + */ + void setClock(uint32_t frequency); + + /** + * @brief Set approximate time in microseconds that clocks may be stretched by + */ + void setClockStretchLimit(uint32_t limit); + + /** + * @brief Signal start of transaction + * @param address Device address + */ + void beginTransmission(uint8_t address); + + /** + * @brief Perform actual transaction with device + * @param sendStop By default, send a stop condition + */ + Error endTransmission(bool sendStop = true); + + /** + * @brief Perform a complete 'read' transaction + * @param address Device to talk to + * @param size Number of bytes to receive + * @param sendStop By default, send a stop condition + */ + uint8_t requestFrom(uint8_t address, uint8_t size, bool sendStop = true); + + /** + * @brief Query bus status + * @retval Status Indicates whether bus is available + */ + Status status(); + + /* Stream methods */ size_t write(uint8_t) override; size_t write(const uint8_t*, size_t) override; @@ -59,46 +123,50 @@ class TwoWire : public Stream int peek() override; void flush() override; - void onReceive(void (*)(int)); - void onRequest(void (*)()); - - size_t write(unsigned long n) - { - return write(uint8_t(n)); - } - - size_t write(long n) - { - return write(uint8_t(n)); - } + using Print::write; - size_t write(unsigned int n) + // Slave mode not currently implemented + void onReceive(UserReceive callback) { - return write(uint8_t(n)); + // userReceiveCallback = callback; } - size_t write(int n) + // Slave mode not currently implemented + void onRequest(UserRequest callback) { - return write(uint8_t(n)); + // userRequestCallback = callback; } - using Print::write; - private: - static uint8_t rxBuffer[]; - static uint8_t rxBufferIndex; - static uint8_t rxBufferLength; - - static uint8_t txAddress; - static uint8_t txBuffer[]; - static uint8_t txBufferIndex; - static uint8_t txBufferLength; - - static uint8_t transmitting; - static void (*user_onRequest)(); - static void (*user_onReceive)(int); - static void onRequestService(); - static void onReceiveService(uint8_t*, int); + uint8_t twi_sda{DEFAULT_SDA_PIN}; + uint8_t twi_scl{DEFAULT_SCL_PIN}; + uint8_t twi_dcount{18}; + unsigned twi_clockStretchLimit{0}; + + uint8_t rxBuffer[BUFFER_LENGTH]{}; + uint8_t rxBufferIndex{0}; + uint8_t rxBufferLength{0}; + + uint8_t txAddress{0}; + uint8_t txBuffer[BUFFER_LENGTH]{}; + uint8_t txBufferIndex{0}; + uint8_t txBufferLength{0}; + + bool transmitting{false}; + UserRequest userRequestCallback{nullptr}; + UserReceive userReceiveCallback{nullptr}; + void onRequestService(); + void onReceiveService(uint8_t*, int); + + void twi_delay(uint8_t v); + bool twi_write_start(); + bool twi_write_stop(); + bool twi_write_bit(bool bit); + bool twi_read_bit(); + bool twi_write_byte(uint8_t byte); + uint8_t twi_read_byte(bool nack); + Error twi_writeTo(uint8_t address, const uint8_t* buf, size_t len, bool sendStop); + Error twi_readFrom(uint8_t address, uint8_t* buf, size_t len, bool sendStop); }; #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_TWOWIRE) diff --git a/Sming/Core/si2c.cpp b/Sming/Core/si2c.cpp index 521120d151..924cf6a051 100644 --- a/Sming/Core/si2c.cpp +++ b/Sming/Core/si2c.cpp @@ -249,7 +249,7 @@ uint8_t twi_status() int clockCount = 20; - while(SDA_READ() == 0 && clockCount > 0) { //if SDA low, read the bits slaves have to sent to a max + while(SDA_READ() == 0 && clockCount-- > 0) { //if SDA low, read the bits slaves have to sent to a max twi_read_bit(); if(SCL_READ() == 0) { return I2C_SCL_HELD_LOW_AFTER_READ; //I2C bus error. SCL held low beyond slave clock stretch time diff --git a/Sming/Kconfig b/Sming/Kconfig new file mode 100644 index 0000000000..d0fffe8f95 --- /dev/null +++ b/Sming/Kconfig @@ -0,0 +1,113 @@ +# +# For a description of the syntax of this configuration file, +# see kconfig/kconfig-language.txt. +# +mainmenu "${SMING_SOC} Sming Framework Configuration" + + config SMING_ARCH + string + option env="SMING_ARCH" + + menu "Sming" + choice + default SELECT_LOCALE_EN_GB + prompt "Date/Time country code" + help + Sming can format dates/time values based on a country code identified by this value. + This is provided as a #define symbol for your application to use. + See :source:`Sming/Core/SmingLocale.h` for further details. + config SELECT_LOCALE_EN_US + bool "English (US)" + config SELECT_LOCALE_EN_GB + bool "English (UK)" + config SELECT_LOCALE_EN_AU + bool "English (Australia)" + config SELECT_LOCALE_FR_FR + bool "Français" + config SELECT_LOCALE_DE_DE + bool "Deutsch" + endchoice + + config LOCALE + int + default 1 if SELECT_LOCALE_EN_US + default 33 if SELECT_LOCALE_FR_FR + default 44 if SELECT_LOCALE_EN_GB + default 49 if SELECT_LOCALE_DE_DE + default 61 if SELECT_LOCALE_EN_AU + + config COM_SPEED + int "Default baud rate for serial port" + default 115200 + help + This will recompile your application to use the revised baud rate. + Note that this will change the default speed used for both flashing and serial comms. + + config ENABLE_CMD_EXECUTOR + bool "Enable command executor functionality" + default y + help + This facilty requires documenting! + + config TASK_QUEUE_LENGTH + int "Length of task queue" + default 10 + depends on SMING_ARCH="Esp8266" || SMING_ARCH="Host" || SMING_ARCH="Rp2040" + + config STRING_OBJECT_SIZE + int "Size of a Wiring String object" + default 12 + help + Change this to increase space for Small String Optimisation (SSO) + + config DISABLE_NETWORK + bool "Build without networking support" + default n + select DISABLE_WIFI if DISABLE_NETWORK + help + Applications which do not require networking can set this flag to avoid building + or linking the core Network library. + + This will reduce build times, application size and RAM usage. + Builds will not succeeded if network code has been inadvertently included. + endmenu + + menu "Debug" + choice + default SELECT_DEBUG_INFO + prompt "Detail level for debug messages" + config SELECT_DEBUG_ERROR + bool "0 Errors only" + config SELECT_DEBUG_WARN + bool "1 Errors and warnings" + config SELECT_DEBUG_INFO + bool "2 Errors, warnings and Information" + config SELECT_DEBUG_DEBUG + bool "3 All debug messages" + endchoice + + config DEBUG_VERBOSE_LEVEL + int + default 0 if SELECT_DEBUG_ERROR + default 1 if SELECT_DEBUG_WARN + default 2 if SELECT_DEBUG_INFO + default 3 if SELECT_DEBUG_DEBUG + + config DEBUG_PRINT_FILENAME_AND_LINE + bool "Include the filename and line number in every line of debug output." + default n + help + This will require extra space on flash + + config ENABLE_GDB + bool "Compile with support for serial debugging using GDB" + + config ENABLE_SPI_DEBUG + bool "Enable SPI debug output" + + config ENABLE_TASK_COUNT + bool "Enable use of System task counting to check for queue overflows" + depends on SMING_ARCH="Esp8266" + endmenu + + source "$KCONFIG_COMPONENTS" diff --git a/Sming/Libraries/.patches/Adafruit_BME280_Library.patch b/Sming/Libraries/.patches/Adafruit_BME280_Library.patch deleted file mode 100644 index 19605ae6e3..0000000000 --- a/Sming/Libraries/.patches/Adafruit_BME280_Library.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff --git a/Adafruit_BME280.h b/Adafruit_BME280.h -index 61aeeed..383c8c8 100644 ---- a/Adafruit_BME280.h -+++ b/Adafruit_BME280.h -@@ -23,7 +23,7 @@ - #include "WProgram.h" - #endif - --#include -+#include - #include - - /*========================================================================= -diff --git a/README.md b/README.md -index ed49542..720c754 100644 ---- a/README.md -+++ b/README.md -@@ -1 +1,3 @@ -+# Adafruit BME280 Humidity/Pressure/Temperature sensor -+ - This is a library for the Adafruit BME280 Humidity, Barometric Pressure + Temp sensor - diff --git a/Sming/Libraries/.patches/Adafruit_BME280_Library/README.md b/Sming/Libraries/.patches/Adafruit_BME280_Library/README.md new file mode 100644 index 0000000000..5ebaad0976 --- /dev/null +++ b/Sming/Libraries/.patches/Adafruit_BME280_Library/README.md @@ -0,0 +1,18 @@ +# Adafruit BME280 Library + +[![Build Status](https://github.com/adafruit/Adafruit_BME280_Library/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit_BME280_Library/actions)[![Documentation](https://github.com/adafruit/ci-arduino/blob/master/assets/doxygen_badge.svg)](http://adafruit.github.io/Adafruit_BME280_Library/html/index.html) + + + +This is a library for the Adafruit BME280 Humidity, Barometric Pressure + Temp sensor + +Designed specifically to work with the [Adafruit BME280 Breakout](http://www.adafruit.com/products/2652). + +Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! + +## About this Driver +Written by Ladyada for Adafruit Industries. + +BSD license, check license.txt for more information + +All text above must be included in any redistribution diff --git a/Sming/Libraries/.patches/Adafruit_BME280_Library/component.mk b/Sming/Libraries/.patches/Adafruit_BME280_Library/component.mk index c858106dbd..692afb73f4 100644 --- a/Sming/Libraries/.patches/Adafruit_BME280_Library/component.mk +++ b/Sming/Libraries/.patches/Adafruit_BME280_Library/component.mk @@ -1 +1,5 @@ -COMPONENT_DEPENDS := Adafruit_Sensor +COMPONENT_DEPENDS := \ + Adafruit_Sensor \ + Adafruit_BusIO + +COMPONENT_INCDIRS := . diff --git a/Sming/Libraries/.patches/Adafruit_BusIO.patch b/Sming/Libraries/.patches/Adafruit_BusIO.patch new file mode 100644 index 0000000000..6c2fa02afd --- /dev/null +++ b/Sming/Libraries/.patches/Adafruit_BusIO.patch @@ -0,0 +1,90 @@ +diff --git a/Adafruit_SPIDevice.h b/Adafruit_SPIDevice.h +index e144bf0..ec2dc7d 100644 +--- a/Adafruit_SPIDevice.h ++++ b/Adafruit_SPIDevice.h +@@ -2,66 +2,20 @@ + #define Adafruit_SPIDevice_h + + #include +- +-#if !defined(SPI_INTERFACES_COUNT) || \ +- (defined(SPI_INTERFACES_COUNT) && (SPI_INTERFACES_COUNT > 0)) +- + #include + +-// some modern SPI definitions don't have BitOrder enum +-#if (defined(__AVR__) && !defined(ARDUINO_ARCH_MEGAAVR)) || \ +- defined(ESP8266) || defined(TEENSYDUINO) || defined(SPARK) || \ +- defined(ARDUINO_ARCH_SPRESENSE) || defined(MEGATINYCORE) || \ +- defined(DXCORE) || defined(ARDUINO_AVR_ATmega4809) || \ +- defined(ARDUINO_AVR_ATmega4808) || defined(ARDUINO_AVR_ATmega3209) || \ +- defined(ARDUINO_AVR_ATmega3208) || defined(ARDUINO_AVR_ATmega1609) || \ +- defined(ARDUINO_AVR_ATmega1608) || defined(ARDUINO_AVR_ATmega809) || \ +- defined(ARDUINO_AVR_ATmega808) || defined(ARDUINO_ARCH_ARC32) +- + typedef enum _BitOrder { + SPI_BITORDER_MSBFIRST = MSBFIRST, + SPI_BITORDER_LSBFIRST = LSBFIRST, + } BusIOBitOrder; + +-#elif defined(ESP32) || defined(__ASR6501__) +- +-// some modern SPI definitions don't have BitOrder enum and have different SPI +-// mode defines +-typedef enum _BitOrder { +- SPI_BITORDER_MSBFIRST = SPI_MSBFIRST, +- SPI_BITORDER_LSBFIRST = SPI_LSBFIRST, +-} BusIOBitOrder; +- +-#else +-// Some platforms have a BitOrder enum but its named MSBFIRST/LSBFIRST +-#define SPI_BITORDER_MSBFIRST MSBFIRST +-#define SPI_BITORDER_LSBFIRST LSBFIRST +-typedef BitOrder BusIOBitOrder; +-#endif +- +-#if defined(__AVR__) || defined(TEENSYDUINO) +-typedef volatile uint8_t BusIO_PortReg; +-typedef uint8_t BusIO_PortMask; +-#define BUSIO_USE_FAST_PINIO +- +-#elif defined(ESP8266) || defined(ESP32) || defined(__SAM3X8E__) || \ +- defined(ARDUINO_ARCH_SAMD) + typedef volatile uint32_t BusIO_PortReg; + typedef uint32_t BusIO_PortMask; +-#define BUSIO_USE_FAST_PINIO + +-#elif (defined(__arm__) || defined(ARDUINO_FEATHER52)) && \ +- !defined(ARDUINO_ARCH_MBED) && !defined(ARDUINO_ARCH_RP2040) +-typedef volatile uint32_t BusIO_PortReg; +-typedef uint32_t BusIO_PortMask; +-#if not defined(__ASR6501__) ++#ifdef ARCH_ESP8266 + #define BUSIO_USE_FAST_PINIO + #endif + +-#else +-#undef BUSIO_USE_FAST_PINIO +-#endif +- + /**! The class which defines how we will talk to this device over SPI **/ + class Adafruit_SPIDevice { + public: +@@ -103,5 +57,4 @@ private: + bool _begun; + }; + +-#endif // has SPI defined + #endif // Adafruit_SPIDevice_h +diff --git a/README.md b/README.md +index 1cc06a1..d98c288 100644 +--- a/README.md ++++ b/README.md +@@ -1,5 +1,6 @@ +-# Adafruit Bus IO Library [![Build Status](https://github.com/adafruit/Adafruit_BusIO/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit_BusIO/actions) ++# Adafruit Bus IO Library + ++[![Build Status](https://github.com/adafruit/Adafruit_BusIO/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit_BusIO/actions) + + This is a helper library to abstract away I2C & SPI transactions and registers + diff --git a/Sming/Libraries/.patches/Adafruit_BusIO/component.mk b/Sming/Libraries/.patches/Adafruit_BusIO/component.mk new file mode 100644 index 0000000000..e804df1d29 --- /dev/null +++ b/Sming/Libraries/.patches/Adafruit_BusIO/component.mk @@ -0,0 +1 @@ +COMPONENT_INCDIRS := . diff --git a/Sming/Libraries/.patches/Adafruit_SSD1306/component.mk b/Sming/Libraries/.patches/Adafruit_SSD1306/component.mk index f2997c2408..f1713fa80a 100644 --- a/Sming/Libraries/.patches/Adafruit_SSD1306/component.mk +++ b/Sming/Libraries/.patches/Adafruit_SSD1306/component.mk @@ -1 +1,2 @@ +COMPONENT_SOC := esp8266 COMPONENT_DEPENDS := Adafruit_GFX diff --git a/Sming/Libraries/.patches/Adafruit_Sensor/component.mk b/Sming/Libraries/.patches/Adafruit_Sensor/component.mk new file mode 100644 index 0000000000..e804df1d29 --- /dev/null +++ b/Sming/Libraries/.patches/Adafruit_Sensor/component.mk @@ -0,0 +1 @@ +COMPONENT_INCDIRS := . diff --git a/Sming/Libraries/.patches/Adafruit_VL53L0X.patch b/Sming/Libraries/.patches/Adafruit_VL53L0X.patch index 81d5a6cd62..fcb74eaf6d 100644 --- a/Sming/Libraries/.patches/Adafruit_VL53L0X.patch +++ b/Sming/Libraries/.patches/Adafruit_VL53L0X.patch @@ -1,100 +1,27 @@ +diff --git a/README.md b/README.md +index c7c7435..f5cc654 100644 +--- a/README.md ++++ b/README.md +@@ -1,4 +1,6 @@ +-# Adafruit VL53L0X Library [![Build Status](https://github.com/adafruit/Adafruit_VL53L0X/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit_VL53L0X/actions)[![Documentation](https://github.com/adafruit/ci-arduino/blob/master/assets/doxygen_badge.svg)](http://adafruit.github.io/Adafruit_VL53L0X/html/index.html) ++# Adafruit VL53L0X Library ++ ++[![Build Status](https://travis-ci.com/adafruit/Adafruit_VL53L0X.svg?branch=master)](https://travis-ci.com/adafruit/Adafruit_VL53L0X) + + + diff --git a/src/Adafruit_VL53L0X.cpp b/src/Adafruit_VL53L0X.cpp -index 5a1e650..6699d6e 100644 +index 00d0af2..8fd9bd2 100644 --- a/src/Adafruit_VL53L0X.cpp +++ b/src/Adafruit_VL53L0X.cpp -@@ -35,8 +35,8 @@ - #define VERSION_REQUIRED_MINOR 0 ///< Required sensor minor version - #define VERSION_REQUIRED_BUILD 1 ///< Required sensor build +@@ -36,8 +36,8 @@ + #define VERSION_REQUIRED_MINOR 0 ///< Required sensor minor version + #define VERSION_REQUIRED_BUILD 1 ///< Required sensor build --#define STR_HELPER( x ) #x ///< a string helper --#define STR( x ) STR_HELPER(x) ///< string helper wrapper +-#define STR_HELPER(x) #x ///< a string helper +-#define STR(x) STR_HELPER(x) ///< string helper wrapper +//#define STR_HELPER( x ) #x ///< a string helper +//#define STR( x ) STR_HELPER(x) ///< string helper wrapper /**************************************************************************/ - /*! -@@ -162,8 +162,33 @@ boolean Adafruit_VL53L0X::begin(uint8_t i2c_addr, boolean debug, TwoWire *i2c) { - Status = VL53L0X_SetLimitCheckEnable( pMyDevice, VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD, 1 ); - } - -- if( Status == VL53L0X_ERROR_NONE ) { -- Status = VL53L0X_SetLimitCheckValue( pMyDevice, VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD, (FixPoint1616_t)( 1.5 * 0.023 * 65536 ) ); -+ if(!longRange) { // 30mm to 1.2 meter -+ if( Status == VL53L0X_ERROR_NONE ) { -+ Status = VL53L0X_SetLimitCheckValue( pMyDevice, VL53L0X_CHECKENABLE_RANGE_IGNORE_THRESHOLD, (FixPoint1616_t)( 1.5 * 0.023 * 65536 ) ); -+ } -+ } -+ else { // can detect as far as 1.5 to 2 meters on a nice white reflective surface -+ // @credits: https://github.com/satoshinm/Adafruit_VL53L0X/commit/72c71bd44091f95ef1211f9ff3928e675dda1348 -+ // Long range mode - based on https://github.com/johnbryanmoore/VL53L0X_rasp_python/blob/master/python_lib/vl53l0x_python.c#L292 -+ if (Status == VL53L0X_ERROR_NONE) { -+ Status = VL53L0X_SetLimitCheckValue(pMyDevice, VL53L0X_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE, (FixPoint1616_t)(0.1*65536)); -+ } -+ -+ if (Status == VL53L0X_ERROR_NONE) { -+ Status = VL53L0X_SetLimitCheckValue(pMyDevice, VL53L0X_CHECKENABLE_SIGMA_FINAL_RANGE, (FixPoint1616_t)(60*65536)); -+ } -+ -+ if (Status == VL53L0X_ERROR_NONE) { -+ Status = VL53L0X_SetMeasurementTimingBudgetMicroSeconds(pMyDevice, 33000); -+ } -+ -+ if (Status == VL53L0X_ERROR_NONE) { -+ Status = VL53L0X_SetVcselPulsePeriod(pMyDevice, VL53L0X_VCSEL_PERIOD_PRE_RANGE, 18); -+ } -+ -+ if (Status == VL53L0X_ERROR_NONE) { -+ Status = VL53L0X_SetVcselPulsePeriod(pMyDevice, VL53L0X_VCSEL_PERIOD_FINAL_RANGE, 14); -+ } - } - - if( Status == VL53L0X_ERROR_NONE ) { -@@ -268,3 +293,8 @@ void Adafruit_VL53L0X::printRangeStatus( VL53L0X_RangingMeasurementData_t* pRang - Serial.println( buf ); - - } -+ -+void Adafruit_VL53L0X::setLongRangeMode(bool flag) -+{ -+ longRange = flag; -+} -diff --git a/src/Adafruit_VL53L0X.h b/src/Adafruit_VL53L0X.h -index 6f06604..47841c7 100644 ---- a/src/Adafruit_VL53L0X.h -+++ b/src/Adafruit_VL53L0X.h -@@ -38,6 +38,7 @@ - class Adafruit_VL53L0X - { - public: -+ void setLongRangeMode(bool flag); - boolean begin(uint8_t i2c_addr = VL53L0X_I2C_ADDR, boolean debug = false, TwoWire *i2c = &Wire); - boolean setAddress(uint8_t newAddr); - -@@ -65,6 +66,7 @@ class Adafruit_VL53L0X - VL53L0X_Version_t Version; - VL53L0X_Version_t *pVersion = &Version; - VL53L0X_DeviceInfo_t DeviceInfo; -+ bool longRange = false; - }; - - #endif -diff --git a/src/vl53l0x_platform_log.h b/src/vl53l0x_platform_log.h -index 26387d0..d203b3c 100644 ---- a/src/vl53l0x_platform_log.h -+++ b/src/vl53l0x_platform_log.h -@@ -88,13 +88,13 @@ void trace_print_module_function(uint32_t module, uint32_t level, uint32_t funct - #define LOG_GET_TIME() (int)clock() - - #define _LOG_FUNCTION_START(module, fmt, ... ) \ -- trace_print_module_function(module, _trace_level, TRACE_FUNCTION_ALL, "%ld %s "fmt"\n", LOG_GET_TIME(), __FUNCTION__, ##__VA_ARGS__); -+ trace_print_module_function(module, _trace_level, TRACE_FUNCTION_ALL, "%ld %s " fmt "\n", LOG_GET_TIME(), __FUNCTION__, ##__VA_ARGS__); - - #define _LOG_FUNCTION_END(module, status, ... )\ - trace_print_module_function(module, _trace_level, TRACE_FUNCTION_ALL, "%ld %s %d\n", LOG_GET_TIME(), __FUNCTION__, (int)status, ##__VA_ARGS__) - - #define _LOG_FUNCTION_END_FMT(module, status, fmt, ... )\ -- trace_print_module_function(module, _trace_level, TRACE_FUNCTION_ALL, "%ld %s %d "fmt"\n", LOG_GET_TIME(), __FUNCTION__, (int)status,##__VA_ARGS__) -+ trace_print_module_function(module, _trace_level, TRACE_FUNCTION_ALL, "%ld %s %d " fmt "\n", LOG_GET_TIME(), __FUNCTION__, (int)status,##__VA_ARGS__) - - // __func__ is gcc only - //#define VL53L0X_ErrLog( fmt, ...) fprintf(stderr, "VL53L0X_ErrLog %s" fmt "\n", __func__, ##__VA_ARGS__) + /*! diff --git a/Sming/Libraries/.patches/Adafruit_VL53L0X/component.mk b/Sming/Libraries/.patches/Adafruit_VL53L0X/component.mk index c2e24f2d72..eee8eb8b5d 100644 --- a/Sming/Libraries/.patches/Adafruit_VL53L0X/component.mk +++ b/Sming/Libraries/.patches/Adafruit_VL53L0X/component.mk @@ -1,5 +1,6 @@ -COMPONENT_SRCDIRS := src \ - src/core/src \ - src/platform/src - -COMPONENT_INCDIRS := $(COMPONENT_SRCDIRS) \ No newline at end of file +COMPONENT_SRCDIRS := \ + src \ + src/core/src \ + src/platform/src + +COMPONENT_INCDIRS := src diff --git a/Sming/Libraries/.patches/ArduinoFFT.patch b/Sming/Libraries/.patches/ArduinoFFT.patch index 79fb67b3db..35733262d0 100644 --- a/Sming/Libraries/.patches/ArduinoFFT.patch +++ b/Sming/Libraries/.patches/ArduinoFFT.patch @@ -163,7 +163,7 @@ index fb602a9..e038b41 100644 - void arduinoFFT::Windowing(uint8_t windowType, uint8_t dir) {// Weighing factors are computed once before multiple use of FFT - // The weighing function is symetric; half the weighs are recorded + // The weighing function is symmetric; half the weighs are recorded @@ -285,63 +184,6 @@ void arduinoFFT::Windowing(uint8_t windowType, uint8_t dir) } diff --git a/Sming/Libraries/.patches/IR/component.mk b/Sming/Libraries/.patches/IR/component.mk index af9a26e76b..f6ca09525d 100644 --- a/Sming/Libraries/.patches/IR/component.mk +++ b/Sming/Libraries/.patches/IR/component.mk @@ -1,2 +1,3 @@ +COMPONENT_SOC := esp8266 COMPONENT_DEPENDS := RingBufCPP COMPONENT_DOCFILES := ReleaseNotes.md .github/* diff --git a/Sming/Libraries/.patches/ITEADLIB_Arduino_Nextion.patch b/Sming/Libraries/.patches/ITEADLIB_Arduino_Nextion.patch index b753291189..a4afa36bc4 100644 --- a/Sming/Libraries/.patches/ITEADLIB_Arduino_Nextion.patch +++ b/Sming/Libraries/.patches/ITEADLIB_Arduino_Nextion.patch @@ -1,8 +1,17 @@ diff --git a/NexConfig.h b/NexConfig.h -index aa095d3..f06394f 100644 +index aa095d3..1e36b2f 100644 --- a/NexConfig.h +++ b/NexConfig.h -@@ -24,7 +24,7 @@ +@@ -15,6 +15,8 @@ + #ifndef __NEXCONFIG_H__ + #define __NEXCONFIG_H__ + ++#include ++ + /** + * @addtogroup Configuration + * @{ +@@ -24,7 +26,7 @@ * Define DEBUG_SERIAL_ENABLE to enable debug serial. * Comment it to disable debug serial. */ @@ -11,7 +20,7 @@ index aa095d3..f06394f 100644 /** * Define dbSerial for the output of debug messages. -@@ -34,7 +34,9 @@ +@@ -34,7 +36,9 @@ /** * Define nexSerial for communicate with Nextion touch panel. */ diff --git a/Sming/Libraries/.patches/ITEADLIB_Arduino_Nextion/README.rst b/Sming/Libraries/.patches/ITEADLIB_Arduino_Nextion/README.rst index 649e4cb836..4f043ea7cf 100644 --- a/Sming/Libraries/.patches/ITEADLIB_Arduino_Nextion/README.rst +++ b/Sming/Libraries/.patches/ITEADLIB_Arduino_Nextion/README.rst @@ -6,12 +6,12 @@ Introduction Nextion Arduino library provides an easy-to-use way to manipulate Nextion serial displays. Users can use the libarry freely, either in -commerical projects or open-source prjects, without any additional +commercial projects or open-source prjects, without any additional condiitons. | For more information about the Nextion display project, please visit `the wiki。 `__ -| The wiki provdies all the necessary technical documnets, quick start +| The wiki provides all the necessary technical documnets, quick start guide, tutorials, demos, as well as some useful resources. To get your Nextion display, please visit @@ -27,7 +27,7 @@ Latest version is unstable and a mass of change may be applied in a short time without any notification for users. Commonly, it is for developers of this library. -**Release version is recommanded for you, unless you are one of +**Release version is recommended for you, unless you are one of developers of this library.** **Release notes** is at @@ -57,11 +57,11 @@ https://github.com/itead/ITEADLIB_Arduino_Nextion/releases. Documentation ------------- -Offline Documentation’s entry ``doc/Documentation/index.html`` shiped +Offline Documentation’s entry ``doc/Documentation/index.html`` shipped with source code can be open in your browser such as Chrome, Firefox or any one you like. -Suppported Mainboards +Supported Mainboards --------------------- **All boards, which has one or more hardware serial, can be supported.** diff --git a/Sming/Libraries/.patches/MCP_CAN_lib.patch b/Sming/Libraries/.patches/MCP_CAN_lib.patch index 47e8ce989c..89dcfe4387 100644 --- a/Sming/Libraries/.patches/MCP_CAN_lib.patch +++ b/Sming/Libraries/.patches/MCP_CAN_lib.patch @@ -1,5 +1,5 @@ diff --git a/README.md b/README.md -index 291a1d0..8886c79 100644 +index 8c2fb42..fbdf826 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ @@ -10,9 +10,9 @@ index 291a1d0..8886c79 100644 MCP_CAN library v1.5 This library is compatible with any shield or board that uses the MCP2515 or MCP25625 CAN protocol controller. -@@ -24,15 +24,15 @@ Using the setMode() function the sketch can now put the protocol controller into +@@ -26,15 +26,15 @@ User can enable and disable (default) One-Shot transmission mode from the sketch - User can enable and disable (default) One-Shot transmission mode from the sketch using enOneShotTX() or disOneShotTX() respectively. + To wake up from CAN bus activity while in sleep mode enable the wake up interrupt with setSleepWakeup(1). Passing 0 will disable the wakeup interrupt (default). -Installation -============== @@ -31,10 +31,10 @@ index 291a1d0..8886c79 100644 diff --git a/mcp_can.cpp b/mcp_can.cpp -index c160939..89eca5c 100644 +index 2c01c7a..6464ebe 100644 --- a/mcp_can.cpp +++ b/mcp_can.cpp -@@ -179,8 +179,10 @@ INT8U MCP_CAN::mcp2515_setCANCTRL_Mode(const INT8U newmode) +@@ -231,8 +231,10 @@ INT8U MCP_CAN::mcp2515_requestNewMode(const INT8U newmode) *********************************************************************************************************/ INT8U MCP_CAN::mcp2515_configRate(const INT8U canSpeed, const INT8U canClock) { @@ -44,6 +44,6 @@ index c160939..89eca5c 100644 + INT8U cfg1 = 0; + INT8U cfg2 = 0; + INT8U cfg3 = 0; - switch (canClock) + switch (canClock & MCP_CLOCK_SELECT) { case (MCP_8MHZ): diff --git a/Sming/Libraries/.patches/ToneGenerator/component.mk b/Sming/Libraries/.patches/ToneGenerator/component.mk new file mode 100644 index 0000000000..84a4e1beca --- /dev/null +++ b/Sming/Libraries/.patches/ToneGenerator/component.mk @@ -0,0 +1,6 @@ +# This is a temporary patch until I2S support is added to the framework for other SoCs +COMPONENT_SOC := esp8266 host + +COMPONENT_INCDIRS := src/include +COMPONENT_SRCDIRS := src +COMPONENT_DOXYGEN_INPUT := src/include diff --git a/Sming/Libraries/AM2321/AM2321.cpp b/Sming/Libraries/AM2321/AM2321.cpp index 3987b2bd26..43993545c1 100644 --- a/Sming/Libraries/AM2321/AM2321.cpp +++ b/Sming/Libraries/AM2321/AM2321.cpp @@ -35,7 +35,7 @@ #define REG_AM2321_TEMPERATURE_LSB 0x03 //温度寄存器低位 #define REG_AM2321_DEVICE_ID_BIT_24_31 0x0B //32位设备ID高8位 -template +template class DataReader { protected: enum { len = 32 }; diff --git a/Sming/Libraries/AM2321/Weather.h b/Sming/Libraries/AM2321/Weather.h index 4becca4343..5a76ea41e4 100644 --- a/Sming/Libraries/AM2321/Weather.h +++ b/Sming/Libraries/AM2321/Weather.h @@ -10,8 +10,8 @@ namespace weather { // fast integer version with rounding inline - int fahrenheitFast(int celcius) { - return (celcius * 18 + 5)/10 + 32; + int fahrenheitFast(int celsius) { + return (celsius * 18 + 5)/10 + 32; } diff --git a/Sming/Libraries/Adafruit_BME280_Library b/Sming/Libraries/Adafruit_BME280_Library index 321186220e..ca3a36b7fd 160000 --- a/Sming/Libraries/Adafruit_BME280_Library +++ b/Sming/Libraries/Adafruit_BME280_Library @@ -1 +1 @@ -Subproject commit 321186220e1e04080bb70fa45aae6e6a5820899f +Subproject commit ca3a36b7fdfc701a90643a2bbfd112f84854eae6 diff --git a/Sming/Libraries/Adafruit_BusIO b/Sming/Libraries/Adafruit_BusIO new file mode 160000 index 0000000000..649bc9f93c --- /dev/null +++ b/Sming/Libraries/Adafruit_BusIO @@ -0,0 +1 @@ +Subproject commit 649bc9f93c00a19d4217281f0a6b1a2556fbd7bb diff --git a/Sming/Libraries/Adafruit_GFX/Adafruit_GFX.cpp b/Sming/Libraries/Adafruit_GFX/Adafruit_GFX.cpp index f0a3614338..300386f8a1 100644 --- a/Sming/Libraries/Adafruit_GFX/Adafruit_GFX.cpp +++ b/Sming/Libraries/Adafruit_GFX/Adafruit_GFX.cpp @@ -157,7 +157,7 @@ void Adafruit_GFX::fillCircleHelper(int16_t x0, int16_t y0, int16_t r, } } -// Bresenham's algorithm - thx wikpedia +// Bresenham's algorithm - thx wikipedia void Adafruit_GFX::drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color) { diff --git a/Sming/Libraries/Adafruit_GFX/glcdfont.c b/Sming/Libraries/Adafruit_GFX/glcdfont.c index ce012943e0..d0a160fd19 100644 --- a/Sming/Libraries/Adafruit_GFX/glcdfont.c +++ b/Sming/Libraries/Adafruit_GFX/glcdfont.c @@ -1,14 +1,7 @@ #ifndef FONT5X7_H #define FONT5X7_H -#if defined(__AVR__) - #include - #include -#elif defined(__ESP8266_EX__) - #include -#elif !defined(PROGMEM) - #define PROGMEM -#endif +#include // Standard ASCII 5x7 font diff --git a/Sming/Libraries/Adafruit_NeoPixel/Adafruit_NeoPixel.cpp b/Sming/Libraries/Adafruit_NeoPixel/Adafruit_NeoPixel.cpp index 423faea698..751bff1425 100644 --- a/Sming/Libraries/Adafruit_NeoPixel/Adafruit_NeoPixel.cpp +++ b/Sming/Libraries/Adafruit_NeoPixel/Adafruit_NeoPixel.cpp @@ -86,7 +86,7 @@ void IRAM_ATTR Adafruit_NeoPixel::show(void) { // allows the mainline code to start generating the next frame of data // rather than stalling for the latch. while(!canShow()); - // endTime is a private member (rather than global var) so that mutliple + // endTime is a private member (rather than global var) so that multiple // instances on different pins can be quickly issued in succession (each // instance doesn't delay the next). diff --git a/Sming/Libraries/Adafruit_NeoPixel/component.mk b/Sming/Libraries/Adafruit_NeoPixel/component.mk new file mode 100644 index 0000000000..e243360e9c --- /dev/null +++ b/Sming/Libraries/Adafruit_NeoPixel/component.mk @@ -0,0 +1 @@ +COMPONENT_SOC := esp8266 diff --git a/Sming/Libraries/Adafruit_PCD8544/Adafruit_PCD8544.cpp b/Sming/Libraries/Adafruit_PCD8544/Adafruit_PCD8544.cpp index 8812012db5..6f6710bbd9 100644 --- a/Sming/Libraries/Adafruit_PCD8544/Adafruit_PCD8544.cpp +++ b/Sming/Libraries/Adafruit_PCD8544/Adafruit_PCD8544.cpp @@ -324,7 +324,7 @@ void Adafruit_PCD8544::clearDisplay(void) { } /* -// this doesnt touch the buffer, just clears the display RAM - might be handy +// this doesn't touch the buffer, just clears the display RAM - might be handy void Adafruit_PCD8544::clearDisplay(void) { uint8_t p, c; diff --git a/Sming/Libraries/Adafruit_PCD8544/examples/pcdtest/pcdtest.ino b/Sming/Libraries/Adafruit_PCD8544/examples/pcdtest/pcdtest.ino index 368ba6bbf1..f47ad60ead 100644 --- a/Sming/Libraries/Adafruit_PCD8544/examples/pcdtest/pcdtest.ino +++ b/Sming/Libraries/Adafruit_PCD8544/examples/pcdtest/pcdtest.ino @@ -103,7 +103,7 @@ void setup() { delay(2000); display.clearDisplay(); - // draw mulitple circles + // draw multiple circles testdrawcircle(); display.display(); delay(2000); diff --git a/Sming/Libraries/Adafruit_Sensor b/Sming/Libraries/Adafruit_Sensor index e985f2253a..6cea0d9c55 160000 --- a/Sming/Libraries/Adafruit_Sensor +++ b/Sming/Libraries/Adafruit_Sensor @@ -1 +1 @@ -Subproject commit e985f2253a687ef377cde3dcfb1f788830d1bc09 +Subproject commit 6cea0d9c554930e3914d6629235ff0a044f452ab diff --git a/Sming/Libraries/Adafruit_VL53L0X b/Sming/Libraries/Adafruit_VL53L0X index cc4ca55e93..701b26431c 160000 --- a/Sming/Libraries/Adafruit_VL53L0X +++ b/Sming/Libraries/Adafruit_VL53L0X @@ -1 +1 @@ -Subproject commit cc4ca55e938891a2903a9fedd5e10c811da20579 +Subproject commit 701b26431ca7aac1cd3239ad3e86bd3d320e87c3 diff --git a/Sming/Libraries/ArduCAM/ArduCAM.cpp b/Sming/Libraries/ArduCAM/ArduCAM.cpp index d0fc4b8106..d3272c07c8 100644 --- a/Sming/Libraries/ArduCAM/ArduCAM.cpp +++ b/Sming/Libraries/ArduCAM/ArduCAM.cpp @@ -72,7 +72,7 @@ Add live preview before JPEG capture. Add play back photos one by one after BMP capture. 2014/05/01 V3.1.1 by Lee Minor changes to add support Arduino IDE for linux distributions. - 2014/09/30 V3.2.0 by Lee Improvement on OV5642 camera dirver. + 2014/09/30 V3.2.0 by Lee Improvement on OV5642 camera driver. 2014/10/06 V3.3.0 by Lee Add OV7660,OV7725 camera support. 2015/02/27 V3.4.0 by Lee Add the support for Arduino Yun board, update the latest UTFT library for ArduCAM. 2015/06/09 V3.4.1 by Lee Minor changes and add some comments diff --git a/Sming/Libraries/ArduCAM/ArduCAM.h b/Sming/Libraries/ArduCAM/ArduCAM.h index 2d078060ef..16cd1e2fa2 100644 --- a/Sming/Libraries/ArduCAM/ArduCAM.h +++ b/Sming/Libraries/ArduCAM/ArduCAM.h @@ -72,7 +72,7 @@ Add live preview before JPEG capture. Add play back photos one by one after BMP capture. 2014/05/01 V3.1.1 by Lee Minor changes to add support Arduino IDE for linux distributions. - 2014/09/30 V3.2.0 by Lee Improvement on OV5642 camera dirver. + 2014/09/30 V3.2.0 by Lee Improvement on OV5642 camera driver. 2014/10/06 V3.3.0 by Lee Add OV7660,OV7725 camera support. 2015/02/27 V3.4.0 by Lee Add the support for Arduino Yun board, update the latest UTFT library for ArduCAM. 2015/06/09 V3.4.1 by Lee Minor changes and add some comments @@ -179,7 +179,7 @@ #define CAM2LCD_MODE 0x01 #define LCD2MCU_MODE 0x02 -#define ARDUCHIP_TIM 0x03 //Timming control +#define ARDUCHIP_TIM 0x03 //Timing control #define HREF_LEVEL_MASK 0x01 //0 = High active , 1 = Low active #define VSYNC_LEVEL_MASK 0x02 //0 = High active , 1 = Low active #define LCD_BKEN_MASK 0x04 //0 = Enable, 1 = Disable diff --git a/Sming/Libraries/ArduCAM/ArduCAMStream.cpp b/Sming/Libraries/ArduCAM/ArduCAMStream.cpp index 11a491cc14..9552ee3c1b 100644 --- a/Sming/Libraries/ArduCAM/ArduCAMStream.cpp +++ b/Sming/Libraries/ArduCAM/ArduCAMStream.cpp @@ -126,7 +126,7 @@ uint16_t ArduCAMStream::readMemoryBlock(char* data, int bufSize) { bool ArduCAMStream::seek(int dist) { // ACAM_DEBUG("ArduCAMStream::seek (%d)\n", dist); - // we do not allow negativ seeks + // we do not allow negative seeks if (dist < 0) return false; // end we ignore forward seeks diff --git a/Sming/Libraries/ArduCAM/README.md b/Sming/Libraries/ArduCAM/README.md index 5c9d019240..e255ef74ac 100644 --- a/Sming/Libraries/ArduCAM/README.md +++ b/Sming/Libraries/ArduCAM/README.md @@ -2,7 +2,7 @@ ## Introduction -This is a opensource library for taking high resolution still images and short video clip on Arduino based platforms using ArduCAM's camera moduels.
+This is a opensource library for taking high resolution still images and short video clip on Arduino based platforms using ArduCAM's camera modules.
The camera breakout boards should work with ArduCAM shield before connecting to the Arduino boards.
ArduCAM mini series camera modules like Mini-2MP, Mini-5MP(Plus) can be connected to Arduino boards directly.
In addition to Arduino, the library can be ported to any hardware platforms as long as they have I2C and SPI interface based on this ArduCAM library.
@@ -55,7 +55,7 @@ and the line `#define OV5642_CAM` then comment other lines.
### 2. Choose correct CS pin for your camera Open one of the examples, wiring SPI and I2C interface especially CS pins to ArduCAM shield according to the examples. -Hardware and software shuld be consistent to run the examples correctly. +Hardware and software should be consistent to run the examples correctly. ### 3. Upload the examples In the example folder there are seven sub directories for different ArduCAM models and the host application. diff --git a/Sming/Libraries/ArduCAM/mt9d111_regs.h b/Sming/Libraries/ArduCAM/mt9d111_regs.h index c77505427d..9c89593245 100644 --- a/Sming/Libraries/ArduCAM/mt9d111_regs.h +++ b/Sming/Libraries/ArduCAM/mt9d111_regs.h @@ -186,7 +186,7 @@ const struct sensor_reg MT9D111_QVGA_30fps[] PROGMEM= //Set minimum integration time to get a maximum of 15 fps at 45MHz {0xC6, 0xA20D }, //AE_MAX_INDEX {0xC8, 0x0004 }, //AE_MAX_INDEX - // Configue all GPIO for output and set low to save power + // Configure all GPIO for output and set low to save power {0xC6, 0x9078 }, {0xC8, 0x0000 }, {0xC6, 0x9079 }, diff --git a/Sming/Libraries/ArduinoFFT b/Sming/Libraries/ArduinoFFT index bb99065f9a..dec237ab14 160000 --- a/Sming/Libraries/ArduinoFFT +++ b/Sming/Libraries/ArduinoFFT @@ -1 +1 @@ -Subproject commit bb99065f9aad9e5781c5bf9e77613bdd33f0074d +Subproject commit dec237ab147d17af2043cdbf4326c30616c7fbec diff --git a/Sming/Libraries/ArduinoJson6/include/ArduinoJson.h b/Sming/Libraries/ArduinoJson6/include/ArduinoJson.h index 567a80a914..db5e270b6b 100644 --- a/Sming/Libraries/ArduinoJson6/include/ArduinoJson.h +++ b/Sming/Libraries/ArduinoJson6/include/ArduinoJson.h @@ -340,7 +340,7 @@ deserialize(JsonDocument& doc, TInput* input, SerializationFormat format = JSON_ * @param input Where to get data from (see notes) * @param format Format of the data * @retval bool true on success, false on error - * @note Supports stream pointers (Stream and inherited classses) + * @note Supports stream pointers (Stream and inherited classes) * This function can be safely used with null pointers */ template diff --git a/Sming/Libraries/Arduino_TensorFlowLite b/Sming/Libraries/Arduino_TensorFlowLite index 9f00dd38f4..a938e15289 160000 --- a/Sming/Libraries/Arduino_TensorFlowLite +++ b/Sming/Libraries/Arduino_TensorFlowLite @@ -1 +1 @@ -Subproject commit 9f00dd38f4329b8e884c417aa1bcfbfb15f47913 +Subproject commit a938e15289a2b0087eef0643dd62993aeb92f6d6 diff --git a/Sming/Libraries/BH1750FVI/BH1750FVI.h b/Sming/Libraries/BH1750FVI/BH1750FVI.h index d483e56a3f..6c8c606044 100644 --- a/Sming/Libraries/BH1750FVI/BH1750FVI.h +++ b/Sming/Libraries/BH1750FVI/BH1750FVI.h @@ -2,7 +2,7 @@ /* This library for Digital Light sensor BH1750FVI - use I2C Communication protocal , SDA,SCL Are required + use I2C Communication protocol , SDA,SCL Are required to interface with this sensor diff --git a/Sming/Libraries/BH1750FVI/BH1750_Led/BH1750_Led.ino b/Sming/Libraries/BH1750FVI/BH1750_Led/BH1750_Led.ino index 49015e3137..21bebc3850 100644 --- a/Sming/Libraries/BH1750FVI/BH1750_Led/BH1750_Led.ino +++ b/Sming/Libraries/BH1750FVI/BH1750_Led/BH1750_Led.ino @@ -51,7 +51,7 @@ void setup() { OneTime_H_resolution_Mode2 OneTime_L_resolution_Mode - The data sheet recommanded To use Continuous_H_resolution_Mode + The data sheet recommended To use Continuous_H_resolution_Mode */ LightSensor.SetMode(Continuous_H_resolution_Mode); pinMode(9,OUTPUT) // Connect LED With 100ohm resistor diff --git a/Sming/Libraries/BH1750FVI/BH1750_serial/BH1750_serial.ino b/Sming/Libraries/BH1750FVI/BH1750_serial/BH1750_serial.ino index d475315167..b6254d8272 100644 --- a/Sming/Libraries/BH1750FVI/BH1750_serial/BH1750_serial.ino +++ b/Sming/Libraries/BH1750FVI/BH1750_serial/BH1750_serial.ino @@ -49,7 +49,7 @@ void setup() { // put your setup code here, to run once: OneTime_H_resolution_Mode2 OneTime_L_resolution_Mode - The data sheet recommanded To use Continuous_H_resolution_Mode + The data sheet recommended To use Continuous_H_resolution_Mode */ LightSensor.SetMode(Continuous_H_resolution_Mode); diff --git a/Sming/Libraries/BME280/BME280_Example/BME280_Example.ino b/Sming/Libraries/BME280/BME280_Example/BME280_Example.ino index 8b84c5f440..5fc36f9a8b 100644 --- a/Sming/Libraries/BME280/BME280_Example/BME280_Example.ino +++ b/Sming/Libraries/BME280/BME280_Example/BME280_Example.ino @@ -44,7 +44,7 @@ void loop() { if(barometer.IsConnected) { - // Retrive the current pressure in Pascals. + // Retrieve the current pressure in Pascals. long currentPressure = barometer.GetPressure(); // Print out the Pressure. @@ -52,7 +52,7 @@ void loop() Serial.print(currentPressure); Serial.print(" Pa"); - // Retrive the current altitude (in meters). Current Sea Level Pressure is required for this. + // Retrieve the current altitude (in meters). Current Sea Level Pressure is required for this. float altitude = barometer.GetAltitude(seaLevelPressure); // Print out the Altitude. @@ -60,7 +60,7 @@ void loop() Serial.print(altitude); Serial.print(" m"); - // Retrive the current temperature in degrees celcius. + // Retrieve the current temperature in degrees celsius. float currentTemperature = barometer.GetTemperature(); // Print out the Temperature diff --git a/Sming/Libraries/BMP180/BMP180.cpp b/Sming/Libraries/BMP180/BMP180.cpp index 003bbd9df3..b26f0994fe 100644 --- a/Sming/Libraries/BMP180/BMP180.cpp +++ b/Sming/Libraries/BMP180/BMP180.cpp @@ -126,7 +126,7 @@ float BMP180::CompensateTemperature(int uncompensatedTemperature) float fTemperature = temperature; fTemperature /= 10.0; - // Record this data because it is required by the pressure algorithem. + // Record this data because it is required by the pressure algorithm. LastTemperatureData = param_b5; LastTemperatureTime = millis(); diff --git a/Sming/Libraries/BMP180/BMP180_Example/BMP180_Example.ino b/Sming/Libraries/BMP180/BMP180_Example/BMP180_Example.ino index 8b84c5f440..5fc36f9a8b 100644 --- a/Sming/Libraries/BMP180/BMP180_Example/BMP180_Example.ino +++ b/Sming/Libraries/BMP180/BMP180_Example/BMP180_Example.ino @@ -44,7 +44,7 @@ void loop() { if(barometer.IsConnected) { - // Retrive the current pressure in Pascals. + // Retrieve the current pressure in Pascals. long currentPressure = barometer.GetPressure(); // Print out the Pressure. @@ -52,7 +52,7 @@ void loop() Serial.print(currentPressure); Serial.print(" Pa"); - // Retrive the current altitude (in meters). Current Sea Level Pressure is required for this. + // Retrieve the current altitude (in meters). Current Sea Level Pressure is required for this. float altitude = barometer.GetAltitude(seaLevelPressure); // Print out the Altitude. @@ -60,7 +60,7 @@ void loop() Serial.print(altitude); Serial.print(" m"); - // Retrive the current temperature in degrees celcius. + // Retrieve the current temperature in degrees celsius. float currentTemperature = barometer.GetTemperature(); // Print out the Temperature diff --git a/Sming/Libraries/Bounce/examples/change/change.pde b/Sming/Libraries/Bounce/examples/change/change.pde index 63074e0e74..e768214adc 100644 --- a/Sming/Libraries/Bounce/examples/change/change.pde +++ b/Sming/Libraries/Bounce/examples/change/change.pde @@ -4,7 +4,7 @@ int ledValue = LOW; -// This example changes the state of the LED everytime the button is pushed +// This example changes the state of the LED every time the button is pushed // Build the circuit indicated here: http://arduino.cc/en/Tutorial/Button diff --git a/Sming/Libraries/Bounce/examples/edge/edge.pde b/Sming/Libraries/Bounce/examples/edge/edge.pde index b38f29b3a1..1112247c31 100644 --- a/Sming/Libraries/Bounce/examples/edge/edge.pde +++ b/Sming/Libraries/Bounce/examples/edge/edge.pde @@ -3,11 +3,11 @@ // This code turns a LED on and incraments number displayed on the 7-segment display // whenever either PB1 or PB2 is pressed. PB1 used the debounce library and PB2 does -// not. PB1 will cleanly increment the displayed value. PB2 will not alway increment +// not. PB1 will cleanly increment the displayed value. PB2 will not always increment // the display because the switch is not debounced. // // The bounce library also detects the rising or falling edge of the input. -// This is often called a one-shot and is usefull if you want something to only +// This is often called a one-shot and is useful if you want something to only // happen once when a button is pressed or released. The risingEdge method is true // for only one scan when the input goes from off-to-on. The fallingEdge method is // true for only one scan when the input goes from on-to-off. Even if you are not diff --git a/Sming/Libraries/CS5460/CS5460.patch b/Sming/Libraries/CS5460/CS5460.patch index a8c2adc3a0..f78e7631cf 100644 --- a/Sming/Libraries/CS5460/CS5460.patch +++ b/Sming/Libraries/CS5460/CS5460.patch @@ -1,5 +1,18 @@ +diff --git a/CS5460.cpp b/CS5460.cpp +index ad1c446..09efc48 100644 +--- a/CS5460.cpp ++++ b/CS5460.cpp +@@ -45,7 +45,7 @@ CS5460::CS5460(uint8_t _cs, uint8_t _reset, uint8_t _edir, uint8_t _eout):curren + */ + void CS5460::init() const + { +- pinMode(MISO, INPUT_PULLUP); ++ //pinMode(SPI_MISO, INPUT_PULLUP); + select(); + SPI.begin(); + SPI.beginTransaction(SETTING); diff --git a/CS5460.h b/CS5460.h -index 0fbbb5b..fe7ff1d 100644 +index 0fbbb5b..08d0d28 100644 --- a/CS5460.h +++ b/CS5460.h @@ -1,7 +1,7 @@ diff --git a/Sming/Libraries/CS5460/README.rst b/Sming/Libraries/CS5460/README.rst index 4e5c1e6742..d671f66536 100644 --- a/Sming/Libraries/CS5460/README.rst +++ b/Sming/Libraries/CS5460/README.rst @@ -1,4 +1,19 @@ CS5460 energy meter IC ====================== -The CS5460(A) is a highly integrated power measurement solution which combines two Analog-to-digital Converters (ADCs), high-speed power calculation functions, and a serial interface on a single chip. It is designed to accurately measure and calculate: Real (True) Energy, Instantaneous Power, I RMS , and V RMS for single phase 2- or 3-wire power metering applications. \ No newline at end of file +Product information: https://www.cirrus.com/products/cs5460a/ + +The CS5460(A) is a highly integrated power measurement solution which combines: + +- Two Analog-to-digital Converters (ADCs) +- High-speed power calculation functions +- A serial interface + +on a single chip. It is designed to accurately measure and calculate + +- Real (True) Energy +- Instantaneous Power +- I RMS +- V RMS + +for single phase 2- or 3-wire power metering applications. diff --git a/Sming/Libraries/CS5460/component.mk b/Sming/Libraries/CS5460/component.mk index e01261a7e6..cdfad478ee 100644 --- a/Sming/Libraries/CS5460/component.mk +++ b/Sming/Libraries/CS5460/component.mk @@ -1,7 +1,3 @@ COMPONENT_SUBMODULES := CS5460 COMPONENT_SRCDIRS := CS5460 COMPONENT_INCDIRS := CS5460 - -COMPONENT_VARS += MISO -MISO ?= 12 -COMPONENT_CXXFLAGS += -DMISO=$(MISO) diff --git a/Sming/Libraries/CS5460/samples/generic/README.rst b/Sming/Libraries/CS5460/samples/generic/README.rst index 9c19108ed1..aa47815b72 100644 --- a/Sming/Libraries/CS5460/samples/generic/README.rst +++ b/Sming/Libraries/CS5460/samples/generic/README.rst @@ -1,14 +1,4 @@ CS5460 generic sample ===================== -.. highlight:: bash - The sample prints the measured RMS voltage each second (with CS5460 voltage and current filters enabled). - -The default MISO pin (12) can be changed through the envvar:`MISO` variable. For example:: - - make MISO=13 - -These variables can be listed with:: - - make list-config diff --git a/Sming/Libraries/CapacitiveSensor/CapacitiveSensor.cpp b/Sming/Libraries/CapacitiveSensor/CapacitiveSensor.cpp index 6a3b27155d..889c8798de 100644 --- a/Sming/Libraries/CapacitiveSensor/CapacitiveSensor.cpp +++ b/Sming/Libraries/CapacitiveSensor/CapacitiveSensor.cpp @@ -22,7 +22,7 @@ // Constructor ///////////////////////////////////////////////////////////////// // Function that handles the creation and setup of instances -CapacitiveSensor::CapacitiveSensor(uint8_t sendPin, uint8_t receivePin) +CapacitiveSensor::CapacitiveSensor(uint8_t sendPin, uint8_t receivePin): total(0) { // initialize this instance's variables // Serial.begin(9600); // for debugging diff --git a/Sming/Libraries/CapacitiveSensor/component.mk b/Sming/Libraries/CapacitiveSensor/component.mk new file mode 100644 index 0000000000..e243360e9c --- /dev/null +++ b/Sming/Libraries/CapacitiveSensor/component.mk @@ -0,0 +1 @@ +COMPONENT_SOC := esp8266 diff --git a/Sming/Libraries/DS18S20/ds18s20.h b/Sming/Libraries/DS18S20/ds18s20.h index c2f108a6c3..40cc303afa 100644 --- a/Sming/Libraries/DS18S20/ds18s20.h +++ b/Sming/Libraries/DS18S20/ds18s20.h @@ -67,14 +67,14 @@ class DS18S20 */ void UnRegisterCallback(); //Unset conversion end function - /** @brief Get the value of the last measurment from a sensor + /** @brief Get the value of the last measurement from a sensor * @param Index of sensor to retrieve value from * @return Temperature value in degrees Celsius or zero for invalid sensor index * @note Call IsValidTemperature() to check value is valid before calling this function */ float GetCelsius(uint8_t); - /** @brief Get the value of the last measurment from a sensor + /** @brief Get the value of the last measurement from a sensor * @param Index of sensor to retrieve value from * @return Temperature value in degrees Fahrenheit or zero for invalid sensor index * @note Call IsValidTemperature() to check value is valid before calling this function diff --git a/Sming/Libraries/DS3232RTC/DS3232RTC.cpp b/Sming/Libraries/DS3232RTC/DS3232RTC.cpp index c099db89c3..1454c5068d 100644 --- a/Sming/Libraries/DS3232RTC/DS3232RTC.cpp +++ b/Sming/Libraries/DS3232RTC/DS3232RTC.cpp @@ -66,7 +66,7 @@ /*============================================================================*/ /* functions to convert to and from system time */ -/* These are for interfacing with time serivces and are not normally needed in a sketch */ +/* These are for interfacing with time services and are not normally needed in a sketch */ // leap year calulator expects year argument as years offset from 1970 #define LEAP_YEAR(Y) ( ((1970+Y)>0) && !((1970+Y)%4) && ( ((1970+Y)%100) || !((1970+Y)%400) ) ) diff --git a/Sming/Libraries/GoogleCast b/Sming/Libraries/GoogleCast index 3e6f1bea43..83ad9974fd 160000 --- a/Sming/Libraries/GoogleCast +++ b/Sming/Libraries/GoogleCast @@ -1 +1 @@ -Subproject commit 3e6f1bea43b56dee27a13a7ab97ff8f3a680303c +Subproject commit 83ad9974fd80b048aec88bcc84a939f4cb0500bf diff --git a/Sming/Libraries/Graphics b/Sming/Libraries/Graphics index f272a5eade..98da456e43 160000 --- a/Sming/Libraries/Graphics +++ b/Sming/Libraries/Graphics @@ -1 +1 @@ -Subproject commit f272a5eade55561dea6b959146fb630a57e58927 +Subproject commit 98da456e4338153d779bca64b6ac7d56ee9b80c4 diff --git a/Sming/Libraries/HMC5883L/HMC5883L.cpp b/Sming/Libraries/HMC5883L/HMC5883L.cpp index 29d8fb56e5..a40aa7b32f 100644 --- a/Sming/Libraries/HMC5883L/HMC5883L.cpp +++ b/Sming/Libraries/HMC5883L/HMC5883L.cpp @@ -56,7 +56,7 @@ HMC5883L::HMC5883L(uint8_t address) { * averaging, 15 Hz data output rate, normal measurement bias, a,d 1090 gain (in * terms of LSB/Gauss). Be sure to adjust any settings you need specifically * after initialization, especially the gain settings if you happen to be seeing - * a lot of -4096 values (see the datasheet for mor information). + * a lot of -4096 values (see the datasheet for more information). */ void HMC5883L::initialize() { // write CONFIG_A register @@ -280,7 +280,7 @@ void HMC5883L::getHeading(int16_t *x, int16_t *y, int16_t *z) { */ int16_t HMC5883L::getHeadingX() { // each axis read requires that ALL axis registers be read, even if only - // one is used; this was not done ineffiently in the code by accident + // one is used; this was not done inefficiently in the code by accident I2Cdev::readBytes(devAddr, HMC5883L_RA_DATAX_H, 6, buffer); if (mode == HMC5883L_MODE_SINGLE) I2Cdev::writeByte(devAddr, HMC5883L_RA_MODE, HMC5883L_MODE_SINGLE << (HMC5883L_MODEREG_BIT - HMC5883L_MODEREG_LENGTH + 1)); return (((int16_t)buffer[0]) << 8) | buffer[1]; @@ -291,7 +291,7 @@ int16_t HMC5883L::getHeadingX() { */ int16_t HMC5883L::getHeadingY() { // each axis read requires that ALL axis registers be read, even if only - // one is used; this was not done ineffiently in the code by accident + // one is used; this was not done inefficiently in the code by accident I2Cdev::readBytes(devAddr, HMC5883L_RA_DATAX_H, 6, buffer); if (mode == HMC5883L_MODE_SINGLE) I2Cdev::writeByte(devAddr, HMC5883L_RA_MODE, HMC5883L_MODE_SINGLE << (HMC5883L_MODEREG_BIT - HMC5883L_MODEREG_LENGTH + 1)); return (((int16_t)buffer[4]) << 8) | buffer[5]; @@ -302,7 +302,7 @@ int16_t HMC5883L::getHeadingY() { */ int16_t HMC5883L::getHeadingZ() { // each axis read requires that ALL axis registers be read, even if only - // one is used; this was not done ineffiently in the code by accident + // one is used; this was not done inefficiently in the code by accident I2Cdev::readBytes(devAddr, HMC5883L_RA_DATAX_H, 6, buffer); if (mode == HMC5883L_MODE_SINGLE) I2Cdev::writeByte(devAddr, HMC5883L_RA_MODE, HMC5883L_MODE_SINGLE << (HMC5883L_MODEREG_BIT - HMC5883L_MODEREG_LENGTH + 1)); return (((int16_t)buffer[2]) << 8) | buffer[3]; diff --git a/Sming/Libraries/HardwareSPI b/Sming/Libraries/HardwareSPI index d464c20324..ae5efe4d99 160000 --- a/Sming/Libraries/HardwareSPI +++ b/Sming/Libraries/HardwareSPI @@ -1 +1 @@ -Subproject commit d464c203240144db1acfb1fb3343accdd28cb6cd +Subproject commit ae5efe4d990340654baa399dba0c9e54203ec5eb diff --git a/Sming/Libraries/HueEmulator b/Sming/Libraries/HueEmulator index 72c333af81..9c275794b9 160000 --- a/Sming/Libraries/HueEmulator +++ b/Sming/Libraries/HueEmulator @@ -1 +1 @@ -Subproject commit 72c333af8161ce0343c440e5a0e6dbf8d1569171 +Subproject commit 9c275794b958e68ea67ebfd974f9189dfd36b695 diff --git a/Sming/Libraries/I2Cdev/I2Cdev.cpp b/Sming/Libraries/I2Cdev/I2Cdev.cpp index 25d9db0ca6..9341671d9d 100644 --- a/Sming/Libraries/I2Cdev/I2Cdev.cpp +++ b/Sming/Libraries/I2Cdev/I2Cdev.cpp @@ -45,6 +45,8 @@ THE SOFTWARE. #include "I2Cdev.h" +constexpr uint8_t BUFFER_LENGTH = TwoWire::BUFFER_LENGTH; + #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE #ifdef I2CDEV_IMPLEMENTATION_WARNINGS @@ -230,7 +232,7 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 Wire.send(regAddr); Wire.endTransmission(); Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)min(length - k, BUFFER_LENGTH)); + Wire.requestFrom(devAddr, min(uint8_t(length - k), BUFFER_LENGTH)); for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { data[count] = Wire.receive(); @@ -254,7 +256,7 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 Wire.write(regAddr); Wire.endTransmission(); Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)min(length - k, BUFFER_LENGTH)); + Wire.requestFrom(devAddr, min(uint8_t(length - k), BUFFER_LENGTH)); for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { data[count] = Wire.read(); @@ -273,12 +275,12 @@ int8_t I2Cdev::readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8 // I2C/TWI subsystem uses internal buffer that breaks with large data requests // so if user requests more than BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length; k += min((unsigned int)length, (unsigned int)BUFFER_LENGTH)) { + for (uint8_t k = 0; k < length; k += min(length, BUFFER_LENGTH)) { Wire.beginTransmission(devAddr); Wire.write(regAddr); Wire.endTransmission(); Wire.beginTransmission(devAddr); - Wire.requestFrom(devAddr, (uint8_t)min(length - k, BUFFER_LENGTH)); + Wire.requestFrom(devAddr, min(uint8_t(length - k), BUFFER_LENGTH)); for (; Wire.available() && (timeout == 0 || millis() - t1 < timeout); count++) { data[count] = Wire.read(); @@ -345,7 +347,7 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 // I2C/TWI subsystem uses internal buffer that breaks with large data requests // so if user requests more than BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length * 2; k += min(length * 2, BUFFER_LENGTH)) { + for (uint8_t k = 0; k < length * 2; k += min(uint8_t(length * 2), BUFFER_LENGTH)) { Wire.beginTransmission(devAddr); Wire.send(regAddr); Wire.endTransmission(); @@ -378,7 +380,7 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 // I2C/TWI subsystem uses internal buffer that breaks with large data requests // so if user requests more than BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length * 2; k += min(length * 2, BUFFER_LENGTH)) { + for (uint8_t k = 0; k < length * 2; k += min(uint8_t(length * 2), BUFFER_LENGTH)) { Wire.beginTransmission(devAddr); Wire.write(regAddr); Wire.endTransmission(); @@ -411,7 +413,7 @@ int8_t I2Cdev::readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint1 // I2C/TWI subsystem uses internal buffer that breaks with large data requests // so if user requests more than BUFFER_LENGTH bytes, we have to do it in // smaller chunks instead of all at once - for (uint8_t k = 0; k < length * 2; k += min(length * 2, BUFFER_LENGTH)) { + for (uint8_t k = 0; k < length * 2; k += min(uint8_t(length * 2), BUFFER_LENGTH)) { Wire.beginTransmission(devAddr); Wire.write(regAddr); Wire.endTransmission(); @@ -1138,7 +1140,7 @@ uint16_t I2Cdev::readTimeout = I2CDEV_DEFAULT_READ_TIMEOUT; // send stop condition TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO); - // wait for stop condition to be exectued on bus + // wait for stop condition to be executed on bus // TWINT is not set after a stop condition! while (TWCR & _BV(TWSTO)) { continue; diff --git a/Sming/Libraries/LiquidCrystal/LCD.cpp b/Sming/Libraries/LiquidCrystal/LCD.cpp index 373f5291c5..d4deb6d0f0 100644 --- a/Sming/Libraries/LiquidCrystal/LCD.cpp +++ b/Sming/Libraries/LiquidCrystal/LCD.cpp @@ -29,7 +29,7 @@ // // @version API 1.1.0 // -// 2012.03.29 bperrybap - changed comparision to use LCD_5x8DOTS rather than 0 +// 2012.03.29 bperrybap - changed comparison to use LCD_5x8DOTS rather than 0 // @author F. Malpartida - fmalpartida@gmail.com // --------------------------------------------------------------------------- #include diff --git a/Sming/Libraries/LiquidCrystal/LCD.h b/Sming/Libraries/LiquidCrystal/LCD.h index 88a58ad1b1..5c51b72446 100644 --- a/Sming/Libraries/LiquidCrystal/LCD.h +++ b/Sming/Libraries/LiquidCrystal/LCD.h @@ -64,7 +64,7 @@ @abstract waits for a given time in microseconds (compilation dependent). @discussion Waits for a given time defined in microseconds depending on the FAST_MODE define. If the FAST_MODE is defined the call will return - inmediatelly. + immediately. @param uSec[in] time in microseconds. @result None */ @@ -145,7 +145,7 @@ inline static void waitUsec ( uint16_t uSec ) /*! @defined @abstract Backlight off constant declaration - @discussion Used in combination with the setBacklight to swith off the + @discussion Used in combination with the setBacklight to switch off the LCD backlight. @set setBacklight */ #define BACKLIGHT_OFF 0 @@ -153,7 +153,7 @@ inline static void waitUsec ( uint16_t uSec ) /*! @defined @abstract Backlight on constant declaration - @discussion Used in combination with the setBacklight to swith on the + @discussion Used in combination with the setBacklight to switch on the LCD backlight. @set setBacklight */ #define BACKLIGHT_ON 255 @@ -187,7 +187,7 @@ class LCD : public Print This method is abstract, a base implementation is available common to all LCD drivers. Should it not be compatible with some other LCD driver, a derived - implementation should be done on the driver specif class. + implementation should be done on the driver-specific class. @param cols[in] the number of columns that the display has @param rows[in] the number of rows that the display has @@ -453,7 +453,7 @@ class LCD : public Print or the adequate backlight control constructor. @see setBacklightPin. - NOTE: The prefered methods to control the backlight are "backlight" and + NOTE: The preferred methods to control the backlight are "backlight" and "noBacklight". @param 0..255 - the value is very dependent on the LCD. However, diff --git a/Sming/Libraries/LiquidCrystal/LiquidCrystal.cpp b/Sming/Libraries/LiquidCrystal/LiquidCrystal.cpp index d6f018ab00..ec1315728e 100644 --- a/Sming/Libraries/LiquidCrystal/LiquidCrystal.cpp +++ b/Sming/Libraries/LiquidCrystal/LiquidCrystal.cpp @@ -78,7 +78,7 @@ LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t enable, init(LCD_4BIT, rs, 255, enable, d0, d1, d2, d3, 0, 0, 0, 0); } -// Contructors with backlight control +// Constructors with backlight control LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t enable, uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7, @@ -154,7 +154,7 @@ void LiquidCrystal::send(uint8_t value, uint8_t mode) // setBacklightPin void LiquidCrystal::setBacklightPin ( uint8_t pin, t_backlighPol pol ) { - pinMode ( pin, OUTPUT ); // Difine the backlight pin as output + pinMode ( pin, OUTPUT ); // Define the backlight pin as output _backlightPin = pin; _polarity = pol; setBacklight(BACKLIGHT_OFF); // Set the backlight low by default diff --git a/Sming/Libraries/LiquidCrystal/LiquidCrystal_SR.h b/Sming/Libraries/LiquidCrystal/LiquidCrystal_SR.h index e0f01ee887..211ffb0ac8 100644 --- a/Sming/Libraries/LiquidCrystal/LiquidCrystal_SR.h +++ b/Sming/Libraries/LiquidCrystal/LiquidCrystal_SR.h @@ -39,7 +39,7 @@ // 2 or 3 Pins required from the Arduino for Data, Clock and (optional) Enable // If not using Enable, the Data pin will be used for the enable signal. // 2 wire mode can be indicated by: -// - ommitting the enable pin in constructor +// - omitting the enable pin in constructor // - defining the same pin for Enable as for Data in constructor // - by using the token TWO_WIRE for the enable pin. // diff --git a/Sming/Libraries/LiquidCrystal/LiquidCrystal_SR2W.cpp b/Sming/Libraries/LiquidCrystal/LiquidCrystal_SR2W.cpp index df4559a335..8f4ae35808 100644 --- a/Sming/Libraries/LiquidCrystal/LiquidCrystal_SR2W.cpp +++ b/Sming/Libraries/LiquidCrystal/LiquidCrystal_SR2W.cpp @@ -102,7 +102,7 @@ void LiquidCrystal_SR2W::send(uint8_t value, uint8_t mode) /* * Don't call waitUsec() - * do our own delay optmization since this code is so fast it needs some added delay + * do our own delay optimization since this code is so fast it needs some added delay * even on slower AVRs. */ #if (F_CPU <= 16000000) diff --git a/Sming/Libraries/LiquidCrystal/README.md b/Sming/Libraries/LiquidCrystal/README.md index c2458bd800..5e060e2d90 100644 --- a/Sming/Libraries/LiquidCrystal/README.md +++ b/Sming/Libraries/LiquidCrystal/README.md @@ -8,7 +8,7 @@ Welcome to the *LCD Library* for **Arduino** and **Chipkit**. It is a derivate o its performance is almost 5 times faster and fully extendable if need be. It supports most ``Hitachi HD44780`` based LCDs, or compatible, connected to any project using: 4, 8 -wire parallel interface, I2C IO port expander (native I2C and bit bang) and Shift Regiter. +wire parallel interface, I2C IO port expander (native I2C and bit bang) and Shift Register. It currently supports 4 types of connections: diff --git a/Sming/Libraries/LiquidCrystal/docs/Doxyfile b/Sming/Libraries/LiquidCrystal/docs/Doxyfile index b097cd851c..1e26e8d31a 100644 --- a/Sming/Libraries/LiquidCrystal/docs/Doxyfile +++ b/Sming/Libraries/LiquidCrystal/docs/Doxyfile @@ -867,7 +867,7 @@ HTML_FILE_EXTENSION = .html # standard header. Note that when using a custom header you are responsible # for the proper inclusion of any scripts and style sheets that doxygen # needs, which is dependent on the configuration options used. -# It is adviced to generate a default header using "doxygen -w html +# It is advised to generate a default header using "doxygen -w html # header.html footer.html stylesheet.css YourConfigFile" and then modify # that header. Note that the header is subject to change so you typically # have to redo this when upgrading to a newer version of doxygen or when diff --git a/Sming/Libraries/LiquidCrystal/docs/def/doxygen.def b/Sming/Libraries/LiquidCrystal/docs/def/doxygen.def index 5af747c386..e0b160971e 100644 --- a/Sming/Libraries/LiquidCrystal/docs/def/doxygen.def +++ b/Sming/Libraries/LiquidCrystal/docs/def/doxygen.def @@ -474,7 +474,7 @@ _EnD_oF_dEf_TeXt_; This method is abstract, a base implementation is available common to all LCD drivers. Should it not be compatible with some other LCD driver, a derived - implementation should be done on the driver specif class. + implementation should be done on the driver-specific class. @param cols[in] the number of columns that the display has @param rows[in] the number of rows that the display has @@ -1004,7 +1004,7 @@ _EnD_oF_dEf_TeXt_; or the adequate backlight control constructor. @see setBacklightPin. - NOTE: The prefered methods to control the backlight are "backlight" and + NOTE: The preferred methods to control the backlight are "backlight" and "noBacklight". @param 0..255 - the value is very dependent on the LCD. However, @@ -6070,7 +6070,7 @@ _EnD_oF_dEf_TeXt_; define-mem-documentation = <<_EnD_oF_dEf_TeXt_ @defined @abstract Backlight off constant declaration - @discussion Used in combination with the setBacklight to swith off the + @discussion Used in combination with the setBacklight to switch off the LCD backlight. @set setBacklight _EnD_oF_dEf_TeXt_; }; /* define-member */ @@ -6091,7 +6091,7 @@ _EnD_oF_dEf_TeXt_; define-mem-documentation = <<_EnD_oF_dEf_TeXt_ @defined @abstract Backlight on constant declaration - @discussion Used in combination with the setBacklight to swith on the + @discussion Used in combination with the setBacklight to switch on the LCD backlight. @set setBacklight _EnD_oF_dEf_TeXt_; }; /* define-member */ @@ -6732,7 +6732,7 @@ _EnD_oF_dEf_TeXt_; @abstract waits for a given time in microseconds (compilation dependent). @discussion Waits for a given time defined in microseconds depending on the FAST_MODE define. If the FAST_MODE is defined the call will return - inmediatelly. + immediately. @param uSec[in] time in microseconds. @result None _EnD_oF_dEf_TeXt_; diff --git a/Sming/Libraries/LiquidCrystal/docs/html/_l_c_d_8cpp_source.html b/Sming/Libraries/LiquidCrystal/docs/html/_l_c_d_8cpp_source.html index 275807e857..82caac54d2 100644 --- a/Sming/Libraries/LiquidCrystal/docs/html/_l_c_d_8cpp_source.html +++ b/Sming/Libraries/LiquidCrystal/docs/html/_l_c_d_8cpp_source.html @@ -92,7 +92,7 @@ 00029 // 00030 // @version API 1.1.0 00031 // -00032 // 2012.03.29 bperrybap - changed comparision to use LCD_5x8DOTS rather than 0 +00032 // 2012.03.29 bperrybap - changed comparison to use LCD_5x8DOTS rather than 0 00033 // @author F. Malpartida - fmalpartida@gmail.com 00034 // --------------------------------------------------------------------------- 00035 #include <stdio.h> diff --git a/Sming/Libraries/LiquidCrystal/docs/html/_l_c_d_8h.html b/Sming/Libraries/LiquidCrystal/docs/html/_l_c_d_8h.html index 19ad58f680..ef0d5eb0a5 100644 --- a/Sming/Libraries/LiquidCrystal/docs/html/_l_c_d_8h.html +++ b/Sming/Libraries/LiquidCrystal/docs/html/_l_c_d_8h.html @@ -132,7 +132,7 @@
-

Backlight off constant declaration Used in combination with the setBacklight to swith off the LCD backlight. setBacklight

+

Backlight off constant declaration Used in combination with the setBacklight to switch off the LCD backlight. setBacklight

Definition at line 151 of file LCD.h.

@@ -148,7 +148,7 @@
-

Backlight on constant declaration Used in combination with the setBacklight to swith on the LCD backlight. setBacklight

+

Backlight on constant declaration Used in combination with the setBacklight to switch on the LCD backlight. setBacklight

Definition at line 159 of file LCD.h.

@@ -676,7 +676,7 @@

Enables disables fast waits for write operations for LCD If defined, the library will avoid doing un-necessary waits. this can be done, because the time taken by Arduino's slow digitalWrite operations. If fast digitalIO operations, comment this line out or undefine the mode.

-

waits for a given time in microseconds (compilation dependent). Waits for a given time defined in microseconds depending on the FAST_MODE define. If the FAST_MODE is defined the call will return inmediatelly.

+

waits for a given time in microseconds (compilation dependent). Waits for a given time defined in microseconds depending on the FAST_MODE define. If the FAST_MODE is defined the call will return immediately.

Parameters:
diff --git a/Sming/Libraries/LiquidCrystal/docs/html/_liquid_crystal_8cpp_source.html b/Sming/Libraries/LiquidCrystal/docs/html/_liquid_crystal_8cpp_source.html index 1760c1c74d..7a5b0b7225 100644 --- a/Sming/Libraries/LiquidCrystal/docs/html/_liquid_crystal_8cpp_source.html +++ b/Sming/Libraries/LiquidCrystal/docs/html/_liquid_crystal_8cpp_source.html @@ -141,7 +141,7 @@ 00078 init(LCD_4BIT, rs, 255, enable, d0, d1, d2, d3, 0, 0, 0, 0); 00079 } 00080 -00081 // Contructors with backlight control +00081 // Constructors with backlight control00082LiquidCrystal::LiquidCrystal(uint8_t rs, uint8_t enable, 00083 uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3, 00084 uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7, @@ -217,7 +217,7 @@ 00154 // setBacklightPin00155voidLiquidCrystal::setBacklightPin ( uint8_t pin, t_backlighPol pol ) 00156 { -00157 pinMode ( pin, OUTPUT ); // Difine the backlight pin as output +00157 pinMode ( pin, OUTPUT ); // Define the backlight pin as output00158 _backlightPin = pin; 00159 _polarity = pol; 00160 setBacklight(BACKLIGHT_OFF); // Set the backlight low by default diff --git a/Sming/Libraries/LiquidCrystal/docs/html/_liquid_crystal___s_r2_w_8cpp_source.html b/Sming/Libraries/LiquidCrystal/docs/html/_liquid_crystal___s_r2_w_8cpp_source.html index 3af3164932..2bd1f519dc 100644 --- a/Sming/Libraries/LiquidCrystal/docs/html/_liquid_crystal___s_r2_w_8cpp_source.html +++ b/Sming/Libraries/LiquidCrystal/docs/html/_liquid_crystal___s_r2_w_8cpp_source.html @@ -165,7 +165,7 @@ 00102 00103 /*00104 * Don't call waitUsec() -00105 * do our own delay optmization since this code is so fast it needs some added delay +00105 * do our own delay optimization since this code is so fast it needs some added delay00106 * even on slower AVRs.00107 */00108 #if (F_CPU <= 16000000) diff --git a/Sming/Libraries/LiquidCrystal/docs/html/_liquid_crystal___s_r_8h_source.html b/Sming/Libraries/LiquidCrystal/docs/html/_liquid_crystal___s_r_8h_source.html index 71640bf88f..a0ee8ae655 100644 --- a/Sming/Libraries/LiquidCrystal/docs/html/_liquid_crystal___s_r_8h_source.html +++ b/Sming/Libraries/LiquidCrystal/docs/html/_liquid_crystal___s_r_8h_source.html @@ -102,7 +102,7 @@ 00039 // 2 or 3 Pins required from the Arduino for Data, Clock and (optional) Enable00040 // If not using Enable, the Data pin will be used for the enable signal.00041 // 2 wire mode can be indicated by: -00042 // - ommitting the enable pin in constructor +00042 // - omitting the enable pin in constructor00043 // - defining the same pin for Enable as for Data in constructor00044 // - by using the token TWO_WIRE for the enable pin.00045 // diff --git a/Sming/Libraries/LiquidCrystal/docs/html/class_l_c_d.html b/Sming/Libraries/LiquidCrystal/docs/html/class_l_c_d.html index a63437a224..1e49e31d2e 100644 --- a/Sming/Libraries/LiquidCrystal/docs/html/class_l_c_d.html +++ b/Sming/Libraries/LiquidCrystal/docs/html/class_l_c_d.html @@ -225,7 +225,7 @@

LCD initialization. Initializes the LCD to a given size (col, row). This methods initializes the LCD, therefore, it MUST be called prior to using any other method from this class.

-

This method is abstract, a base implementation is available common to all LCD drivers. Should it not be compatible with some other LCD driver, a derived implementation should be done on the driver specif class.

+

This method is abstract, a base implementation is available common to all LCD drivers. Should it not be compatible with some other LCD driver, a derived implementation should be done on the driver-specific class.

Parameters:
uSec[in]time in microseconds.
@@ -748,7 +748,7 @@

Sets the pin to control the backlight. Sets the pin in the device to control the backlight. The behaviour of this method is very dependent on the device. Some controllers support dimming some don't. Please read the actual header file for each individual device. The setBacklightPin method has to be called before setting the backlight or the adequate backlight control constructor.

See also:
setBacklightPin.
-

NOTE: The prefered methods to control the backlight are "backlight" and "noBacklight".

+

NOTE: The preferred methods to control the backlight are "backlight" and "noBacklight".

Parameters:
cols[in]the number of columns that the display has
diff --git a/Sming/Libraries/LiquidCrystal/docs/html/search/search.js b/Sming/Libraries/LiquidCrystal/docs/html/search/search.js index 1b2829afba..4cd2e88c8d 100644 --- a/Sming/Libraries/LiquidCrystal/docs/html/search/search.js +++ b/Sming/Libraries/LiquidCrystal/docs/html/search/search.js @@ -1,7 +1,7 @@ // Search script generated by doxygen // Copyright (C) 2009 by Dimitri van Heesch. -// The code in this file is loosly based on main.js, part of Natural Docs, +// The code in this file is loosely based on main.js, part of Natural Docs, // which is Copyright (C) 2003-2008 Greg Valure // Natural Docs is licensed under the GPL. diff --git a/Sming/Libraries/LiquidCrystal/examples/HelloWorld_4bit/HelloWorld_4bit.pde b/Sming/Libraries/LiquidCrystal/examples/HelloWorld_4bit/HelloWorld_4bit.pde index 0c06514a77..a8179d1c59 100644 --- a/Sming/Libraries/LiquidCrystal/examples/HelloWorld_4bit/HelloWorld_4bit.pde +++ b/Sming/Libraries/LiquidCrystal/examples/HelloWorld_4bit/HelloWorld_4bit.pde @@ -8,7 +8,7 @@ LiquidCrystal lcd(12, 11, 5, 4, 3, 2, BACKLIGH_PIN, POSITIVE ); -// Creat a set of new characters +// Create a set of new characters byte smiley[8] = { 0b00000, 0b00000, diff --git a/Sming/Libraries/LiquidCrystal/examples/HelloWorld_SR/HelloWorld_SR.pde b/Sming/Libraries/LiquidCrystal/examples/HelloWorld_SR/HelloWorld_SR.pde index 00c8eeb0d1..6dd45ccbde 100644 --- a/Sming/Libraries/LiquidCrystal/examples/HelloWorld_SR/HelloWorld_SR.pde +++ b/Sming/Libraries/LiquidCrystal/examples/HelloWorld_SR/HelloWorld_SR.pde @@ -6,7 +6,7 @@ LiquidCrystal_SR lcd(8,7,TWO_WIRE); // | \-- Clock Pin // \---- Data/Enable Pin -// Creat a set of new characters +// Create a set of new characters byte armsUp[8] = {0b00100,0b01010,0b00100,0b10101,0b01110,0b00100,0b00100,0b01010}; byte armsDown[8] = {0b00100,0b01010,0b00100,0b00100,0b01110,0b10101,0b00100,0b01010}; diff --git a/Sming/Libraries/LiquidCrystal/examples/HelloWorld_i2c/HelloWorld_i2c.pde b/Sming/Libraries/LiquidCrystal/examples/HelloWorld_i2c/HelloWorld_i2c.pde index d0fd78cea9..fc44a94873 100644 --- a/Sming/Libraries/LiquidCrystal/examples/HelloWorld_i2c/HelloWorld_i2c.pde +++ b/Sming/Libraries/LiquidCrystal/examples/HelloWorld_i2c/HelloWorld_i2c.pde @@ -10,7 +10,7 @@ LiquidCrystal_I2C lcd(0x38); // Set the LCD I2C address //LiquidCrystal_I2C lcd(0x38, BACKLIGHT_PIN, POSITIVE); // Set the LCD I2C address -// Creat a set of new characters +// Create a set of new characters const uint8_t charBitmap[][8] = { { 0xc, 0x12, 0x12, 0xc, 0, 0, 0, 0 }, { 0x6, 0x9, 0x9, 0x6, 0, 0, 0, 0 }, diff --git a/Sming/Libraries/LiquidCrystal/examples/LCDiSpeed/LCDiSpeed.pde b/Sming/Libraries/LiquidCrystal/examples/LCDiSpeed/LCDiSpeed.pde index 4edcddca82..1fc90aeaa2 100644 --- a/Sming/Libraries/LiquidCrystal/examples/LCDiSpeed/LCDiSpeed.pde +++ b/Sming/Libraries/LiquidCrystal/examples/LCDiSpeed/LCDiSpeed.pde @@ -15,7 +15,7 @@ static char dummyvar; // dummy declaration for STUPID IDE!!!! * It runs a Frames/Sec (FPS) test which writes a "frame" of each digit 0-9 to * the display. * A "frame" is a full display of characters. - * It is created by positioning the cursor to the begining of each row + * It is created by positioning the cursor to the beginning of each row * and then writing a character to every position on the row, until the * entire display is filled. * The FPS test does a frame of 9's then 8's, .... down to 0's @@ -206,7 +206,7 @@ char c; unsigned long stime, etime; stime = micros(); - for(c = '9'; c >= '0'; c--) // do not change this unless you change the FPS/ByteXfer calcuations as well + for(c = '9'; c >= '0'; c--) // do not change this unless you change the FPS/ByteXfer calculations as well { for(uint8_t i = 0; i < iter; i++) { diff --git a/Sming/Libraries/LiquidCrystal/examples/LCDiSpeed/LCDiSpeed.txt b/Sming/Libraries/LiquidCrystal/examples/LCDiSpeed/LCDiSpeed.txt index b59d0133aa..d18c87f6c0 100644 --- a/Sming/Libraries/LiquidCrystal/examples/LCDiSpeed/LCDiSpeed.txt +++ b/Sming/Libraries/LiquidCrystal/examples/LCDiSpeed/LCDiSpeed.txt @@ -1,7 +1,7 @@ 16Mhz AVR Interface ByteXfer 16x2FPS Ftime ---------------------------------------------- -4BIT 338uS 86.92 11.51ms (orignal Liquid Crystal) +4BIT 338uS 86.92 11.51ms (original Liquid Crystal) 4BIT 98uS 298.58 3.35ms SR2W 76uS 388.62 2.57ms SR_2W 72uS 406.90 2.46ms @@ -12,7 +12,7 @@ SR3W 102uS 287.92 3.47ms 80Mhz Pic32 (ChipKit Uno32) Interface ByteXfer 16x2FPS Ftime ---------------------------------------------- -4BIT 232uS 126.73 7.89ms (orignal mpide Liquid Crystal) +4BIT 232uS 126.73 7.89ms (original mpide Liquid Crystal) 4BIT 57uS 517.41 1.93ms SR2W 53uS 557.35 1.79ms SR_2W 53uS 554.66 1.80ms diff --git a/Sming/Libraries/LiquidCrystal/examples/i2cLCDextraIO/i2cLCDextraIO.pde b/Sming/Libraries/LiquidCrystal/examples/i2cLCDextraIO/i2cLCDextraIO.pde index 5eaad1f0a5..bbeefe01fe 100644 --- a/Sming/Libraries/LiquidCrystal/examples/i2cLCDextraIO/i2cLCDextraIO.pde +++ b/Sming/Libraries/LiquidCrystal/examples/i2cLCDextraIO/i2cLCDextraIO.pde @@ -12,7 +12,7 @@ // @file i2CLCDextraIO.pde // Temperature logging to demonstrate the I2CLCDextraIO library. // -// @brief This application is a demostration file for the I2CLCDextraIO library +// @brief This application is a demonstration file for the I2CLCDextraIO library // that reads a temperature from the internal ATMEGA328p temperature sensor // and displays it on the LCD. The application also demonstrates some of the // methods of the library, such as loading custom characters to the LCD, @@ -106,7 +106,7 @@ const uint8_t charBitmap[][8] = { /*! @function @abstract Return available RAM memory - @discussion This routine returns the ammount of RAM memory available after + @discussion This routine returns the amount of RAM memory available after initialising the C runtime. @param @result Free RAM available. @@ -134,7 +134,7 @@ static int freeMemory() static int readTemperature() { - ADMUX = 0xC8; // activate interal temperature sensor, + ADMUX = 0xC8; // activate internal temperature sensor, // using 1.1V ref. voltage ADCSRA |= _BV(ADSC); // start the conversion while (bit_is_set(ADCSRA, ADSC)); // ADSC is cleared when the conversion diff --git a/Sming/Libraries/LiquidCrystal/examples/i2cLCDextraIO_tempLeonardo/i2cLCDextraIO_tempLeonardo.ino b/Sming/Libraries/LiquidCrystal/examples/i2cLCDextraIO_tempLeonardo/i2cLCDextraIO_tempLeonardo.ino index f981507372..784a329eaf 100644 --- a/Sming/Libraries/LiquidCrystal/examples/i2cLCDextraIO_tempLeonardo/i2cLCDextraIO_tempLeonardo.ino +++ b/Sming/Libraries/LiquidCrystal/examples/i2cLCDextraIO_tempLeonardo/i2cLCDextraIO_tempLeonardo.ino @@ -12,7 +12,7 @@ // @file i2CLCDextraIO_tempLeonardo.ino // Temperature logging to demonstrate the I2CLCDextraIO library. // -// @brief This application is a demostration file for the I2CLCDextraIO library +// @brief This application is a demonstration file for the I2CLCDextraIO library // that reads a temperature from the internal ATMEGA32U4 temperature sensor // and displays it on the LCD. The application also demonstrates some of the // methods of the library, such as loading custom characters to the LCD, @@ -161,7 +161,7 @@ const uint8_t charBitmap[][8] = { /*! @function @abstract Return available RAM memory - @discussion This routine returns the ammount of RAM memory available after + @discussion This routine returns the amount of RAM memory available after initialising the C runtime. @param @result Free RAM available. @@ -188,7 +188,7 @@ static int freeMemory() static int readTemperature() { - ADMUX = 0xC7; // activate interal temperature sensor, + ADMUX = 0xC7; // activate internal temperature sensor, // using 2.56V ref. voltage ADCSRB |= _BV(MUX5); diff --git a/Sming/Libraries/LiquidCrystal/examples/performanceLCD/performanceLCD.pde b/Sming/Libraries/LiquidCrystal/examples/performanceLCD/performanceLCD.pde index dea6c5064a..a9ccc70713 100644 --- a/Sming/Libraries/LiquidCrystal/examples/performanceLCD/performanceLCD.pde +++ b/Sming/Libraries/LiquidCrystal/examples/performanceLCD/performanceLCD.pde @@ -84,7 +84,7 @@ extern void *__brkval; /*! @defined LCD_COLUMNS @abstract LCD available columns - @discussion Defines the number of colums that the LCD has, normal LCD ranges are (8, 16, 20). + @discussion Defines the number of columns that the LCD has, normal LCD ranges are (8, 16, 20). */ #define LCD_COLUMNS 16 @@ -199,7 +199,7 @@ static t_benchMarks myBenchMarks[NUM_BENCHMARKS] = /*! @function freeMemory @abstract Return available RAM memory - @discussion This routine returns the ammount of RAM memory available after + @discussion This routine returns the amount of RAM memory available after initialising the C runtime. @param @return Free RAM available, -1 for non AVR microcontrollers @@ -282,7 +282,7 @@ static void LCDLoadCharacters ( int numChars ) memory. @discussion Writes to all the positions of the LCD a fixed pattern from memory. For every line it writes, it positions the cursor. - The number of writen LCD accesses is: LCD_ROW * LCD_COLUMS + 2. + The number of written LCD accesses is: LCD_ROW * LCD_COLUMS + 2. It returns the cumulative time used by all the iterations. @param[in] iterations: number of iterations the benchmark is executed before @@ -320,9 +320,9 @@ long benchmark1 ( uint8_t iterations ) @abstract writes to the LCD a full set of characters loaded on the LCD memory one line pixel at the time @discussion Writes to all the positions of the LCD a fixed pattern from - memory each patern take 6 write operations to the LCD. For every - character it writes it sets the cursor possition. - The number of writen LCD accesses is: LCD_ROW * LCD_COLUMS * 6. + memory each pattern take 6 write operations to the LCD. For every + character it writes it sets the cursor position. + The number of written LCD accesses is: LCD_ROW * LCD_COLUMS * 6. It returns the cumulative time used by all the iterations. @param[in] iterations: number of iterations the benchmark is executed before @@ -363,7 +363,7 @@ long benchmark2 ( uint8_t iterations ) @abstract writes to the LCD a full set of characters from memory. @discussion Writes to all the positions of the LCD a fixed pattern from RAM. For every line it writes, it positions the cursor. - The number of writen LCD accesses is: LCD_ROW * LCD_COLUMS + 2. + The number of written LCD accesses is: LCD_ROW * LCD_COLUMS + 2. It returns the cumulative time used by all the iterations. @param[in] iterations: number of iterations the benchmark is executed before @@ -398,7 +398,7 @@ long benchmark3 ( uint8_t iterations ) @abstract writes to the LCD a full set of characters from memory. @discussion Writes to all the positions of the LCD a fixed pattern from flash. For every line it writes, it positions the cursor. - The number of writen LCD accesses is: LCD_ROW * LCD_COLUMS + 2. + The number of written LCD accesses is: LCD_ROW * LCD_COLUMS + 2. It returns the cumulative time used by all the iterations. @param[in] iterations: number of iterations the benchmark is executed before diff --git a/Sming/Libraries/LittleFS b/Sming/Libraries/LittleFS index e02efce58e..7e3ffdc7df 160000 --- a/Sming/Libraries/LittleFS +++ b/Sming/Libraries/LittleFS @@ -1 +1 @@ -Subproject commit e02efce58e6996601255e59c3c688d583f1b843d +Subproject commit 7e3ffdc7dffca6c2139bf090bac50e0aa8ce399d diff --git a/Sming/Libraries/MCP23017/MCP23017.cpp b/Sming/Libraries/MCP23017/MCP23017.cpp index 0c2cc315be..9917016ca4 100644 --- a/Sming/Libraries/MCP23017/MCP23017.cpp +++ b/Sming/Libraries/MCP23017/MCP23017.cpp @@ -222,7 +222,7 @@ uint8_t MCP23017::digitalRead(uint8_t pin) { * Opendrain will set the INT pin to value or open drain. * polarity will set LOW or HIGH on interrupt. * Default values after Power On Reset are: (false,flase, LOW) - * If you are connecting the INTA/B pin to arduino 2/3, you should configure the interupt handling as FALLING with + * If you are connecting the INTA/B pin to arduino 2/3, you should configure the interrupt handling as FALLING with * the default configuration. */ void MCP23017::setupInterrupts(uint8_t mirroring, uint8_t openDrain, uint8_t polarity){ diff --git a/Sming/Libraries/MCP23S17/MCP23S17.cpp b/Sming/Libraries/MCP23S17/MCP23S17.cpp index 7433c0b88d..6f45947871 100644 --- a/Sming/Libraries/MCP23S17/MCP23S17.cpp +++ b/Sming/Libraries/MCP23S17/MCP23S17.cpp @@ -45,7 +45,7 @@ MCP::MCP(uint8_t address, uint8_t cs) _csBitmask = (1 << _cs); _address = address; _rcmd = (OPCODER | (_address << 1)); //Read command for chip address - _wcmd = (OPCODEW | (_address << 1)); //Write command for chip addres + _wcmd = (OPCODEW | (_address << 1)); //Write command for chip address _modeCache = 0xFFFF; // Default I/O mode is all input, 0xFFFF _outputCache = 0x0000; // Default output state is all off, 0x0000 _pullupCache = 0x0000; // Default pull-up state is all off, 0x0000 diff --git a/Sming/Libraries/MCP23S17/MCP23S17.h b/Sming/Libraries/MCP23S17/MCP23S17.h index cc6c81f91a..5cb986d795 100644 --- a/Sming/Libraries/MCP23S17/MCP23S17.h +++ b/Sming/Libraries/MCP23S17/MCP23S17.h @@ -48,7 +48,7 @@ namespace MCP23S17Registers { static const uint8_t IPOLA = 0x02; // MCP23x17 Input Polarity Register static const uint8_t IPOLB = 0x03; // 0 = Normal (default)(low reads as 0), 1 = Inverted (low reads as 1) - static const uint8_t GPINTENA = 0x04; // MCP23x17 Interrupt on Change Pin Assignements + static const uint8_t GPINTENA = 0x04; // MCP23x17 Interrupt on Change Pin Assignments static const uint8_t GPINTENB = 0x05; // 0 = No Interrupt on Change (default), 1 = Interrupt on Change static const uint8_t DEFVALA = 0x06; // MCP23x17 Default Compare Register for Interrupt on Change diff --git a/Sming/Libraries/MCP_CAN_lib b/Sming/Libraries/MCP_CAN_lib index 280d6bec2f..074f7f4c69 160000 --- a/Sming/Libraries/MCP_CAN_lib +++ b/Sming/Libraries/MCP_CAN_lib @@ -1 +1 @@ -Subproject commit 280d6bec2f424f39955e62f2bc45efc01577f783 +Subproject commit 074f7f4c69f65c19c6fa5e32287d621abf03be64 diff --git a/Sming/Libraries/MDNS b/Sming/Libraries/MDNS index 3c1370d47d..cb2d299958 160000 --- a/Sming/Libraries/MDNS +++ b/Sming/Libraries/MDNS @@ -1 +1 @@ -Subproject commit 3c1370d47d1deec99074bc9e6ff384998440aff4 +Subproject commit cb2d299958ee08d7bcdc3b8431c313e1057dda77 diff --git a/Sming/Libraries/MFRC522/MFRC522.cpp b/Sming/Libraries/MFRC522/MFRC522.cpp index 43e557f121..31ae38c33c 100644 --- a/Sming/Libraries/MFRC522/MFRC522.cpp +++ b/Sming/Libraries/MFRC522/MFRC522.cpp @@ -681,7 +681,7 @@ byte MFRC522::PICC_Select( Uid *uid, ///< Pointer to Uid struct. Normally outp } // Set bit adjustments - rxAlign = txLastBits; // Having a seperate variable is overkill. But it makes the next line easier to read. + rxAlign = txLastBits; // Having a separate variable is overkill. But it makes the next line easier to read. PCD_WriteRegister(BitFramingReg, (rxAlign << 4) + txLastBits); // RxAlign = BitFramingReg[6..4]. TxLastBits = BitFramingReg[2..0] // Transmit the buffer and receive the response. @@ -934,7 +934,7 @@ byte MFRC522::MIFARE_Ultralight_Write( byte page, ///< The page (2-15) to writ return STATUS_INVALID; } - // Build commmand buffer + // Build command buffer byte cmdBuffer[6]; cmdBuffer[0] = PICC_CMD_UL_WRITE; cmdBuffer[1] = page; @@ -1160,7 +1160,7 @@ const char * MFRC522::GetStatusCodeName(byte code ///< One of the StatusCode enu switch (code) { case STATUS_OK: return ("Success."); break; case STATUS_ERROR: return ("Error in communication."); break; - case STATUS_COLLISION: return ("Collission detected."); break; + case STATUS_COLLISION: return ("Collision detected."); break; case STATUS_TIMEOUT: return ("Timeout in communication."); break; case STATUS_NO_ROOM: return ("A buffer is not big enough."); break; case STATUS_INTERNAL_ERROR: return ("Internal error in the code. Should not happen."); break; @@ -1517,7 +1517,7 @@ void MFRC522::PICC_DumpMifareUltralightToSerial() { } // End PICC_DumpMifareUltralightToSerial() /** - * Calculates the bit pattern needed for the specified access bits. In the [C1 C2 C3] tupples C1 is MSB (=4) and C3 is LSB (=1). + * Calculates the bit pattern needed for the specified access bits. In the [C1 C2 C3] tuples C1 is MSB (=4) and C3 is LSB (=1). */ void MFRC522::MIFARE_SetAccessBits( byte *accessBitBuffer, ///< Pointer to byte 6, 7 and 8 in the sector trailer. Bytes [0..2] will be set. byte g0, ///< Access bits [C1 C2 C3] for block 0 (for sectors 0-31) or blocks 0-4 (for sectors 32-39) diff --git a/Sming/Libraries/MFRC522/MFRC522.h b/Sming/Libraries/MFRC522/MFRC522.h index 9d3158062f..927ee3f4df 100644 --- a/Sming/Libraries/MFRC522/MFRC522.h +++ b/Sming/Libraries/MFRC522/MFRC522.h @@ -74,7 +74,6 @@ */ #ifndef MFRC522_h #define MFRC522_h -#include #include #include @@ -289,7 +288,7 @@ class MFRC522 { enum StatusCode { STATUS_OK = 1, // Success STATUS_ERROR = 2, // Error in communication - STATUS_COLLISION = 3, // Collission detected + STATUS_COLLISION = 3, // Collision detected STATUS_TIMEOUT = 4, // Timeout in communication. STATUS_NO_ROOM = 5, // A buffer is not big enough. STATUS_INTERNAL_ERROR = 6, // Internal error in the code. Should not happen ;-) diff --git a/Sming/Libraries/MFRC522/README.rst b/Sming/Libraries/MFRC522/README.rst index 4eb93048d0..2196eb0678 100644 --- a/Sming/Libraries/MFRC522/README.rst +++ b/Sming/Libraries/MFRC522/README.rst @@ -22,12 +22,12 @@ Development **Feature status: complete freeze**; no function or API change -**Code status: paritial freeze**; just fixes/typos or documentation updates; *no* extentions for other boards; *no* new examples +**Code status: partial freeze**; just fixes/typos or documentation updates; *no* extensions for other boards; *no* new examples **Maintenance status: sporadically** **Why no further development?** -This library has a long history and is used in many projects. This projects often do not document what version they use. Commiting changes maybe brake those old project and lead to bad experience (for beginners) and support request. For those reasons the library is in freeze mode. You can still commit typo, documentation or bug fixes. +This library has a long history and is used in many projects. This projects often do not document what version they use. Committing changes maybe brake those old project and lead to bad experience (for beginners) and support request. For those reasons the library is in freeze mode. You can still commit typo, documentation or bug fixes. .. _before buy: diff --git a/Sming/Libraries/MHZ19 b/Sming/Libraries/MHZ19 new file mode 160000 index 0000000000..a2ecfec4c1 --- /dev/null +++ b/Sming/Libraries/MHZ19 @@ -0,0 +1 @@ +Subproject commit a2ecfec4c1fa07e7be68dab0d1a2fcc2cc6190de diff --git a/Sming/Libraries/MMA_7455/examples/MMA_7455_simpleRead/MMA_7455_simpleRead.pde b/Sming/Libraries/MMA_7455/examples/MMA_7455_simpleRead/MMA_7455_simpleRead.pde index bdcfb0912a..9dc182f887 100644 --- a/Sming/Libraries/MMA_7455/examples/MMA_7455_simpleRead/MMA_7455_simpleRead.pde +++ b/Sming/Libraries/MMA_7455/examples/MMA_7455_simpleRead/MMA_7455_simpleRead.pde @@ -17,7 +17,7 @@ void setup() // Set the sensitivity you want to use // 2 = 2g, 4 = 4g, 8 = 8g mySensor.initSensitivity(2); - // Calibrate the Offset, that values corespond in + // Calibrate the Offset, that values correspond in // flat position to: xVal = -30, yVal = -20, zVal = +20 // !!!Activate this after having the first values read out!!! //mySensor.calibrateOffset(0.23, -43.2, 12.43); diff --git a/Sming/Libraries/Mirf/Mirf.cpp b/Sming/Libraries/Mirf/Mirf.cpp index 68c94e274e..59b10aca3d 100644 --- a/Sming/Libraries/Mirf/Mirf.cpp +++ b/Sming/Libraries/Mirf/Mirf.cpp @@ -18,7 +18,7 @@ * An Ardunio port of: * http://www.tinkerer.eu/AVRLib/nRF24L01 * - * Significant changes to remove depencence on interupts and auto ack support. + * Significant changes to remove depencence on interrupts and auto ack support. * * Aaron Shrimpton * @@ -187,7 +187,7 @@ void Nrf24l::send(uint8_t * value) PTX = 0; break; } - } // Wait until last paket is send + } // Wait until last packet is send ceLow(); @@ -216,7 +216,7 @@ bool Nrf24l::isSending() { status = getStatus(); /* - * if sending successful (TX_DS) or max retries exceded (MAX_RT). + * if sending successful (TX_DS) or max retries exceeded (MAX_RT). */ if((status & ((1 << TX_DS) | (1 << MAX_RT)))){ diff --git a/Sming/Libraries/Mirf/examples/attiny85_counter_example/attiny85_counter_example.ino b/Sming/Libraries/Mirf/examples/attiny85_counter_example/attiny85_counter_example.ino index 5009f9ac0f..d0904ba9f4 100644 --- a/Sming/Libraries/Mirf/examples/attiny85_counter_example/attiny85_counter_example.ino +++ b/Sming/Libraries/Mirf/examples/attiny85_counter_example/attiny85_counter_example.ino @@ -40,7 +40,7 @@ void setup() { Mirf.init(); /* - * Configure reciving address. + * Configure receiving address. */ Mirf.setRADDR((byte *)"clie1"); diff --git a/Sming/Libraries/Mirf/examples/ping_client/ping_client.pde b/Sming/Libraries/Mirf/examples/ping_client/ping_client.pde index 221489ea8c..5f3e6c859e 100644 --- a/Sming/Libraries/Mirf/examples/ping_client/ping_client.pde +++ b/Sming/Libraries/Mirf/examples/ping_client/ping_client.pde @@ -40,7 +40,7 @@ void setup(){ Mirf.init(); /* - * Configure reciving address. + * Configure receiving address. */ Mirf.setRADDR((byte *)"clie1"); diff --git a/Sming/Libraries/Mirf/examples/ping_server/ping_server.pde b/Sming/Libraries/Mirf/examples/ping_server/ping_server.pde index 1138721978..fdca49bb73 100644 --- a/Sming/Libraries/Mirf/examples/ping_server/ping_server.pde +++ b/Sming/Libraries/Mirf/examples/ping_server/ping_server.pde @@ -1,5 +1,5 @@ /** - * An Mirf example which copies back the data it recives. + * An Mirf example which copies back the data it receives. * * Pins: * Hardware SPI: @@ -34,7 +34,7 @@ void setup(){ Mirf.init(); /* - * Configure reciving address. + * Configure receiving address. */ Mirf.setRADDR((byte *)"serv1"); @@ -65,7 +65,7 @@ void loop(){ byte data[Mirf.payload]; /* - * If a packet has been recived. + * If a packet has been received. * * isSending also restores listening mode when it * transitions from true to false. @@ -94,9 +94,9 @@ void loop(){ Mirf.send(data); /* - * Wait untill sending has finished + * Wait until sending has finished * - * NB: isSending returns the chip to receving after returning true. + * NB: isSending returns the chip to receiving after returning true. */ Serial.println("Reply sent."); diff --git a/Sming/Libraries/Mirf/examples/ping_server_interupt/ping_server_interupt.pde b/Sming/Libraries/Mirf/examples/ping_server_interupt/ping_server_interupt.pde index f75c7a4d32..abe001c5f4 100644 --- a/Sming/Libraries/Mirf/examples/ping_server_interupt/ping_server_interupt.pde +++ b/Sming/Libraries/Mirf/examples/ping_server_interupt/ping_server_interupt.pde @@ -1,7 +1,7 @@ /** - * An Mirf example which copies back the data it recives. - * While wating the arduino goes to sleep and will be woken up - * by the interupt pin of the mirf. + * An Mirf example which copies back the data it receives. + * While waiting the arduino goes to sleep and will be woken up + * by the interrupt pin of the mirf. * * Warning: Due to the sleep mode the Serial output donsn't work. * @@ -47,7 +47,7 @@ void setup(){ Mirf.init(); /* - * Configure reciving address. + * Configure receiving address. */ Mirf.setRADDR((byte *)"serv1"); @@ -85,7 +85,7 @@ void loop(){ byte data[Mirf.payload]; /* - * If a packet has been recived. + * If a packet has been received. */ if(!Mirf.isSending() && Mirf.dataReady()){ diff --git a/Sming/Libraries/ModbusMaster/samples/generic/app/application.cpp b/Sming/Libraries/ModbusMaster/samples/generic/app/application.cpp index c8fd3ef394..3d8d826030 100644 --- a/Sming/Libraries/ModbusMaster/samples/generic/app/application.cpp +++ b/Sming/Libraries/ModbusMaster/samples/generic/app/application.cpp @@ -10,8 +10,8 @@ Timer mbLoopTimer; ModbusMaster mbMaster; -HardwareSerial modbusComPort(UART0); -HardwareSerial debugComPort(UART1); +HardwareSerial modbusComPort(UART_ID_0); +HardwareSerial debugComPort(UART_ID_1); uint16_t globalSeconds = 0; diff --git a/Sming/Libraries/MultipartParser/component.mk b/Sming/Libraries/MultipartParser/component.mk index de2e15648c..5deb975db0 100644 --- a/Sming/Libraries/MultipartParser/component.mk +++ b/Sming/Libraries/MultipartParser/component.mk @@ -1,6 +1,7 @@ COMPONENT_SRCDIRS := src COMPONENT_INCDIRS := src COMPONENT_DOXYGEN_INPUT := src +COMPONENT_DEPENDS := Network COMPONENT_SUBMODULES := multipart-parser COMPONENT_SRCFILES := multipart-parser/multipart_parser.c diff --git a/Sming/Libraries/MultipartParser/samples/Conditional_Upload/Makefile b/Sming/Libraries/MultipartParser/samples/Conditional_Upload/Makefile new file mode 100644 index 0000000000..ff51b6c3a7 --- /dev/null +++ b/Sming/Libraries/MultipartParser/samples/Conditional_Upload/Makefile @@ -0,0 +1,9 @@ +##################################################################### +#### Please don't change this file. Use component.mk instead #### +##################################################################### + +ifndef SMING_HOME +$(error SMING_HOME is not set: please configure it as an environment variable) +endif + +include $(SMING_HOME)/project.mk diff --git a/Sming/Libraries/MultipartParser/samples/Conditional_Upload/README.rst b/Sming/Libraries/MultipartParser/samples/Conditional_Upload/README.rst new file mode 100644 index 0000000000..888eb21fae --- /dev/null +++ b/Sming/Libraries/MultipartParser/samples/Conditional_Upload/README.rst @@ -0,0 +1,44 @@ +HttpServer Upload +================= + +This example demonstrates how to upload multiple files on the server. + + +About HTTP server file upload +----------------------------- + +The HTTP server coming with Sming is quite powerful but it is limited +by available hardware resources. + +This sample demonstrates how to use the :library:`MultipartParser` library +to enable file upload of the HTTP server. On a normal computer the file uploads +are usually using temporary space on the hard disk or in memory to store the +incoming data. + +On an embedded device that is a luxury that we can hardly afford. +In this sample we demonstrate how to define which file upload fields +should be recognized and what (file) streams are responsible for processing and +storing the data. +If a field is not specified then its content will be discarded. + +Usage instructions +------------------ + +1. Configure your flash memory layout. See :ref:`hardware_config`. + +2. Build the example by running:: + + make + +3. Connect your device via USB/Serial cable and run:: + + make flash + + to install the example firmware. + +4. Point the browser to your device's IP address to open the firmware upgrade page. + +5. Select the upload file and hit the "Update" button. + + If the file size isn't bigger than the MAX_FILE_SIZE defined in the application code + you should see a confirmation that the upload was successful. \ No newline at end of file diff --git a/Sming/Libraries/MultipartParser/samples/Conditional_Upload/app/application.cpp b/Sming/Libraries/MultipartParser/samples/Conditional_Upload/app/application.cpp new file mode 100644 index 0000000000..e6ce7b9a76 --- /dev/null +++ b/Sming/Libraries/MultipartParser/samples/Conditional_Upload/app/application.cpp @@ -0,0 +1,170 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +HttpServer server; + +constexpr size_t MAX_FILE_SIZE = 1024; // Allowed size in bytes +String uploadError; + +void onIndex(HttpRequest& request, HttpResponse& response) +{ + auto tmpl = new TemplateFileStream("index.html"); + auto& vars = tmpl->variables(); + vars["MAX_FILE_SIZE"] = String(MAX_FILE_SIZE); + response.sendNamedStream(tmpl); // this template object will be deleted automatically + + response.setCache(86400, true); // You can instruct the browser to cache the content for better performance. +} + +void onFile(HttpRequest& request, HttpResponse& response) +{ + String file = request.uri.getRelativePath(); + if(file.length() == 0) { + file = "index.html"; + } + + response.setCache(86400, true); // It's important to use cache for better performance. + response.sendFile(file); +} + +int onUpload(HttpServerConnection& connection, HttpRequest& request, HttpResponse& response) +{ + response.code = HTTP_STATUS_OK; + response.setContentType(MIME_HTML); + String content = F("All good"); + + ReadWriteStream* stream = request.files["firmware"]; + + if(stream != nullptr && stream->getStreamType() == eSST_HeaderChecker) { + auto checkerStream = static_cast(stream); + if(!checkerStream->isValid()) { + response.code = HTTP_STATUS_BAD_REQUEST; + content = uploadError; + } + } + else { + auto limitedWriteStream = static_cast(stream); + + + if(uploadError.length() > 0) { + response.code = HTTP_STATUS_BAD_REQUEST; + content = uploadError; + } + else if(!limitedWriteStream->isValid()) { + content = F("File size is bigger than allowed!"); + response.code = HTTP_STATUS_BAD_REQUEST; + /* + * There is an incomplete file stored on the file system. + * You can either leave it as it is and overwrite it the next time or + * truncate it with the code below + */ + auto fileStream = static_cast(limitedWriteStream->getSource()); + fileStream->truncate(); + } + } + + String html = F("

") + content + F("

"); + response.headers[HTTP_HEADER_CONTENT_LENGTH] = html.length(); + response.sendString(html); + + return 0; +} + +/** + * @brief This function is used to check if an upload file can be stored. + * + * @param headers - HTTP headers for the specific part + * @param stream - the original stream used to store data + * @param part + * + * @retval bool false to reject the saving of the content + */ +bool allowPart(const HttpHeaders& headers, ReadWriteStream* stream, const PartCheckerStream::FilePart& part) +{ + // below is an example how to check for the filename length before storing it + if(part.fileName.length() > 32) { + uploadError = F("Filename too long!"); + return false; + } + + // If needed it is possible also to check if the file type is as expected + // The code below requires the uploaded file to be plain text. + if(part.mime != toString(MIME_TEXT)) { + uploadError = F("Only text files allowed!"); + return false; + } + + // here is an example how to set the provided file name + if(part.fileName.length() > 0) { + auto fileStream = static_cast(stream); + fileStream->open(part.fileName, File::CreateNewAlways | File::WriteOnly); + } + + return true; +} + +void fileUploadMapper(HttpFiles& files) +{ + uploadError = nullptr; // Reset to 'no error' + + /* + * On a normal computer file uploads are usually using + * temporary space on the hard disk or in memory to store the incoming data. + * + * On an embedded device that is a luxury that we can hardly afford. + * Therefore we should define a `map` that specifies explicitly + * by which stream each form field will be consumed. + * + * If a field is not specified then its content will be discarded. + * + */ + + /* + * Create a stream to store uploaded content. + * Since no name is provided in the constructor the name will be injected by the MultipartParser. + */ + auto fileStream = new FileStream; + + /* + * Using the LimitedWriteStream wrapper will guarantee that the file size is limited to MAX_FILE_SIZE bytes. + */ + // files["firmware"] = new LimitedWriteStream(fileStream, MAX_FILE_SIZE); + + /** + * Uncomment the line below for a more complex example. + * This one uses PartCheckerStream and provides way to decide if the content should be stored + * based on the allowPart callback. + */ + files["firmware"] = new PartCheckerStream(fileStream, allowPart); +} + +void startWebServer() +{ + server.setBodyParser(MIME_FORM_MULTIPART, formMultipartParser); + + server.listen(80); + server.paths.set("/", onIndex); + server.paths.set("/upgrade", new HttpMultipartResource(fileUploadMapper, onUpload)); + server.paths.setDefault(onFile); +} + +void init() +{ + Serial.begin(SERIAL_BAUD_RATE); // 115200 by default + Serial.systemDebugOutput(true); // Enable debug output to serial + + spiffs_mount(); // Mount file system in order to work with files + + WifiStation.enable(true); + //WifiStation.config(WIFI_SSID, WIFI_PWD); + //WifiStation.enableDHCP(true); + + // Run WEB server on system ready + System.onReady(startWebServer); +} diff --git a/Sming/Libraries/MultipartParser/samples/Conditional_Upload/component.mk b/Sming/Libraries/MultipartParser/samples/Conditional_Upload/component.mk new file mode 100644 index 0000000000..aafe73766e --- /dev/null +++ b/Sming/Libraries/MultipartParser/samples/Conditional_Upload/component.mk @@ -0,0 +1,10 @@ +HWCONFIG := spiffs +SPIFF_FILES = web/ +ARDUINO_LIBRARIES := MultipartParser + +ifndef MAKE_DOCS + +web-upload: spiffs-image-update + $(call WriteFlash,$(SPIFF_START_ADDR)=$(SPIFF_BIN_OUT)) + +endif diff --git a/Sming/Libraries/MultipartParser/samples/Conditional_Upload/web/index.html b/Sming/Libraries/MultipartParser/samples/Conditional_Upload/web/index.html new file mode 100644 index 0000000000..1f89f21e70 --- /dev/null +++ b/Sming/Libraries/MultipartParser/samples/Conditional_Upload/web/index.html @@ -0,0 +1,18 @@ + + + + Upload Demo + + +

Update Firmware

+

+ This sample demonstrates how to upload a file, get its filename and store the file on the device file system.
+ The maximum allowed file size is {MAX_FILE_SIZE} bytes. +

+

+
+ + +

+ + diff --git a/Sming/Libraries/MultipartParser/src/MultipartParser.cpp b/Sming/Libraries/MultipartParser/src/MultipartParser.cpp index 43d29d9ac7..3a864ae250 100644 --- a/Sming/Libraries/MultipartParser/src/MultipartParser.cpp +++ b/Sming/Libraries/MultipartParser/src/MultipartParser.cpp @@ -12,6 +12,7 @@ #include "MultipartParser.h" #include +#include multipart_parser_settings_t MultipartParser::settings = { .on_header_field = readHeaderName, @@ -91,8 +92,7 @@ int MultipartParser::partBegin(multipart_parser_t* p) { GET_PARSER(); - parser->headerName.setLength(0); - parser->headerValue.setLength(0); + parser->resetHeaders(); parser->stream = nullptr; return 0; @@ -102,62 +102,102 @@ int MultipartParser::readHeaderName(multipart_parser_t* p, const char* at, size_ { GET_PARSER(); - if(parser->headerValue != String::empty) { - // process previous header - int result = parser->processHeader(); - if(result != 0) { - return result; - } - } + return parser->headerBuilder.onHeaderField(at, length); +} - parser->headerName.concat(at, length); +int MultipartParser::readHeaderValue(multipart_parser_t* p, const char* at, size_t length) +{ + GET_PARSER(); - return 0; + return parser->headerBuilder.onHeaderValue(parser->incomingHeaders, at, length); } -int MultipartParser::processHeader() +int MultipartParser::partHeadersComplete(multipart_parser_t* p) { - if(FS("Content-Disposition") == headerName) { - // Content-Disposition: form-data; name="image"; filename=".gitignore" - // Content-Disposition: form-data; name="data" - int startPos = headerValue.indexOf(FS("name=")); - if(startPos < 0) { - debug_e("Invalid header content"); - return -1; // Invalid header content - } - startPos += 6; // name=" - int endPos = headerValue.indexOf(';', startPos); - - String name; - if(endPos < 0) { - name = headerValue.substring(startPos, headerValue.length() - 1); - } else { - name = headerValue.substring(startPos, endPos - 1); - } - // get stream corresponding to field name - stream = request.files[name]; + GET_PARSER(); + + auto& headers = static_cast(parser->incomingHeaders); + String headerValue = headers[HTTP_HEADER_CONTENT_DISPOSITION]; + if(!headerValue) { + return 0; } - headerName.setLength(0); - headerValue.setLength(0); + // Content-Disposition: form-data; name="image"; filename=".gitignore" + // Content-Disposition: form-data; name="data" + int startPos = headerValue.indexOf(F("name=")); + if(startPos < 0) { + debug_e("Invalid header content"); + return -1; // Invalid header content + } + startPos += 6; // name=" + int endPos = headerValue.indexOf(';', startPos); + + String name; + if(endPos < 0) { + name = headerValue.substring(startPos, headerValue.length() - 1); + } else { + name = headerValue.substring(startPos, endPos - 1); + } + // get stream corresponding to field name + parser->stream = parser->request.files[name]; - return 0; -} + // inject file name, if any + startPos = headerValue.indexOf(F("filename=")); + if(startPos < 0) { + return 0; + } -int MultipartParser::readHeaderValue(multipart_parser_t* p, const char* at, size_t length) -{ - GET_PARSER(); + startPos += 10; // filename=" + endPos = headerValue.indexOf('"', startPos); + if(endPos < 0) { + return 0; + } - parser->headerValue.concat(at, length); + String fileName = headerValue.substring(startPos, endPos); + // sanitize the name -> remove any slashes and trailing dots + fileName.replace('/', '-'); + fileName.trim("."); + if(fileName.length() == 0) { + return 0; + } - return 0; -} + // if the stream is of type FileStream and the name is not set + // then we can set the name and flags to create-write + auto stream = parser->stream; + if(stream == nullptr) { + return 0; + } -int MultipartParser::partHeadersComplete(multipart_parser_t* p) -{ - GET_PARSER(); + if(stream->getStreamType() == eSST_Wrapper) { + auto wrapper = static_cast(stream); + stream = wrapper->getSource(); + } - return parser->processHeader(); + if(stream->getStreamType() == eSST_File) { + auto fileStream = static_cast(stream); + if(fileStream->fileName().length() == 0) { + fileStream->open(fileName, File::CreateNewAlways | File::WriteOnly); + } + return 0; + } + + if(stream->getStreamType() == eSST_HeaderChecker) { + String contentLength = headers[HTTP_HEADER_CONTENT_LENGTH]; + PartCheckerStream::FilePart part = { + .name = name, + .fileName = fileName, + .mime = headers[HTTP_HEADER_CONTENT_TYPE], + .length = contentLength ? contentLength.toInt() : -1, + }; + + auto checkerStream = static_cast(stream); + if(!checkerStream->checkHeaders(headers, part)) { + // the stream will be freed later. For now mark it as not usable. + parser->stream = nullptr; + } + } + + return 0; } int MultipartParser::partData(multipart_parser_t* p, const char* at, size_t length) @@ -178,6 +218,8 @@ int MultipartParser::partEnd(multipart_parser_t* p) { GET_PARSER(); + parser->resetHeaders(); + return 0; } @@ -187,3 +229,9 @@ int MultipartParser::bodyEnd(multipart_parser_t* p) return 0; } + +void MultipartParser::resetHeaders() +{ + headerBuilder.reset(); + incomingHeaders.clear(); +} diff --git a/Sming/Libraries/MultipartParser/src/MultipartParser.h b/Sming/Libraries/MultipartParser/src/MultipartParser.h index e6184858ee..eab7844321 100644 --- a/Sming/Libraries/MultipartParser/src/MultipartParser.h +++ b/Sming/Libraries/MultipartParser/src/MultipartParser.h @@ -14,7 +14,9 @@ #include #include +#include #include +#include "PartCheckerStream.h" #include "../multipart-parser/multipart_parser.h" @@ -43,20 +45,18 @@ class MultipartParser } private: - MultipartParser(HttpRequest& request, const String& boundaryArg); - static multipart_parser_settings_t settings; - String headerName; ///< Current header field name - String headerValue; ///< Current header field name - + HttpHeaderBuilder headerBuilder; + HttpHeaders incomingHeaders; ///< Full set of incoming part headers HttpRequest& request; String boundary; multipart_parser_t parserEngine; ReadWriteStream* stream = nullptr; - int processHeader(); + MultipartParser(HttpRequest& request, const String& boundaryArg); + void resetHeaders(); }; /** Body parser for content-type `form-data/multipart` diff --git a/Sming/Libraries/MultipartParser/src/PartCheckerStream.h b/Sming/Libraries/MultipartParser/src/PartCheckerStream.h new file mode 100644 index 0000000000..248381c84d --- /dev/null +++ b/Sming/Libraries/MultipartParser/src/PartCheckerStream.h @@ -0,0 +1,79 @@ +/**** + * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. + * Created 2015 by Skurydin Alexey + * http://github.com/SmingHub/Sming + * All files of the Sming Core are provided under the LGPL v3 license. + * + * PartCheckerStream.h + * + * @author: 2021 - Slavey Karadzhov + * + ****/ + +#pragma once + +#include +#include +#include + +class PartCheckerStream : public StreamWrapper +{ +public: + struct FilePart { + String name; + String fileName; + String mime; + int length; // -1 if not available, >0 otherwise + }; + + using CheckerCallback = + Delegate; + + /** + * @param callback + * @param stream - The actual stream doing the work. The stream is owned and will be deleted here + */ + PartCheckerStream(ReadWriteStream* source, CheckerCallback callback) : StreamWrapper(source), callback(callback) + { + } + + bool checkHeaders(const HttpHeaders& headers, const FilePart& part) + { + save = callback(headers, getSource(), part); + return save; + } + + bool isValid() const override + { + return save; + } + + StreamType getStreamType() const override + { + return eSST_HeaderChecker; + } + + size_t write(const uint8_t* buffer, size_t size) override + { + if(!save) { + debug_d("Discarding %d bytes", size); + return size; + } + + return getSource()->write(buffer, size); + } + + uint16_t readMemoryBlock(char* data, int bufSize) override + { + return getSource()->readMemoryBlock(data, bufSize); + } + + bool isFinished() override + { + return getSource()->isFinished(); + } + +private: + bool save{true}; + CheckerCallback callback; +}; diff --git a/Sming/Libraries/OneWire/examples/DS250x_PROM/DS250x_PROM.pde b/Sming/Libraries/OneWire/examples/DS250x_PROM/DS250x_PROM.pde index a85b1c2925..08061709a7 100644 --- a/Sming/Libraries/OneWire/examples/DS250x_PROM/DS250x_PROM.pde +++ b/Sming/Libraries/OneWire/examples/DS250x_PROM/DS250x_PROM.pde @@ -11,7 +11,7 @@ DS250x add-only programmable memory reader w/SKIP ROM. Sketch will only read the first page of memory(32bits) starting from the lower address(0000h), if more than 1 device is present, then use the sketch with search functions. Remember to put a 4.7K pullup resistor between pin 6 and +Vcc - To change the range or ammount of data to read, simply change the data array size, LSB/MSB addresses and for loop iterations + To change the range or amount of data to read, simply change the data array size, LSB/MSB addresses and for loop iterations This example code is in the public domain and is provided AS-IS. @@ -32,7 +32,7 @@ void loop() { byte i; // This is for the for loops boolean present; // device present var byte data[32]; // container for the data from device - byte leemem[3] = { // array with the commands to initiate a read, DS250x devices expect 3 bytes to start a read: command,LSB&MSB adresses + byte leemem[3] = { // array with the commands to initiate a read, DS250x devices expect 3 bytes to start a read: command,LSB&MSB addresses 0xF0 , 0x00 , 0x00 }; // 0xF0 is the Read Data command, followed by 00h 00h as starting address(the beginning, 0000h) byte ccrc; // Variable to store the command CRC byte ccrc_calc; diff --git a/Sming/Libraries/Ota/README.rst b/Sming/Libraries/Ota/README.rst index 5b0c046e43..03ce9a3549 100644 --- a/Sming/Libraries/Ota/README.rst +++ b/Sming/Libraries/Ota/README.rst @@ -51,7 +51,7 @@ After that you will have access to a global ``OtaManager`` instance that can be // ... } -See the :sample:`Upgrade` sample application. +See the :sample:`Basic_Ota` sample application. API Documentation ----------------- diff --git a/Sming/Libraries/Ota/component.mk b/Sming/Libraries/Ota/component.mk index 1303f4fdc5..d5939e6287 100644 --- a/Sming/Libraries/Ota/component.mk +++ b/Sming/Libraries/Ota/component.mk @@ -13,4 +13,6 @@ COMPONENT_INCDIRS := \ ifeq ($(COMPONENT_ARCH),Esp8266) COMPONENT_DEPENDS += rboot -endif \ No newline at end of file +endif + +COMPONENT_DOXYGEN_INPUT := src diff --git a/Sming/Libraries/Ota/src/Arch/Esp32/include/Ota/IdfUpgrader.h b/Sming/Libraries/Ota/src/Arch/Esp32/include/Ota/IdfUpgrader.h index 906354e45c..f266eb91c0 100644 --- a/Sming/Libraries/Ota/src/Arch/Esp32/include/Ota/IdfUpgrader.h +++ b/Sming/Libraries/Ota/src/Arch/Esp32/include/Ota/IdfUpgrader.h @@ -16,6 +16,9 @@ namespace Ota { +/** + * @brief ESP32 OTA Upgrader implementation + */ class IdfUpgrader : public UpgraderBase { public: diff --git a/Sming/Libraries/Ota/src/Arch/Esp8266/include/Ota/RbootUpgrader.h b/Sming/Libraries/Ota/src/Arch/Esp8266/include/Ota/RbootUpgrader.h index ecf42af05c..c0f100ca79 100644 --- a/Sming/Libraries/Ota/src/Arch/Esp8266/include/Ota/RbootUpgrader.h +++ b/Sming/Libraries/Ota/src/Arch/Esp8266/include/Ota/RbootUpgrader.h @@ -16,6 +16,9 @@ namespace Ota { +/** + * @brief ESP8266 rBoot OTA Upgrader implementation + */ class RbootUpgrader : public UpgraderBase { public: diff --git a/Sming/Libraries/Ota/src/UpgradeOutputStream.cpp b/Sming/Libraries/Ota/src/UpgradeOutputStream.cpp index f84e348ed3..998d7945c5 100644 --- a/Sming/Libraries/Ota/src/UpgradeOutputStream.cpp +++ b/Sming/Libraries/Ota/src/UpgradeOutputStream.cpp @@ -10,6 +10,7 @@ */ #include "include/Ota/UpgradeOutputStream.h" +#include namespace Ota { diff --git a/Sming/Libraries/Ota/src/include/Ota/UpgraderBase.h b/Sming/Libraries/Ota/src/include/Ota/UpgraderBase.h index ebfbf2781a..880488d7cb 100644 --- a/Sming/Libraries/Ota/src/include/Ota/UpgraderBase.h +++ b/Sming/Libraries/Ota/src/include/Ota/UpgraderBase.h @@ -29,7 +29,7 @@ class UpgraderBase /** * @brief Prepares a partition for an upgrade. - * The preparation is bootloader and architecture dependant. + * The preparation is bootloader and architecture dependent. * @param partition * @param size * @@ -47,7 +47,7 @@ class UpgraderBase virtual size_t write(const uint8_t* buffer, size_t size) = 0; /** - * @brief Finilizes the partition upgrade. + * @brief Finalizes the partition upgrade. */ virtual bool end() = 0; @@ -60,7 +60,7 @@ class UpgraderBase } /** - * @brief Sets the default parition from where the application will be booted on next restart. + * @brief Sets the default partition from where the application will be booted on next restart. * @param partition * @param save if true the change is persisted on the flash, otherwise it will be valid only for the next boot * @@ -69,16 +69,16 @@ class UpgraderBase virtual bool setBootPartition(Partition partition, bool save = true) = 0; /** - * @brief Gets information about the parition that is set as the default one to boot. - * @note The returned parition can be different than the current running partition. + * @brief Gets information about the partition that is set as the default one to boot. + * @note The returned partition can be different than the current running partition. * * @retval partition */ virtual Partition getBootPartition() = 0; /** - * @brief Gets information about the parition from which the current application is running. - * @note The returned parition can be different than the default boot partition. + * @brief Gets information about the partition from which the current application is running. + * @note The returned partition can be different than the default boot partition. * * @retval partition */ diff --git a/Sming/Libraries/OtaNetwork/README.rst b/Sming/Libraries/OtaNetwork/README.rst index 84f479d9cf..23d8670aeb 100644 --- a/Sming/Libraries/OtaNetwork/README.rst +++ b/Sming/Libraries/OtaNetwork/README.rst @@ -10,6 +10,7 @@ This architecture-agnostic component adds support for Over-The-Air upgrades. Usage ----- + 1. Add ``COMPONENT_DEPENDS += Ota`` to your application componenent.mk file. 2. Add these lines to your application:: @@ -32,7 +33,6 @@ After that you will have access to a global ``OtaManager`` instance that can be 4. If needed you can also create your own instance of the of OtaUpgrader as shown below:: - // Call when IP address has been obtained void onIp(IpAddress ip, IpAddress mask, IpAddress gateway) { @@ -51,11 +51,11 @@ After that you will have access to a global ``OtaManager`` instance that can be // ... } -See the :sample:`Upgrade` sample application. +See the :sample:`Basic_Ota` sample application. API Documentation ----------------- -.. doxygennamespace:: Ota +.. doxygennamespace:: Ota::Network :members: diff --git a/Sming/Libraries/OtaNetwork/component.mk b/Sming/Libraries/OtaNetwork/component.mk index 176580747f..a8c004d394 100644 --- a/Sming/Libraries/OtaNetwork/component.mk +++ b/Sming/Libraries/OtaNetwork/component.mk @@ -1,4 +1,4 @@ COMPONENT_SRCDIRS := src COMPONENT_INCDIRS := src/include COMPONENT_DEPENDS := Ota Network - +COMPONENT_DOXYGEN_INPUT := src/include diff --git a/Sming/Libraries/OtaNetwork/src/include/Ota/Network/HttpUpgrader.h b/Sming/Libraries/OtaNetwork/src/include/Ota/Network/HttpUpgrader.h index 40816b6491..9a93aa114f 100644 --- a/Sming/Libraries/OtaNetwork/src/include/Ota/Network/HttpUpgrader.h +++ b/Sming/Libraries/OtaNetwork/src/include/Ota/Network/HttpUpgrader.h @@ -119,15 +119,6 @@ class HttpUpgrader : protected HttpClient baseRequest = request; } - /** - * @brief Allow reading items - * @deprecated Access list directly using `getItems()` - */ - const Item& getItem(unsigned int index) const SMING_DEPRECATED - { - return items[index]; - } - /** * @brief Allow read access to item list */ diff --git a/Sming/Libraries/OtaUpgrade/Kconfig b/Sming/Libraries/OtaUpgrade/Kconfig new file mode 100644 index 0000000000..3dd5c1893c --- /dev/null +++ b/Sming/Libraries/OtaUpgrade/Kconfig @@ -0,0 +1,41 @@ +menu "OTA Upgrade" + + config ENABLE_OTA_SIGNING + bool "Protect upgrade files using digital signature" + default y + help + If enabled (highly recommended), OTA upgrade files are protected against unauthorized modification by a digital signature. + + You may disable signing in order to save some program memory if your communication channel already establishes a + comparable level of trust, e.g. TLS with a pinned certificate. + + config OTA_ENABLE_ENCRYPTION + bool "Encrypt upgrade files" + help + This option helps to protect any confidential data embedded in your firmware, such as WiFi credentials, server certificates, etc. + + config OTA_KEY + string "Path to secret encryption/signing key" + default "ota.key" + + config ENABLE_OTA_DOWNGRADE + bool "Enable downgrade" + help + By default, BasicStream refuses to downgrade to an older firmware version to prevent an attacker from restoring already patched security vulnerabilities. + + Downgrade protection must be combined with encryption or signing to be effective. + + config OTA_UPLOAD_URL + string "URL used by the `make ota-upload` command" + + + config OTA_UPLOAD_NAME + string "Field name for upgrade file in HTTP POST request" + default "firmware" + help + This relates to the `name` attribute of the HTML input element + used with the `make ota-upload` command: + + + +endmenu diff --git a/Sming/Libraries/OtaUpgrade/OtaUpgrade/BasicStream.cpp b/Sming/Libraries/OtaUpgrade/OtaUpgrade/BasicStream.cpp index 451936f54f..094b0f3c00 100644 --- a/Sming/Libraries/OtaUpgrade/OtaUpgrade/BasicStream.cpp +++ b/Sming/Libraries/OtaUpgrade/OtaUpgrade/BasicStream.cpp @@ -12,6 +12,7 @@ #include #include #include +#include extern "C" uint32 user_rf_cal_sector_set(void); @@ -23,10 +24,9 @@ extern const uint64_t BuildTimestamp; DECLARE_FSTR_ARRAY(AppFlashRegionOffsets, uint32_t); -BasicStream::Slot::Slot() +// Lookup slot details from partition table +BasicStream::Slot::Slot() : partition(OtaManager.getNextBootPartition()) { - // Lookup slot details from partition table - partition = OtaManager.getNextBootPartition(); } BasicStream::BasicStream() @@ -201,11 +201,6 @@ size_t BasicStream::write(const uint8_t* data, size_t size) return origSize - size; } -String BasicStream::errorToString(Error code) -{ - return toString(code); -} - } // namespace OtaUpgrade String toString(OtaUpgrade::BasicStream::Error code) diff --git a/Sming/Libraries/OtaUpgrade/OtaUpgrade/BasicStream.h b/Sming/Libraries/OtaUpgrade/OtaUpgrade/BasicStream.h index aaa96251bc..880fad0653 100644 --- a/Sming/Libraries/OtaUpgrade/OtaUpgrade/BasicStream.h +++ b/Sming/Libraries/OtaUpgrade/OtaUpgrade/BasicStream.h @@ -50,7 +50,7 @@ class BasicStream : public ReadWriteStream * @brief Error code values */ enum class Error { - None, ///< No error occured thus far (default value of \c #errorCode if `hasError()` returns false) + None, ///< No error occurred thus far (default value of \c #errorCode if `hasError()` returns false) InvalidFormat, ///< Invalid/unsupported upgrade file format UnsupportedData, ///< Some content of the upgrade file is not supported by this version of OtaUpgradeStream. DecryptionFailed, ///< Decryption failed. Probably wrong decryption key. @@ -61,21 +61,15 @@ class BasicStream : public ReadWriteStream FlashWriteFailed, ///< Error while writing to Flash memory. RomActivationFailed, ///< Error while activating updated ROM slot. OutOfMemory, ///< Dynamic memory allocation failed - Internal, ///< An unexpected error occured. + Internal, ///< An unexpected error occurred. }; Error errorCode = Error::None; ///< Error code. Only relevant if `hasError()` returns `true`. - /** @brief Convert error code to string. - * @see #errorCode - * @deprecated Use `toString()` global function - */ - static String errorToString(Error code) SMING_DEPRECATED; - /** @brief Process chunk of upgrade file. * @param data Pointer to chunk of data. * @param size Size of chunk pointed to by \a data in bytes. - * @return If less than \a size, an error occured. Check \c #errorCode for more details. + * @return If less than \a size, an error occurred. Check \c #errorCode for more details. * @note Even if `write()` never returns less than \a size it is not guaranteed that the upgrade was successful. * Always use `hasError()` to determine success. */ diff --git a/Sming/Libraries/OtaUpgrade/OtaUpgrade/EncryptedStream.h b/Sming/Libraries/OtaUpgrade/OtaUpgrade/EncryptedStream.h index eec39954c6..239c463bc8 100644 --- a/Sming/Libraries/OtaUpgrade/OtaUpgrade/EncryptedStream.h +++ b/Sming/Libraries/OtaUpgrade/OtaUpgrade/EncryptedStream.h @@ -22,7 +22,7 @@ namespace OtaUpgrade * The class processes encrypted firmware upgrade files created by otatool.py. * A buffer is allocated dynamically to fit the largest chunk of the encryption container * (2kB unless otatool.py was modified). The actual processing of the decrypted data is - * defered to #BasicStream. + * deferred to #BasicStream. */ class EncryptedStream : public BasicStream { @@ -32,7 +32,7 @@ class EncryptedStream : public BasicStream /** @brief Process an arbitrarily sized chunk of an encrypted OTA upgrade file. * @param data Pointer to chunk of data. * @param size Size of chunk pointed to by \a data in bytes. - * @return If less than \a size, an error occured. Check \link BasicStream::errorCode \c errorCode \endlink for more details. + * @return If less than \a size, an error occurred. Check \link BasicStream::errorCode \c errorCode \endlink for more details. * @note \a size does not have to match the chunk size used by otatool.py */ size_t write(const uint8_t* data, size_t size) override; diff --git a/Sming/Libraries/OtaUpgrade/OtaUpgrade/FileFormat.h b/Sming/Libraries/OtaUpgrade/OtaUpgrade/FileFormat.h index 2ba6ff1652..4082a42a9d 100644 --- a/Sming/Libraries/OtaUpgrade/OtaUpgrade/FileFormat.h +++ b/Sming/Libraries/OtaUpgrade/OtaUpgrade/FileFormat.h @@ -25,7 +25,7 @@ struct OtaFileHeader { uint32_t magic; ///< File type identification, either #OTA_HEADER_MAGIC_SIGNED or #OTA_HEADER_MAGIC_NOT_SIGNED. uint32_t buildTimestampLow; ///< File creation timestamp, Milliseconds since 1900/01/01 (lower 32 bits) uint32_t buildTimestampHigh; ///< File creation timestamp, Milliseconds since 1900/01/01 (lower 32 bits) - uint8_t romCount; ///< Number of ROM images in this filem, each preceeded with an #OTA_RomHeader. + uint8_t romCount; ///< Number of ROM images in this filem, each preceded with an #OTA_RomHeader. uint8_t reserved[3]; ///< Reserved bytes, must be zero for compatibility with future versions. }; diff --git a/Sming/Libraries/OtaUpgradeMqtt/Kconfig b/Sming/Libraries/OtaUpgradeMqtt/Kconfig new file mode 100644 index 0000000000..6137787c00 --- /dev/null +++ b/Sming/Libraries/OtaUpgradeMqtt/Kconfig @@ -0,0 +1,20 @@ +menu "OTA Upgrade MQTT" + + config ENABLE_OTA_VARINT_VERSION + bool "Enable 'varint' encoding for patch version" + default y + help + If enabled, the OTA upgrade mechanism and application will use a `varint `_ + encoding for the patch version. Thus allowing unlimited number of patch versions. Useful for enumerating unstable/nightly releases. + A bit more difficult to read and write but allows for unlimited versions. + + If disabled, the OTA upgrade mechanism and application will use one byte for the patch version which will limit it to 256 possible patch versions. + Useful for enumerating stable releases. Easier to write and read but limited to 256 versions only. + + config ENABLE_OTA_ADVANCED + bool "Support firmware signing/encryption" + help + Enabling this option allows the library to work with OtaUpgradeStream which supports signature and encryption of the firmware data itself. + In the application the AdvancedPayloadParser can be used to do the MQTT message handling. + +endmenu diff --git a/Sming/Libraries/OtaUpgradeMqtt/README.rst b/Sming/Libraries/OtaUpgradeMqtt/README.rst index 3756a75401..5826275f48 100644 --- a/Sming/Libraries/OtaUpgradeMqtt/README.rst +++ b/Sming/Libraries/OtaUpgradeMqtt/README.rst @@ -144,7 +144,7 @@ Configuration A bit more difficult to read and write but allows for unlimited versions. If set to 0 the OTA upgrade mechanism and application will use one byte for the patch version which will limit it to 256 possible patch versions. - Useful for enumarating stable releases. Easier to write and read but limited to 256 versions only. + Useful for enumerating stable releases. Easier to write and read but limited to 256 versions only. .. envvar:: ENABLE_OTA_ADVANCED @@ -153,3 +153,10 @@ Configuration If set to 1 the library will work with OtaUpgradeStream which supports signature and encryption of the firmware data itself. See :library:`OtaUpgrade` for details. In the application the AdvancedPayloadParser can be used to do the MQTT message handling. + +API +--- + +.. toctree:: + + api diff --git a/Sming/Libraries/OtaUpgradeMqtt/api.rst b/Sming/Libraries/OtaUpgradeMqtt/api.rst index e9aca95651..4aad05020c 100644 --- a/Sming/Libraries/OtaUpgradeMqtt/api.rst +++ b/Sming/Libraries/OtaUpgradeMqtt/api.rst @@ -1,8 +1,5 @@ -OTA Upgrade over MQTT classes -============================= +API Documentation +================= -.. doxygentypedef:: OtaUpgrade::Mqtt - -.. doxygenclass:: OtaUpgrade::Mqtt::PayloadParser -.. doxygenclass:: OtaUpgrade::Mqtt::RbootPayloadParser -.. doxygenclass:: OtaUpgrade::Mqtt::AdvancedPayloadParser +.. doxygennamespace:: OtaUpgrade::Mqtt + :members: diff --git a/Sming/Libraries/OtaUpgradeMqtt/component.mk b/Sming/Libraries/OtaUpgradeMqtt/component.mk index 505288b2af..f77bc9e505 100644 --- a/Sming/Libraries/OtaUpgradeMqtt/component.mk +++ b/Sming/Libraries/OtaUpgradeMqtt/component.mk @@ -1,8 +1,9 @@ COMPONENT_SRCDIRS := COMPONENT_SRCFILES := src/PayloadParser.cpp src/StandardPayloadParser.cpp COMPONENT_INCDIRS := src/include +COMPONENT_DOXYGEN_INPUT := src/include -# If enabled (set to 1) then we can use all sofisticated mechanisms to upgrade the firmware using the ``OtaUpgrade`` library. +# If enabled (set to 1) then we can use all sophisticated mechanisms to upgrade the firmware using the ``OtaUpgrade`` library. COMPONENT_VARS := ENABLE_OTA_ADVANCED ENABLE_OTA_ADVANCED ?= 0 @@ -28,7 +29,7 @@ $(OTA_DEPLOYMENT_TOOL): $(Q) $(MAKE) -C $(OTA_TOOLS)/deployer SMING_ARCH=Host ENABLE_CUSTOM_LWIP=2 -# SDP = Sming Deployment Pakage +# SDP = Sming Deployment Package OTA_PACKAGE_EXT =.sdp OTA_PATCH_VERSION ?= $(shell date +%s) diff --git a/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/README.rst b/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/README.rst index b0126b3b18..c90377cf8c 100644 --- a/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/README.rst +++ b/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/README.rst @@ -19,7 +19,7 @@ For more information read ``Firmware packaging`` in the documentation of the :li Security -------- -Depending on :envvar:`ENABLE_SSL` a standard SSL/TLS can be enabled. This way +Depending on :envvar:`ENABLE_SSL` a standard SSL/TLS can be enabled: 1. The communication between the application and the server will be encrypted using standard SSL. @@ -31,6 +31,8 @@ Depending on :envvar:`ENABLE_SSL` a standard SSL/TLS can be enabled. This way Configuration ------------- +If :envvar:`ENABLE_SSL` is enabled (highly recommended), OTA upgrade files will be transferred securely over TLS/SSL. + .. envvar:: APP_ID Default: "test" @@ -51,38 +53,15 @@ Configuration Contains the application patch version as integer. For stable versions you can use 0 until 255. For unstable versions the current timestamp can be used as a patch version. -.. envvar:: ENABLE_OTA_VARINT_VERSION - - Default: 1 (enabled) - - If set to 1 the OTA upgrade mechanism and application will use a `varint `_ - encoding for the patch version. Thus allowing unlimited number of patch versions. Useful for enumerating unstable/nightly releases. - A bit more difficult to read and write but allows for unlimited versions. - - If set to 0 the OTA upgrade mechanism and application will use one byte for the patch version which will limit it to 256 possible patch versions. - Useful for enumarating stable releases. Easier to write and read but limited to 256 versions only. - -.. envvar:: ENABLE_OTA_ADVANCED - - Default: 0 (disabled) - - If set to 1 the library will work with OtaUpgradeStream which supports signature and encryption of the firmware data itself. - See :library:`OtaUpgrade` for details. - -.. envvar:: ENABLE_SSL - - Default: unset (disable) - - If set to 1 (highly recommended), OTA upgrade files will be trasnferred securely over TLS/SSL. - .. envvar:: ENABLE_CLIENT_CERTIFICATE Default: 0 (disabled) - Used in combination with ``ENABLE_SSL``. Set to 1 if the remote server requires the application to authenticate via client certficate. + Used in combination with ``ENABLE_SSL``. Set to 1 if the remote server requires the application to authenticate via client certificate. .. envvar:: MQTT_URL Default: depends on ``ENABLE_SSL`` and ``ENABLE_CLIENT_CERTIFICATE`` values Url containing the location of the firmware update MQTT server. + diff --git a/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/app/application.cpp b/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/app/application.cpp index 37f8125182..516616749d 100644 --- a/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/app/application.cpp +++ b/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/app/application.cpp @@ -99,9 +99,8 @@ void showInfo() int total = 0; for(auto it = OtaManager.getBootPartitions(); it; ++it) { - auto part = *it; - debug_d("ROM %s: 0x%08x, SubType: %s", part.name().c_str(), part.address(), - toLongString(part.type(), part.subType()).c_str()); + debug_d("ROM %s: 0x%08x, SubType: %s", it->name().c_str(), it->address(), + toLongString(it->type(), it->subType()).c_str()); total++; } debug_d("======================="); @@ -117,7 +116,7 @@ void showInfo() void connectOk(IpAddress ip, IpAddress mask, IpAddress gateway) { /* - This application starts the update right after a successful connecton. + This application starts the update right after a successful connection. In a real-world application you should start the update procedure only when the chances of success are high enough. diff --git a/Sming/Libraries/OtaUpgradeMqtt/src/PayloadParser.cpp b/Sming/Libraries/OtaUpgradeMqtt/src/PayloadParser.cpp index 56f39ab4e3..34b695b76b 100644 --- a/Sming/Libraries/OtaUpgradeMqtt/src/PayloadParser.cpp +++ b/Sming/Libraries/OtaUpgradeMqtt/src/PayloadParser.cpp @@ -40,7 +40,7 @@ int PayloadParser::parse(MqttPayloadParserState& state, mqtt_message_t* message, bool success = switchRom(*updateState); if(success) { debug_d("Switching was successful. Restarting..."); - System.restart(); + System.restart(1000); } else { debug_e("Switching failed!"); } diff --git a/Sming/Libraries/OtaUpgradeMqtt/src/StandardPayloadParser.cpp b/Sming/Libraries/OtaUpgradeMqtt/src/StandardPayloadParser.cpp index f312423442..2ac2cf3fdb 100644 --- a/Sming/Libraries/OtaUpgradeMqtt/src/StandardPayloadParser.cpp +++ b/Sming/Libraries/OtaUpgradeMqtt/src/StandardPayloadParser.cpp @@ -20,11 +20,12 @@ namespace Mqtt { bool StandardPayloadParser::switchRom(const UpdateState& updateState) { - auto before = OtaManager.getBootPartition(); auto after = OtaManager.getNextBootPartition(); - +#if DEBUG_VERBOSE_LEVEL >= DBG + auto before = OtaManager.getBootPartition(); debug_d("Swapping from %s @ 0x%08x to %s @ 0x%08x.\r\n", before.name().c_str(), before.address(), after.name().c_str(), after.address()); +#endif return OtaManager.setBootPartition(after); } diff --git a/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/.cproject b/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/.cproject deleted file mode 100644 index fecee42f2f..0000000000 --- a/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/.cproject +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - - all - true - true - true - - - make - - rebuild - true - true - true - - - make - - flash - true - true - true - - - - diff --git a/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/.project b/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/.project deleted file mode 100644 index 0b94d5c588..0000000000 --- a/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/.project +++ /dev/null @@ -1,30 +0,0 @@ - - - FirmwareDeployer - - - SmingFramework - Libraries - Sming - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/app/application.cpp b/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/app/application.cpp index f3a513af69..aa55f83fc2 100644 --- a/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/app/application.cpp +++ b/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/app/application.cpp @@ -89,7 +89,7 @@ bool pack(const String& inputFileName, const String& outputFileName, size_t patc } HostFileStream output; - if(!output.open(outputFileName, eFO_CreateNewAlways | eFO_WriteOnly)) { + if(!output.open(outputFileName, File::CreateNewAlways | File::WriteOnly)) { fileError(output, outputFileName, F("open output")); return false; } @@ -124,7 +124,10 @@ bool deploy(const String& outputFileName, const String& url) WifiEvents.onStationGotIP([url, output](IpAddress ip, IpAddress netmask, IpAddress gateway) { Url mqttUrl(url); - mqtt.connect(mqttUrl, "sming"); + mqtt.setCompleteDelegate([](TcpClient& client, bool successful) { + debug_d("Deployer completed: %d", successful); + System.restart(1000); + }); mqtt.setConnectedHandler([mqttUrl, output](MqttClient& client, mqtt_message_t* message) -> int { if(message == nullptr) { // invalid message received @@ -150,6 +153,11 @@ bool deploy(const String& outputFileName, const String& url) return 0; }); + + if(!mqtt.connect(mqttUrl, "sming")) { + System.restart(1000); + return; + } }); return true; @@ -219,7 +227,7 @@ bool parseCommands() return false; // after packaging the application can be terminated } } else if(cmd == "deploy") { - if(checkParameterCount(2, 2)) { + if(checkParameterCount(3, 3)) { return deploy(parameters[1].text, parameters[2].text); } } else { diff --git a/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/component.mk b/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/component.mk index 3069b10758..e9fa43f7ab 100644 --- a/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/component.mk +++ b/Sming/Libraries/OtaUpgradeMqtt/tools/deployer/component.mk @@ -1,7 +1,9 @@ +COMPONENT_SOC := host COMPONENT_DEPENDS := OtaUpgradeMqtt APP_NAME := deployer SMING_ARCH := Host +ENABLE_SSL := Bearssl ##@Firmware Upgrade diff --git a/Sming/Libraries/RCSwitch/RCSwitch.cpp b/Sming/Libraries/RCSwitch/RCSwitch.cpp index 7a1366d9c1..9d45f74de4 100644 --- a/Sming/Libraries/RCSwitch/RCSwitch.cpp +++ b/Sming/Libraries/RCSwitch/RCSwitch.cpp @@ -1,5 +1,5 @@ /* - RCSwitch - Arduino libary for remote control outlet switches + RCSwitch - Arduino library for remote control outlet switches Copyright (c) 2011 Suat Özgür. All right reserved. Contributors: @@ -31,8 +31,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include -//#include #include "RCSwitch.h" /* Format for protocol definitions: @@ -673,7 +671,7 @@ static IRAM_ATTR __forceinline unsigned int diff(int A, int B) { bool RCSwitch::receiveProtocol(const int p, unsigned int changeCount) { Protocol pro; - ets_memcpy(&pro, &proto[p-1], sizeof(Protocol)); + memcpy(&pro, &proto[p-1], sizeof(Protocol)); unsigned long code = 0; const unsigned int delay = RCSwitch::timings[0] / pro.syncFactor.low; diff --git a/Sming/Libraries/RCSwitch/RCSwitch.h b/Sming/Libraries/RCSwitch/RCSwitch.h index 702c24e854..3c2d44498c 100644 --- a/Sming/Libraries/RCSwitch/RCSwitch.h +++ b/Sming/Libraries/RCSwitch/RCSwitch.h @@ -1,5 +1,5 @@ /* - RCSwitch - Arduino libary for remote control outlet switches + RCSwitch - Arduino library for remote control outlet switches Copyright (c) 2011 Suat Özgür. All right reserved. Contributors: @@ -64,7 +64,7 @@ // At least for the ATTiny X4/X5, receiving has to be disabled due to -// missing libm depencies (udivmodhi4) +// missing libm dependencies (udivmodhi4) #if defined( __AVR_ATtinyX5__ ) or defined ( __AVR_ATtinyX4__ ) #define RCSwitchDisableReceiving #endif diff --git a/Sming/Libraries/RCSwitch/README.md b/Sming/Libraries/RCSwitch/README.md index c839711ad5..c267c3098e 100644 --- a/Sming/Libraries/RCSwitch/README.md +++ b/Sming/Libraries/RCSwitch/README.md @@ -30,7 +30,7 @@ or more devices with one of the supported chipsets: Find out what codes your remote is sending. Use your remote to control your Arduino. -All you need is an Arduino, a 315/433MHz AM receiver (altough there is no +All you need is an Arduino, a 315/433MHz AM receiver (although there is no instruction yet, yes it is possible to hack an existing device) and a remote hand set. diff --git a/Sming/Libraries/RF24/Doxyfile b/Sming/Libraries/RF24/Doxyfile index 4604afcc57..50ffce48bd 100644 --- a/Sming/Libraries/RF24/Doxyfile +++ b/Sming/Libraries/RF24/Doxyfile @@ -278,10 +278,10 @@ TYPEDEF_HIDES_STRUCT = NO # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penality. +# causing a significant performance penalty. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will rougly double the +# a logarithmic scale so increasing the size by one will roughly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols diff --git a/Sming/Libraries/RF24/README.md b/Sming/Libraries/RF24/README.md index c0e71c092e..8aa3beae5f 100644 --- a/Sming/Libraries/RF24/README.md +++ b/Sming/Libraries/RF24/README.md @@ -4,7 +4,7 @@ Design Goals: This library is designed to be... * Maximally compliant with the intended operation of the chip * Easy for beginners to use -* Consumed with a public interface that's similiar to other Arduino standard libraries +* Consumed with a public interface that's similar to other Arduino standard libraries * Built against the standard SPI library. Please refer to: diff --git a/Sming/Libraries/RF24/RF24.cpp b/Sming/Libraries/RF24/RF24.cpp index 6115fd290a..215443fb36 100644 --- a/Sming/Libraries/RF24/RF24.cpp +++ b/Sming/Libraries/RF24/RF24.cpp @@ -394,7 +394,7 @@ void RF24::startListening(void) write_register(CONFIG, read_register(CONFIG) | _BV(PWR_UP) | _BV(PRIM_RX)); write_register(REG_STATUS, _BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); - // Restore the pipe0 adddress, if exists + // Restore the pipe0 address, if exists if (pipe0_reading_address) write_register(RX_ADDR_P0, reinterpret_cast(&pipe0_reading_address), 5); diff --git a/Sming/Libraries/RF24/RF24.h b/Sming/Libraries/RF24/RF24.h index 3d9ff70f0e..1d9f571fc9 100644 --- a/Sming/Libraries/RF24/RF24.h +++ b/Sming/Libraries/RF24/RF24.h @@ -763,7 +763,7 @@ class RF24 * This library is designed to be... * @li Maximally compliant with the intended operation of the chip * @li Easy for beginners to use - * @li Consumed with a public interface that's similiar to other Arduino standard libraries + * @li Consumed with a public interface that's similar to other Arduino standard libraries * * @section News News * diff --git a/Sming/Libraries/RapidXML b/Sming/Libraries/RapidXML index cab0af2fda..4a1fe56b85 160000 --- a/Sming/Libraries/RapidXML +++ b/Sming/Libraries/RapidXML @@ -1 +1 @@ -Subproject commit cab0af2fda5d52a365502750db6e6bd01f585053 +Subproject commit 4a1fe56b851fef63b99a1433c743e5ca0043b08d diff --git a/Sming/Libraries/RingBufCPP b/Sming/Libraries/RingBufCPP index 9e091e9632..7aa253e2f2 160000 --- a/Sming/Libraries/RingBufCPP +++ b/Sming/Libraries/RingBufCPP @@ -1 +1 @@ -Subproject commit 9e091e9632bc3eba513f422ee7cb17895c565a1a +Subproject commit 7aa253e2f23a4be6c903ed94f209ce40ef7bfe4d diff --git a/Sming/Libraries/RingTone b/Sming/Libraries/RingTone index 56bdf070f7..27abfdae6e 160000 --- a/Sming/Libraries/RingTone +++ b/Sming/Libraries/RingTone @@ -1 +1 @@ -Subproject commit 56bdf070f7e4eebebe15646079aa709af10e248c +Subproject commit 27abfdae6ea684646be347cbfbf757d9882cc0bb diff --git a/Sming/Libraries/SDCard/SDCard.cpp b/Sming/Libraries/SDCard/SDCard.cpp index 885d00f4da..05f0d3952b 100644 --- a/Sming/Libraries/SDCard/SDCard.cpp +++ b/Sming/Libraries/SDCard/SDCard.cpp @@ -33,7 +33,6 @@ Descr: Low-level SDCard functions /-------------------------------------------------------------------------*/ #include "SDCard.h" -#include "fatfs/ff.h" #include "fatfs/diskio.h" /* Declarations of disk I/O functions */ #include #include @@ -71,7 +70,7 @@ bool SDCard_begin(uint8_t slaveSelect, uint32_t freqLimit) } // Note: Some SD cards struggle at 40MHz - settings.speed = std::min(freqLimit, 40000000U); + settings.speed = std::min(freqLimit, uint32_t(40000000)); if(!SDCardSPI->begin()) { debug_e("SDCard SPI init failed"); diff --git a/Sming/Libraries/SDCard/SDCard.h b/Sming/Libraries/SDCard/SDCard.h index aff11003d8..9acba19894 100644 --- a/Sming/Libraries/SDCard/SDCard.h +++ b/Sming/Libraries/SDCard/SDCard.h @@ -8,9 +8,11 @@ Descr: Low-level SDCard functions #pragma once #include +#include + /** - * @brief Intialise SD card interface + * @brief Initialise SD card interface * @param slaveSelect Pin to use for CS * @param freqLimit Maximum SPI clock speed * @retval bool true on success, false on error diff --git a/Sming/Libraries/SDCard/component.mk b/Sming/Libraries/SDCard/component.mk new file mode 100644 index 0000000000..5397d0b008 --- /dev/null +++ b/Sming/Libraries/SDCard/component.mk @@ -0,0 +1 @@ +COMPONENT_DEPENDS := fatfs diff --git a/Sming/Libraries/SI7021/SI7021.cpp b/Sming/Libraries/SI7021/SI7021.cpp index c1f5e3bd44..ce3889dd05 100644 --- a/Sming/Libraries/SI7021/SI7021.cpp +++ b/Sming/Libraries/SI7021/SI7021.cpp @@ -170,12 +170,12 @@ struct si7021_env SI7021::getHumidityAndTemperature() { // get temperature only struct si7021_olt SI7021::getTemperatureOlt() { - si7021_olt olt = {0, 0}; - olt.temperature = getTemperature(); - olt.error_crc = 0; - if (olt.temperature == 99998){ - olt.error_crc = 1; + si7021_olt old = {0, 0}; + old.temperature = getTemperature(); + old.error_crc = 0; + if (old.temperature == 99998){ + old.error_crc = 1; } - return olt; + return old; } diff --git a/Sming/Libraries/SSDP b/Sming/Libraries/SSDP index 835b7f68e3..a864d47dc7 160000 --- a/Sming/Libraries/SSDP +++ b/Sming/Libraries/SSDP @@ -1 +1 @@ -Subproject commit 835b7f68e33e6f809c0d8b66d98b7aa2b1ef7988 +Subproject commit a864d47dc7a554e451ce3abe458285ec64a68ecf diff --git a/Sming/Libraries/Servo/README.rst b/Sming/Libraries/Servo/README.rst index 0931f14eae..28b473f4a4 100644 --- a/Sming/Libraries/Servo/README.rst +++ b/Sming/Libraries/Servo/README.rst @@ -52,7 +52,7 @@ Servos typically use a 5V logic-level input but are usually fine with the 3.3v o However, remember to always insert a protection resistor of at least 200 ohms between the GPIO and the servo. This limits the current to <10mA if 5V is present on the line. - For 12V servos a 1K resistor will peform the same function. + For 12V servos a 1K resistor will perform the same function. Technical Explanation diff --git a/Sming/Libraries/SmingTest b/Sming/Libraries/SmingTest index 29ca79605d..1a25cc1ea7 160000 --- a/Sming/Libraries/SmingTest +++ b/Sming/Libraries/SmingTest @@ -1 +1 @@ -Subproject commit 29ca79605d2ec29c06c71ce23583ee74fc16e879 +Subproject commit 1a25cc1ea71b68139fbccbd4e66afc5db8b89846 diff --git a/Sming/Libraries/SolarCalculator b/Sming/Libraries/SolarCalculator index 92dcf47b7a..942afd61d6 160000 --- a/Sming/Libraries/SolarCalculator +++ b/Sming/Libraries/SolarCalculator @@ -1 +1 @@ -Subproject commit 92dcf47b7a1d03acdf58871867cd553e4c6de678 +Subproject commit 942afd61d6ad7da40c03bca691b108fe0eedec32 diff --git a/Sming/Libraries/Spiffs/Kconfig b/Sming/Libraries/Spiffs/Kconfig new file mode 100644 index 0000000000..7aa6d949fe --- /dev/null +++ b/Sming/Libraries/Spiffs/Kconfig @@ -0,0 +1,30 @@ +menu "SPIFFS" + config SPIFF_FILEDESC_COUNT + int "Number of file descriptors allocated" + default 7 + help + This sets the maximum number of files which may be opened at once. + + config SPIFFS_OBJ_META_LEN + int "Maximum size of file metadata" + default 16 + help + Maximum size of metadata which SPIFFS stores in each file index header (after the filename). + If this value is changed, existing SPIFFS images will not be readable. + + The default value is the minimum necessary to support IFS extended file attribute information. + + The first 16 bytes are used for system attributes (e.g. modified time), so setting this to, say, 64 + leaves 48 bytes for user metadata. Each attribute has a 2-byte header (tag + size) so a single user + attribute can be stored of up to 46 bytes, or multiple tags up to this limit. + + Note: LittleFS provides better support for user metadata. + + config SPIFF_FILES + string "Path to source files for default spiffs volume" + default "files" + help + The SPIFFS image is built using files from this directory, which must exist or the build will fail. + If you set this to an empty value, then an empty filesystem will be created. + +endmenu diff --git a/Sming/Libraries/Spiffs/README.rst b/Sming/Libraries/Spiffs/README.rst index 4e50a7c99d..ef7ed673a1 100644 --- a/Sming/Libraries/Spiffs/README.rst +++ b/Sming/Libraries/Spiffs/README.rst @@ -18,8 +18,6 @@ A single SPIFFS partition is defined using :envvar:`HWCONFIG` ``=spiffs``, which Size (in bytes) of the SPIFFS area in Flash memory. To change this, edit the :ref:`hardware_config`. - .. envvar:: SPIFF_FILES - .. envvar:: SPIFF_FILES default: ``files`` diff --git a/Sming/Libraries/Spiffs/component.mk b/Sming/Libraries/Spiffs/component.mk index 946794670c..a482d6ff1f 100644 --- a/Sming/Libraries/Spiffs/component.mk +++ b/Sming/Libraries/Spiffs/component.mk @@ -19,7 +19,7 @@ SPIFF_BIN_OUT := $(FW_BASE)/$(SPIFF_BIN).bin COMPONENT_RELINK_VARS += SPIFF_FILEDESC_COUNT SPIFF_FILEDESC_COUNT ?= 7 -COMPONENT_CFLAGS += -DSPIFF_FILEDESC_COUNT=$(SPIFF_FILEDESC_COUNT) +COMPONENT_CXXFLAGS += -DSPIFF_FILEDESC_COUNT=$(SPIFF_FILEDESC_COUNT) COMPONENT_CFLAGS += -Wno-tautological-compare diff --git a/Sming/Libraries/Spiffs/spiffsgen.py b/Sming/Libraries/Spiffs/spiffsgen.py index 0ca153dcca..46ecb5944e 100644 --- a/Sming/Libraries/Spiffs/spiffsgen.py +++ b/Sming/Libraries/Spiffs/spiffsgen.py @@ -210,7 +210,7 @@ def to_binary(self): # Add padding before the object index page specific information img += b'\xFF' * self.build_config.OBJ_DATA_PAGE_HEADER_LEN_ALIGNED_PAD - # If this is the first object index page for the object, add filname, type + # If this is the first object index page for the object, add filename, type # and size information if self.span_ix == 0: img += struct.pack(SpiffsPage._endianness_dict[self.build_config.endianness] + diff --git a/Sming/Libraries/Spiffs/src/Error.cpp b/Sming/Libraries/Spiffs/src/Error.cpp index 395957b744..494c24a335 100644 --- a/Sming/Libraries/Spiffs/src/Error.cpp +++ b/Sming/Libraries/Spiffs/src/Error.cpp @@ -28,7 +28,7 @@ namespace IFS namespace SPIFFS { /* - * @todo Return generic FSERR codes whereever possible by mapping from SPIFFS codes + * @todo Return generic FSERR codes wherever possible by mapping from SPIFFS codes */ #define SPIFFS_ERROR_MAP(XX) \ diff --git a/Sming/Libraries/Spiffs/src/FileMeta.cpp b/Sming/Libraries/Spiffs/src/FileMeta.cpp index f603a8f27d..e7ea32dbe7 100644 --- a/Sming/Libraries/Spiffs/src/FileMeta.cpp +++ b/Sming/Libraries/Spiffs/src/FileMeta.cpp @@ -64,6 +64,7 @@ int SpiffsMetaBuffer::enumxattr(AttributeEnumCallback callback, void* buffer, si } } +#if SPIFFS_USER_METALEN for(unsigned i = 0; i < SPIFFS_USER_METALEN;) { uint8_t tagIndex = user[i++]; uint8_t tagSize = user[i++]; @@ -76,6 +77,7 @@ int SpiffsMetaBuffer::enumxattr(AttributeEnumCallback callback, void* buffer, si } i += tagSize; } +#endif return count; } diff --git a/Sming/Libraries/Spiffs/src/FileSystem.cpp b/Sming/Libraries/Spiffs/src/FileSystem.cpp index 710a3adab6..c17b14cfb2 100644 --- a/Sming/Libraries/Spiffs/src/FileSystem.cpp +++ b/Sming/Libraries/Spiffs/src/FileSystem.cpp @@ -409,7 +409,7 @@ SpiffsMetaBuffer* FileSystem::initMetaBuffer(FileHandle file) SpiffsMetaBuffer* FileSystem::getMetaBuffer(FileHandle file) { unsigned off = SPIFFS_FH_UNOFFS(handle(), file) - 1; - if(off >= FFS_MAX_FILEDESC) { + if(off >= SPIFF_FILEDESC_COUNT) { debug_e("getMetaBuffer(%d) - bad file", file); return nullptr; } diff --git a/Sming/Libraries/Spiffs/src/include/IFS/SPIFFS/FileSystem.h b/Sming/Libraries/Spiffs/src/include/IFS/SPIFFS/FileSystem.h index be59da5e25..ed9279218e 100644 --- a/Sming/Libraries/Spiffs/src/include/IFS/SPIFFS/FileSystem.h +++ b/Sming/Libraries/Spiffs/src/include/IFS/SPIFFS/FileSystem.h @@ -48,11 +48,6 @@ extern "C" { #include "../../../../spiffs/src/spiffs_nucleus.h" } -/* - * Maxmimum number of open files - */ -#define FFS_MAX_FILEDESC 8 - namespace IFS { namespace SPIFFS @@ -139,10 +134,10 @@ class FileSystem : public IFileSystem Storage::Partition partition; IProfiler* profiler{nullptr}; - SpiffsMetaBuffer metaCache[FFS_MAX_FILEDESC]; + SpiffsMetaBuffer metaCache[SPIFF_FILEDESC_COUNT]; spiffs fs; uint16_t workBuffer[LOG_PAGE_SIZE]; - spiffs_fd fileDescriptors[FFS_MAX_FILEDESC]; + spiffs_fd fileDescriptors[SPIFF_FILEDESC_COUNT]; uint8_t cache[CACHE_SIZE]; }; diff --git a/Sming/Libraries/Spiffs/src/include/spiffs_config.h b/Sming/Libraries/Spiffs/src/include/spiffs_config.h index f72525e495..18771a6799 100644 --- a/Sming/Libraries/Spiffs/src/include/spiffs_config.h +++ b/Sming/Libraries/Spiffs/src/include/spiffs_config.h @@ -9,7 +9,8 @@ #define SPIFFS_CONFIG_H_ // ----------- 8< ------------ -#include +#include +#include // ----------- >8 ------------ // compile time switches @@ -294,14 +295,12 @@ // the logical block size (log_block_size), and the logical page size // (log_page_size) -#ifdef ARCH_HOST typedef uint8_t u8_t; typedef int8_t s8_t; typedef uint16_t u16_t; typedef int16_t s16_t; typedef uint32_t u32_t; typedef int32_t s32_t; -#endif // Block index type. Make sure the size of this type can hold // the highest number of all blocks - i.e. spiffs_file_system_size / log_block_size diff --git a/Sming/Libraries/TFT_ILI9163C/README.md b/Sming/Libraries/TFT_ILI9163C/README.md index 7461e4ec82..a1f08ec0aa 100644 --- a/Sming/Libraries/TFT_ILI9163C/README.md +++ b/Sming/Libraries/TFT_ILI9163C/README.md @@ -12,7 +12,7 @@ https://www.youtube.com/watch?v=y5f-VNBxgEk&feature=youtu.be Features: - - Very FAST!, expecially with Teensy 3.x where uses DMA SPI. + - Very FAST!, especially with Teensy 3.x where uses DMA SPI. - It uses just 4 or 5 wires. - Compatible at command level with Adafruit display series so it's easy to adapt existing code. - It uses the standard Adafruit_GFX Library (you need to install). @@ -36,7 +36,7 @@ Pay Attention to connections!!!!: Background: - I got one of those displays from a chinese ebay seller but unfortunatly I cannot get + I got one of those displays from a chinese ebay seller but unfortunately I cannot get any working library so I decided to hack it. ILI9163C looks pretty similar to other display driver but it uses it's own commands so it's tricky to work with it unlsess you carefully fight with his gigantic and not so clever datasheet. diff --git a/Sming/Libraries/TFT_ILI9163C/TFT_ILI9163C.h b/Sming/Libraries/TFT_ILI9163C/TFT_ILI9163C.h index 3c6add2700..ae1ecf22c6 100644 --- a/Sming/Libraries/TFT_ILI9163C/TFT_ILI9163C.h +++ b/Sming/Libraries/TFT_ILI9163C/TFT_ILI9163C.h @@ -2,13 +2,13 @@ ILI9163C - A fast SPI driver for TFT that use Ilitek ILI9163C. Features: - - Very FAST!, expecially with Teensy 3.x where uses DMA SPI. + - Very FAST!, especially with Teensy 3.x where uses DMA SPI. - It uses just 4 or 5 wires. - Compatible at command level with Adafruit display series so it's easy to adapt existing code. - It uses the standard Adafruit_GFX Library (you need to install). Background: - I got one of those displays from a chinese ebay seller but unfortunatly I cannot get + I got one of those displays from a chinese ebay seller but unfortunately I cannot get any working library so I decided to hack it. ILI9163C looks pretty similar to other display driver but it uses it's own commands so it's tricky to work with it unlsess you carefully fight with his gigantic and not so clever datasheet. @@ -147,8 +147,8 @@ This display: This particular display has a design error! The controller has 3 pins to configure to constrain the memory and resolution to a fixed dimension (in that case 128x128) but they leaved those pins configured for 128x160 so there was several pixel memory addressing problems. -I solved by setup several parameters that dinamically fix the resolution as needit so below -the parameters for this diplay. If you have a strain or a correct display (can happen with chinese) +I solved by setup several parameters that dynamically fix the resolution as needit so below +the parameters for this display. If you have a strain or a correct display (can happen with chinese) you can copy those parameters and create setup for different displays. */ #define _TFTWIDTH 128//the REAL W resolution of the TFT @@ -223,7 +223,7 @@ Not tested! #define CMD_FRMCTR3 0xB3//Frame Rate Control(In Partial mode/full colors) #define CMD_DINVCTR 0xB4//Display Inversion Control #define CMD_RGBBLK 0xB5//RGB Interface Blanking Porch setting -#define CMD_DFUNCTR 0xB6//Display Fuction set 5 +#define CMD_DFUNCTR 0xB6//Display Function set 5 #define CMD_SDRVDIR 0xB7//Source Driver Direction Control #define CMD_GDRVDIR 0xB8//Gate Driver Direction Control diff --git a/Sming/Libraries/TFT_ILI9163C/component.mk b/Sming/Libraries/TFT_ILI9163C/component.mk index f2997c2408..f1713fa80a 100644 --- a/Sming/Libraries/TFT_ILI9163C/component.mk +++ b/Sming/Libraries/TFT_ILI9163C/component.mk @@ -1 +1,2 @@ +COMPONENT_SOC := esp8266 COMPONENT_DEPENDS := Adafruit_GFX diff --git a/Sming/Libraries/TFT_S1D13781 b/Sming/Libraries/TFT_S1D13781 index 902f8daba3..0903c3e305 160000 --- a/Sming/Libraries/TFT_S1D13781 +++ b/Sming/Libraries/TFT_S1D13781 @@ -1 +1 @@ -Subproject commit 902f8daba3e03b6ed85d1f06e231c31212fac95b +Subproject commit 0903c3e30545e1a023e6200bca2d9d9ebc73ea9b diff --git a/Sming/Libraries/Timezone b/Sming/Libraries/Timezone index b930f3fc70..9af032b5b5 160000 --- a/Sming/Libraries/Timezone +++ b/Sming/Libraries/Timezone @@ -1 +1 @@ -Subproject commit b930f3fc704a99999505505b2e270346d2788ec1 +Subproject commit 9af032b5b5820434f94c715a39da787b7ab8301b diff --git a/Sming/Libraries/ToneGenerator b/Sming/Libraries/ToneGenerator index 0457fce7d6..46d597d76f 160000 --- a/Sming/Libraries/ToneGenerator +++ b/Sming/Libraries/ToneGenerator @@ -1 +1 @@ -Subproject commit 0457fce7d6da0147cca3cf2285b5cf6c947b0bd6 +Subproject commit 46d597d76fce20f5fbf05e017166e5c50d8d77d8 diff --git a/Sming/Libraries/UPnP b/Sming/Libraries/UPnP index fdc5ee9915..983ecdfd2b 160000 --- a/Sming/Libraries/UPnP +++ b/Sming/Libraries/UPnP @@ -1 +1 @@ -Subproject commit fdc5ee991534c3e9caf8cd0ed002f3861b3a62fd +Subproject commit 983ecdfd2b814e744fe2231867d45e5d50edd312 diff --git a/Sming/Libraries/UPnP-Schema b/Sming/Libraries/UPnP-Schema index 1438502af5..4a0945dddc 160000 --- a/Sming/Libraries/UPnP-Schema +++ b/Sming/Libraries/UPnP-Schema @@ -1 +1 @@ -Subproject commit 1438502af5a922bd04d81f158c6a820815fefe42 +Subproject commit 4a0945dddc69fe138efb7b79aabca8eb04f9230e diff --git a/Sming/Libraries/VT100 b/Sming/Libraries/VT100 index bdf2d2ea7e..2334dfa06e 160000 --- a/Sming/Libraries/VT100 +++ b/Sming/Libraries/VT100 @@ -1 +1 @@ -Subproject commit bdf2d2ea7e7edca99bd317fa57b63f21c72bf60b +Subproject commit 2334dfa06e2ec677acd288b1504057efd924e353 diff --git a/Sming/Libraries/WS2812/component.mk b/Sming/Libraries/WS2812/component.mk new file mode 100644 index 0000000000..e243360e9c --- /dev/null +++ b/Sming/Libraries/WS2812/component.mk @@ -0,0 +1 @@ +COMPONENT_SOC := esp8266 diff --git a/Sming/Arch/Esp32/Components/fatfs/README.rst b/Sming/Libraries/fatfs/README.rst similarity index 100% rename from Sming/Arch/Esp32/Components/fatfs/README.rst rename to Sming/Libraries/fatfs/README.rst diff --git a/Sming/Libraries/fatfs/component.mk b/Sming/Libraries/fatfs/component.mk new file mode 100644 index 0000000000..e0601bd9e8 --- /dev/null +++ b/Sming/Libraries/fatfs/component.mk @@ -0,0 +1,2 @@ +COMPONENT_SRCDIRS := src/fatfs +COMPONENT_INCDIRS := src diff --git a/Sming/Arch/Esp32/Components/fatfs/diskio.h b/Sming/Libraries/fatfs/src/fatfs/diskio.h similarity index 95% rename from Sming/Arch/Esp32/Components/fatfs/diskio.h rename to Sming/Libraries/fatfs/src/fatfs/diskio.h index c7e901d332..76e1539867 100644 --- a/Sming/Arch/Esp32/Components/fatfs/diskio.h +++ b/Sming/Libraries/fatfs/src/fatfs/diskio.h @@ -1,5 +1,5 @@ /*----------------------------------------------------------------------- -/ Low level disk interface modlue include file (C)ChaN, 2014 +/ Low level disk interface module include file (C)ChaN, 2014 /-----------------------------------------------------------------------*/ #ifndef _DISKIO_DEFINED @@ -42,7 +42,7 @@ DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); #define STA_PROTECT 0x04 /* Write protected */ -/* Command code for disk_ioctrl fucntion */ +/* Command code for disk_ioctrl function */ /* Generic command (Used by FatFs) */ #define CTRL_SYNC 0 /* Complete pending write process (needed at _FS_READONLY == 0) */ diff --git a/Sming/Arch/Esp32/Components/fatfs/ff.c b/Sming/Libraries/fatfs/src/fatfs/ff.c similarity index 99% rename from Sming/Arch/Esp32/Components/fatfs/ff.c rename to Sming/Libraries/fatfs/src/fatfs/ff.c index 30d2e714c8..36e60b4fc6 100644 --- a/Sming/Arch/Esp32/Components/fatfs/ff.c +++ b/Sming/Libraries/fatfs/src/fatfs/ff.c @@ -625,7 +625,7 @@ FRESULT dec_lock ( /* Decrement object open counter */ if (!n) Files[i].fs = 0; /* Delete the entry if open count gets zero */ res = FR_OK; } else { - res = FR_INT_ERR; /* Invalid index nunber */ + res = FR_INT_ERR; /* Invalid index number */ } return res; } @@ -1356,7 +1356,7 @@ void gen_numname ( seq = (UINT)sr; } - /* itoa (hexdecimal) */ + /* itoa (hexadecimal) */ i = 7; do { c = (seq % 16) + '0'; @@ -1769,7 +1769,7 @@ int pattern_matching ( /* Return value: 0:mismatched, 1:matched */ do { /* Analyze the wildcard chars */ if (*pp++ == '?') nm++; else nx = 1; } while (*pp == '?' || *pp == '*'); - if (pattern_matching(pp, np, nm, nx)) return 1; /* Test new branch (recurs upto number of wildcard blocks in the pattern) */ + if (pattern_matching(pp, np, nm, nx)) return 1; /* Test new branch (recurs up to number of wildcard blocks in the pattern) */ nc = *np; break; /* Branch mismatched */ } pc = get_achar(&pp); /* Get a pattern char */ @@ -2037,7 +2037,7 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ if (_FS_RPATH && (ns & NS_DOT)) { /* If dot entry is not exist, */ dp->sclust = 0; dp->dir = 0; /* it is the root directory and stay there */ if (!(ns & NS_LAST)) continue; /* Continue to follow if not last segment */ - res = FR_OK; /* Ended at the root directroy. Function completed. */ + res = FR_OK; /* Ended at the root directory. Function completed. */ } else { /* Could not find the object */ if (!(ns & NS_LAST)) res = FR_NO_PATH; /* Adjust error code if not last segment */ } @@ -2218,7 +2218,7 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */ fmt = bsect ? check_fs(fs, bsect) : 2; /* Check the partition */ } while (!LD2PT(vol) && fmt && ++i < 4); } - if (fmt == 3) return FR_DISK_ERR; /* An error occured in the disk I/O layer */ + if (fmt == 3) return FR_DISK_ERR; /* An error occurred in the disk I/O layer */ if (fmt) return FR_NO_FILESYSTEM; /* No FAT volume is found */ /* An FAT volume is found. Following code initializes the file system object */ @@ -3184,7 +3184,7 @@ FRESULT f_opendir ( } if (res == FR_NO_FILE) res = FR_NO_PATH; } - if (res != FR_OK) dp->fs = 0; /* Invalidate the directory object if function faild */ + if (res != FR_OK) dp->fs = 0; /* Invalidate the directory object if function failed */ LEAVE_FF(fs, res); } @@ -3598,7 +3598,7 @@ FRESULT f_mkdir ( mem_set(dir, 0, SS(dj.fs)); } } - if (res == FR_OK) res = dir_register(&dj); /* Register the object to the directoy */ + if (res == FR_OK) res = dir_register(&dj); /* Register the object to the directory */ if (res != FR_OK) { remove_chain(dj.fs, dcl); /* Could not register, remove cluster chain */ } else { @@ -4049,7 +4049,7 @@ FRESULT f_mkfs ( pdrv = LD2PD(vol); /* Physical drive */ part = LD2PT(vol); /* Partition (0:auto detect, 1-4:get from partition table)*/ - /* Get disk statics */ + /* Get disk statistics */ stat = disk_initialize(pdrv); if (stat & STA_NOINIT) return FR_NOT_READY; if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; @@ -4137,7 +4137,7 @@ FRESULT f_mkfs ( /* Update system ID in the partition table */ tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE]; tbl[4] = sys; - if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) /* Write it to teh MBR */ + if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) /* Write it to the MBR */ return FR_DISK_ERR; md = 0xF8; } else { @@ -4598,7 +4598,7 @@ int f_printf ( case 'D' : /* Signed decimal */ case 'U' : /* Unsigned decimal */ r = 10; break; - case 'X' : /* Hexdecimal */ + case 'X' : /* Hexadecimal */ r = 16; break; default: /* Unknown type (pass-through) */ putc_bfd(&pb, c); continue; diff --git a/Sming/Arch/Esp32/Components/fatfs/ff.h b/Sming/Libraries/fatfs/src/fatfs/ff.h similarity index 100% rename from Sming/Arch/Esp32/Components/fatfs/ff.h rename to Sming/Libraries/fatfs/src/fatfs/ff.h diff --git a/Sming/Arch/Esp32/Components/fatfs/ffconf.h b/Sming/Libraries/fatfs/src/fatfs/ffconf.h similarity index 99% rename from Sming/Arch/Esp32/Components/fatfs/ffconf.h rename to Sming/Libraries/fatfs/src/fatfs/ffconf.h index 9f77061925..819ace05e3 100644 --- a/Sming/Arch/Esp32/Components/fatfs/ffconf.h +++ b/Sming/Libraries/fatfs/src/fatfs/ffconf.h @@ -159,7 +159,7 @@ / number is bound to the same physical drive number and only an FAT volume found on / the physical drive will be mounted. When multi-partition feature is enabled (1), / each logical drive number is bound to arbitrary physical drive and partition -/ listed in the VolToPart[]. Also f_fdisk() funciton will be available. */ +/ listed in the VolToPart[]. Also f_fdisk() function will be available. */ #define _MIN_SS 512 diff --git a/Sming/Arch/Esp32/Components/fatfs/integer.h b/Sming/Libraries/fatfs/src/fatfs/integer.h similarity index 51% rename from Sming/Arch/Esp32/Components/fatfs/integer.h rename to Sming/Libraries/fatfs/src/fatfs/integer.h index 16ad408233..7f4033be72 100644 --- a/Sming/Arch/Esp32/Components/fatfs/integer.h +++ b/Sming/Libraries/fatfs/src/fatfs/integer.h @@ -2,36 +2,29 @@ /* Integer type definitions for FatFs module */ /*-------------------------------------------*/ +#include + #ifndef _INTEGER #define _INTEGER -#ifdef _WIN32 /* FatFs development platform */ - -#include -#include - -#else /* Embedded platform */ - /* These types must be 16-bit, 32-bit or larger integer */ -typedef int INT; -typedef unsigned int UINT; +typedef int32_t INT; +typedef uint32_t UINT; /* These types must be 8-bit integer */ typedef char CHAR; typedef unsigned char UCHAR; -typedef unsigned char BYTE; +typedef uint8_t BYTE; /* These types must be 16-bit integer */ -typedef short SHORT; -typedef unsigned short USHORT; -typedef unsigned short WORD; -typedef unsigned short WCHAR; +typedef int16_t SHORT; +typedef uint16_t USHORT; +typedef uint16_t WORD; +typedef uint16_t WCHAR; /* These types must be 32-bit integer */ -typedef long LONG; -typedef unsigned long ULONG; -typedef unsigned long DWORD; - -#endif +typedef int32_t LONG; +typedef uint32_t ULONG; +typedef uint32_t DWORD; #endif diff --git a/Sming/Libraries/flatbuffers/samples/Basic/.cproject b/Sming/Libraries/flatbuffers/samples/Basic/.cproject deleted file mode 100644 index 67c056d24e..0000000000 --- a/Sming/Libraries/flatbuffers/samples/Basic/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/Sming/Libraries/flatbuffers/samples/Basic/.project b/Sming/Libraries/flatbuffers/samples/Basic/.project deleted file mode 100644 index 0b15c33502..0000000000 --- a/Sming/Libraries/flatbuffers/samples/Basic/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Basic_Flatbuffers - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/Sming/Libraries/jerryscript b/Sming/Libraries/jerryscript new file mode 160000 index 0000000000..91dee9e149 --- /dev/null +++ b/Sming/Libraries/jerryscript @@ -0,0 +1 @@ +Subproject commit 91dee9e1490375f0a0bf583805d38937c96db1bd diff --git a/Sming/Libraries/libsodium/README.md b/Sming/Libraries/libsodium/README.md index ece962225a..8203c27f0c 100644 --- a/Sming/Libraries/libsodium/README.md +++ b/Sming/Libraries/libsodium/README.md @@ -10,7 +10,7 @@ For further information, see libsodiums [documentation](https://libsodium.gitboo ## Build Details To build the library, Sming's standard component build process is used in favor of libsodium's original autotools based build process, which is not compatible with the xtensa-lx106-elf architecture. The list of source files, as well as compiler definitions, are hard-coded in component.mk according to the outcomes of (a hacked version of) the configure script. -All optimizations leveraging x86/ARM architecture-specific assembly intructions are disabled and **only C reference implementations are used** instead. This is true even when compiling for the "Host" architecture. +All optimizations leveraging x86/ARM architecture-specific assembly instructions are disabled and **only C reference implementations are used** instead. This is true even when compiling for the "Host" architecture. As a side effect, **there is no need to invoke `sodium_init()` on application startup** (which would otherwise detect available CPU features and select optimal implementations accordingly). ## Notes on Random Number Generation diff --git a/Sming/Libraries/modbusino/samples/generic/app/application.cpp b/Sming/Libraries/modbusino/samples/generic/app/application.cpp index 7256e6509c..6405541879 100644 --- a/Sming/Libraries/modbusino/samples/generic/app/application.cpp +++ b/Sming/Libraries/modbusino/samples/generic/app/application.cpp @@ -6,7 +6,7 @@ uint16_t mbDataArray[ARRLEN] = {0, 0, 0}; ModbusinoSlave mbSlave(MB_SLAVE_ADDR, mbDataArray, ARRLEN); -HardwareSerial debugComPort(UART1); +HardwareSerial debugComPort(UART_ID_1); void mbPrint() { diff --git a/Sming/Libraries/nanopb/README.rst b/Sming/Libraries/nanopb/README.rst index 5a70236598..aaaa0ec81d 100644 --- a/Sming/Libraries/nanopb/README.rst +++ b/Sming/Libraries/nanopb/README.rst @@ -6,7 +6,8 @@ Introduction This component adds support for `Nano Protocol-Buffer `_ implementation. - Nanopb is a small code-size `Protocol Buffers `_ implementation in ansi C. It is especially suitable for use in microcontrollers, but fits any memory restricted system. +Nanopb is a small code-size `Protocol Buffers `_ implementation in ansi C. +It is especially suitable for use in microcontrollers, but fits any memory restricted system. C file generation from Proto files diff --git a/Sming/Libraries/nanopb/nanopb b/Sming/Libraries/nanopb/nanopb index 049485ff55..3d65777c13 160000 --- a/Sming/Libraries/nanopb/nanopb +++ b/Sming/Libraries/nanopb/nanopb @@ -1 +1 @@ -Subproject commit 049485ff557178f646d573eca3bd647f543b760b +Subproject commit 3d65777c1379dc6ce329779f1294b8c7638d1fcc diff --git a/Sming/Libraries/rbpf b/Sming/Libraries/rbpf new file mode 160000 index 0000000000..c5d14ea4f1 --- /dev/null +++ b/Sming/Libraries/rbpf @@ -0,0 +1 @@ +Subproject commit c5d14ea4f1dc74656155907c1dd191505deee0b7 diff --git a/Sming/Libraries/si4432/component.mk b/Sming/Libraries/si4432/component.mk new file mode 100644 index 0000000000..e243360e9c --- /dev/null +++ b/Sming/Libraries/si4432/component.mk @@ -0,0 +1 @@ +COMPONENT_SOC := esp8266 diff --git a/Sming/Libraries/si4432/si4432.cpp b/Sming/Libraries/si4432/si4432.cpp index 27a0c41ffc..69499dfbad 100644 --- a/Sming/Libraries/si4432/si4432.cpp +++ b/Sming/Libraries/si4432/si4432.cpp @@ -1,7 +1,7 @@ /* * SI4432 library for Arduino - v0.1 * - * Please note that Library uses standart SS pin for NSEL pin on the chip. This is 53 for Mega, 10 for Uno. + * Please note that Library uses standard SS pin for NSEL pin on the chip. This is 53 for Mega, 10 for Uno. * NOTES: * * V0.1 @@ -196,7 +196,7 @@ bool Si4432::sendPacket(uint8_t length, } } - //timeout occured. + //timeout occurred. debugf("TX timeout"); switchMode(Ready); @@ -223,7 +223,7 @@ bool Si4432::waitForPacket(uint64_t waitMs) { } } - //timeout occured. + //timeout occurred. debugf("RX timeout"); @@ -298,7 +298,7 @@ void Si4432::setBaudRate(uint16_t kbps) { debugf("min Bandwidth value: %x ", minBandwidth); #endif byte IFValue = 0xff; - //since the table is ordered (from low to high), just find the 'minimum bandwith which is greater than required' + //since the table is ordered (from low to high), just find the 'minimum bandwidth which is greater than required' for (byte i = 0; i < 8; ++i) { if (IFFilterTable[i][0] >= (minBandwidth * 10)) { IFValue = IFFilterTable[i][1]; @@ -483,7 +483,7 @@ void Si4432::startListening() { bool Si4432::isPacketReceived() { if ((_intPin != 0) && (digitalRead(_intPin) != 0)) { - return false; // if no interrupt occured, no packet received is assumed (since startListening will be called prior, this assumption is enough) + return false; // if no interrupt occurred, no packet received is assumed (since startListening will be called prior, this assumption is enough) } // check for package received status interrupt register byte intStat = ReadRegister(REG_INT_STATUS1); @@ -491,13 +491,13 @@ bool Si4432::isPacketReceived() { #if DEBUG_SI4432 byte intStat2 = ReadRegister(REG_INT_STATUS2); - if (intStat2 & 0x40) { //interrupt occured, check it && read the Interrupt Status1 register for 'preamble ' + if (intStat2 & 0x40) { //interrupt occurred, check it && read the Interrupt Status1 register for 'preamble ' debugf("Valid Preamble detected -- %x", intStat2); } - if (intStat2 & 0x80) { //interrupt occured, check it && read the Interrupt Status1 register for 'preamble ' + if (intStat2 & 0x80) { //interrupt occurred, check it && read the Interrupt Status1 register for 'preamble ' debugf("SYNC WORD detected -- %x", intStat2); @@ -506,7 +506,7 @@ bool Si4432::isPacketReceived() { ReadRegister(REG_INT_STATUS2); #endif - if (intStat & 0x02) { //interrupt occured, check it && read the Interrupt Status1 register for 'valid packet' + if (intStat & 0x02) { //interrupt occurred, check it && read the Interrupt Status1 register for 'valid packet' switchMode(Ready | TuneMode); // if packet came, get out of Rx mode till the packet is read out. Keep PLL on for fast reaction #if DEBUG_SI4432 debugf("Packet detected -- %x", intStat); diff --git a/Sming/Libraries/si4432/si4432.h b/Sming/Libraries/si4432/si4432.h index f810e1af18..eb3399fcc9 100644 --- a/Sming/Libraries/si4432/si4432.h +++ b/Sming/Libraries/si4432/si4432.h @@ -1,7 +1,7 @@ /* * SI4432 library for Arduino - v0.1 * - * Please note that Library uses standart SS pin for NSEL pin on the chip. This is 53 for Mega, 10 for Uno. + * Please note that Library uses standard SS pin for NSEL pin on the chip. This is 53 for Mega, 10 for Uno. * NOTES: * * V0.1 diff --git a/Sming/Makefile b/Sming/Makefile index a64374e5ca..9f241f7ced 100644 --- a/Sming/Makefile +++ b/Sming/Makefile @@ -2,7 +2,7 @@ # # Created by Espressif # UDK modifications by CHERTS -# Cross platform compatability by kireevco +# Cross platform compatibility by kireevco # Multi-architecture support by mikee47 # ############################################################# @@ -103,74 +103,93 @@ docs: submodules ##Build the Sming documentation # For integration testing both samples and tests are moved outside of the repo. SMING_PROJECTS_DIR ?= $(abspath $(SMING_HOME)/..) -SMING_PROJECTS_DIR := $(call FixPath, $(SMING_PROJECTS_DIR)) +SMING_PROJECTS_DIR := $(call FixPath,$(SMING_PROJECTS_DIR)) SAMPLES_DIR := $(SMING_PROJECTS_DIR)/samples -SAMPLE_NAMES = $(shell ls -1 $(SAMPLES_DIR)) - -.PHONY: samples $(SAMPLE_NAMES) -samples: | $(SAMPLE_NAMES) ##Build all sample applications +# Marks sample as build complete for faster re-testing +BUILT_SUFFIX := /.$(SMING_SOC).built +SAMPLE_PATHS = $(sort $(wildcard $(SAMPLES_DIR)/*)) +SAMPLES_BUILT = $(addsuffix $(BUILT_SUFFIX),$(SAMPLE_PATHS)) +SAMPLE_NAMES = $(notdir $(SAMPLE_PATHS)) + +.PHONY: samples +samples: $(SAMPLES_BUILT) ##Build all sample applications + +# Build any samples which haven't yet been marked +$(SAMPLES_BUILT): + @printf "\n\n** Building $(notdir $(call dirx,$@)) **\n\n" + $(Q) $(MAKE) --no-print-directory -C $(@D) PIP_ARGS=-q python-requirements sample + $(Q) touch $@ -$(SAMPLE_NAMES): - @printf "\n\n** Building ${@F} **\n\n" - $(Q) $(MAKE) --no-print-directory -C $(SAMPLES_DIR)/$@ PIP_ARGS=-q python-requirements all +# Build/clean named samples +# $1 -> Sample path +define CreateSampleTargets +.PHONY: $(notdir $1) $(notdir $1)-clean +$(notdir $1): $1$(BUILT_SUFFIX) +$(notdir $1)-clean: + -$(Q) cd $1 && $(MAKE) --no-print-directory -C$1 clean + -$(Q) rm -f $1$(BUILT_SUFFIX) +endef +$(foreach s,$(SAMPLE_PATHS),$(eval $(call CreateSampleTargets,$s))) # Build component samples .PHONY: component-samples component-samples: submodules ##Build all samples contained in components $(Q) $(MAKE) --no-print-directory build-component-samples -# Marks sample as build complete for faster re-testing -BUILT_SUFFIX := /out/.built -COMPONENT_SAMPLE_TARGETS = $(addsuffix $(BUILT_SUFFIX),$(wildcard $(foreach c,$(COMPONENT_SEARCH_DIRS),$c/*/samples/*))) +COMPONENT_SAMPLE_PATHS = $(wildcard $(foreach c,$(COMPONENT_SEARCH_DIRS),$c/*/samples/*)) +COMPONENT_SAMPLES_BUILT = $(addsuffix $(BUILT_SUFFIX),$(COMPONENT_SAMPLE_PATHS)) .PHONY: build-component-samples -build-component-samples: $(COMPONENT_SAMPLE_TARGETS) +build-component-samples: $(COMPONENT_SAMPLES_BUILT) -$(COMPONENT_SAMPLE_TARGETS): - @printf "\n\n** Building $(notdir $(@:$(BUILT_SUFFIX)=)) **\n\n" - $(Q) $(MAKE) --no-print-directory -C $(@:$(BUILT_SUFFIX)=) PIP_ARGS=-q python-requirements all +$(COMPONENT_SAMPLES_BUILT): + @printf "\n\n** Building $(@D) **\n\n" + $(Q) $(MAKE) --no-print-directory -C $(@D) PIP_ARGS=-q python-requirements sample $(Q) touch $@ +# This file is generated on failure during test phase +export TEST_FAILURE_FILE := $(SMING_HOME)/.test-failure PHONY: tests tests: submodules ##Build and run all tests + $(Q) rm -rf $(TEST_FAILURE_FILE) $(Q) $(MAKE) --no-print-directory build-and-run-tests + $(Q) if [ -f "$(TEST_FAILURE_FILE)" ]; then \ + printf "\n\n** Tests failed **\n\n"; \ + exit 2; \ + fi -COMPLETED_SUFFIX := /.complete COMPONENT_TESTS = $(call dirx,$(wildcard $(foreach c,$(COMPONENT_SEARCH_DIRS),$c/*/test/component.mk))) -TESTS_COMPLETED = $(addsuffix $(COMPLETED_SUFFIX),$(wildcard $(SMING_PROJECTS_DIR)/tests/* $(COMPONENT_TESTS))) +TEST_PATHS = $(wildcard $(SMING_PROJECTS_DIR)/tests/* $(COMPONENT_TESTS)) +TESTS_COMPLETED = $(addsuffix /.$(SMING_SOC).complete,$(TEST_PATHS)) PHONY: build-and-run-tests build-and-run-tests: $(TESTS_COMPLETED) ##Build and run all test applications $(TESTS_COMPLETED): - @printf "\n\n** Building $(notdir $(@D)) **\n\n" - $(Q) $(MAKE) -C $(@D) execute - $(Q) touch $@ - + $(Q) \ + export MODULE="$(patsubst $(SMING_PROJECTS_DIR)/tests/%,%,$(@D))" && \ + printf "\n\n** Building $$MODULE **\n\n" && \ + $(MAKE) -C $(@D) execute HOST_PARAMETERS="module=$(MODULE)" && \ + touch $@ ##@Cleaning .PHONY: samples-clean samples-clean: ##Clean all sample applications (all arch/build types) @echo Cleaning all samples... - -$(Q) cd $(SAMPLES_DIR) && rm -rf $(addsuffix /out,$(SAMPLE_NAMES)) + -$(Q) rm -rf $(addsuffix /out,$(SAMPLE_PATHS)) $(addsuffix /.*.built,$(SAMPLE_PATHS)) .PHONY: component-samples-clean component-samples-clean: ##Clean all component samples @echo Cleaning all component samples... - -$(Q) rm -rf $(dir $(COMPONENT_SAMPLE_TARGETS)) + -$(Q) rm -rf $(addsuffix /out,$(COMPONENT_SAMPLE_PATHS)) $(addsuffix /.*.built,$(COMPONENT_SAMPLE_PATHS)) -CLEAN_TESTS := $(TESTS_COMPLETED:complete=clean) .PHONY: tests-clean -tests-clean: $(wildcard $(CLEAN_TESTS)) ##Clean all test applications (all arch/build types) - -$(Q) rm -f $(TESTS_COMPLETED) - -.PHONY: $(CLEAN_TESTS) -$(CLEAN_TESTS): - @echo Cleaning '$(@D)' - -$(Q) $(MAKE) -C $(@D) clean +tests-clean: ##Clean all test applications + -$(Q) $(foreach p,$(TEST_PATHS),echo ">> $p"; $(MAKE) --no-print-directory -C $p clean;) + -$(Q) rm -f $(addsuffix /.*.complete,$(TEST_PATHS)) $(TEST_FAILURE_FILE) ##@Tools @@ -212,6 +231,18 @@ CS_DEV_FILES = $(filter $(abspath $(addprefix ../,$(shell git diff --name-only d cs-dev: ##Apply coding style to all files changed from current upstream develop branch $(call ClangFormat,$(CS_DEV_FILES)) +.PHONY: codespell +codespell: ##Check spelling (set CS_PARAM with additional command-line parameters) + @echo Running codespell... + $(Q)cd $(SMING_HOME)/.. && \ + codespell \ + --check-filenames \ + --skip $$(tr "\n" , < Tools/spelling/skip.txt) \ + --ignore-words Tools/spelling/ignore.txt \ + --summary \ + $(CS_PARAM) + + ##@Help diff --git a/Sming/Platform/OsMessageInterceptor.cpp b/Sming/Platform/OsMessageInterceptor.cpp index f4a74d36c6..280c041ad2 100644 --- a/Sming/Platform/OsMessageInterceptor.cpp +++ b/Sming/Platform/OsMessageInterceptor.cpp @@ -11,6 +11,7 @@ ****/ #include "Platform/OsMessageInterceptor.h" +#include extern void smg_uart_debug_putc(char); @@ -30,11 +31,17 @@ void OsMessageInterceptor::begin(OsMessageCallback callback) this->callback = callback; message.clear(); self = this; +#if defined(ARCH_ESP8266) || defined(ARCH_ESP32) ets_install_putc1(static_putc); +#endif +#if defined(ARCH_ESP8266) system_set_os_print(true); +#endif } void OsMessageInterceptor::end() { +#if defined(ARCH_ESP8266) || defined(ARCH_ESP32) ets_install_putc1(smg_uart_debug_putc); +#endif } diff --git a/Sming/Platform/System.cpp b/Sming/Platform/System.cpp index 52472fa658..f661d942fd 100644 --- a/Sming/Platform/System.cpp +++ b/Sming/Platform/System.cpp @@ -11,20 +11,25 @@ #include "Platform/System.h" #include "Timer.h" -#ifndef TASK_QUEUE_LENGTH +SystemClass System; +SystemState SystemClass::state = eSS_None; + +#ifdef ARCH_ESP32 +#undef TASK_QUEUE_LENGTH +#define TASK_QUEUE_LENGTH 0 +#define taskQueue nullptr +#else +#ifdef TASK_QUEUE_LENGTH +static_assert(TASK_QUEUE_LENGTH >= 8, "Task queue too small"); +#else /** @brief default number of tasks in global queue * @note tasks are usually short-lived and executed very promptly, so a large queue is * normally un-necessry. If queue overrun is suspected, check `SystemClass::getMaxTaskCount()`. */ #define TASK_QUEUE_LENGTH 10 #endif - -SystemClass System; - -SystemState SystemClass::state = eSS_None; os_event_t SystemClass::taskQueue[TASK_QUEUE_LENGTH]; - -static_assert(TASK_QUEUE_LENGTH >= 8, "Task queue too small"); +#endif #ifdef ENABLE_TASK_COUNT volatile uint8_t SystemClass::taskCount; diff --git a/Sming/Platform/System.h b/Sming/Platform/System.h index 948fd375aa..562e5d5074 100644 --- a/Sming/Platform/System.h +++ b/Sming/Platform/System.h @@ -65,12 +65,14 @@ class ISystemReadyHandler }; /** - * @brief CPU Frequency + * @brief Common CPU frequencies */ enum CpuFrequency { - eCF_80MHz = 80, ///< CPU 80MHz - eCF_160MHz = 160, ///< CPU 160MHz - eCF_240MHz = 240, ///< CPU 240MHz + eCF_80MHz = 80, + eCF_125MHz = 125, + eCF_133MHz = 133, + eCF_160MHz = 160, + eCF_240MHz = 240, }; /** @@ -127,10 +129,11 @@ class SystemClass /** @brief Set the CPU frequency * @param freq Frequency to set CPU + * @retval bool true on success */ - void setCpuFrequency(CpuFrequency freq) + bool setCpuFrequency(CpuFrequency freq) { - system_update_cpu_freq(freq); + return system_update_cpu_freq(freq); } /** @brief Get the CPU frequency diff --git a/Sming/Platform/WDT.cpp b/Sming/Platform/WDT.cpp index 3c5c0cae7f..d9731bd423 100644 --- a/Sming/Platform/WDT.cpp +++ b/Sming/Platform/WDT.cpp @@ -18,15 +18,16 @@ WDTClass WDT; void WDTClass::enable(bool enableWatchDog) { enabled = enableWatchDog; - if(System.isReady()) + if(System.isReady()) { internalApplyEnabled(); - else + } else { System.onReady(this); + } } void WDTClass::alive() { - system_soft_wdt_restart(); + system_soft_wdt_feed(); } void WDTClass::onSystemReady() @@ -36,8 +37,9 @@ void WDTClass::onSystemReady() void WDTClass::internalApplyEnabled() { - if(enabled) + if(enabled) { system_soft_wdt_restart(); - else + } else { system_soft_wdt_stop(); + } } diff --git a/Sming/Platform/WDT.h b/Sming/Platform/WDT.h index df02bd5b17..cde9adf3e2 100644 --- a/Sming/Platform/WDT.h +++ b/Sming/Platform/WDT.h @@ -20,7 +20,6 @@ #pragma once -#include #include "System.h" /** @brief Watchdog timer class diff --git a/Sming/Services/CommandProcessing/CommandDelegate.h b/Sming/Services/CommandProcessing/CommandDelegate.h index 2acab00e7f..59ca69f256 100644 --- a/Sming/Services/CommandProcessing/CommandDelegate.h +++ b/Sming/Services/CommandProcessing/CommandDelegate.h @@ -22,13 +22,10 @@ */ using CommandFunctionDelegate = Delegate; -/** @deprecated Use `CommandFunctionDelegate` instead */ -typedef CommandFunctionDelegate commandFunctionDelegate SMING_DEPRECATED; - /** @brief Command delegate class */ class CommandDelegate { - // Hashmap uses CommandDelegate() contructor when extending size + // Hashmap uses CommandDelegate() constructor when extending size friend class HashMap; public: diff --git a/Sming/Services/CommandProcessing/CommandExecutor.cpp b/Sming/Services/CommandProcessing/CommandExecutor.cpp index fc61202431..c42dae5e45 100644 --- a/Sming/Services/CommandProcessing/CommandExecutor.cpp +++ b/Sming/Services/CommandProcessing/CommandExecutor.cpp @@ -7,6 +7,7 @@ #include "CommandExecutor.h" #include "HardwareSerial.h" +#include CommandExecutor::CommandExecutor() { diff --git a/Sming/Services/CommandProcessing/CommandExecutor.h b/Sming/Services/CommandProcessing/CommandExecutor.h index 9bf51f749d..2e74f548ba 100644 --- a/Sming/Services/CommandProcessing/CommandExecutor.h +++ b/Sming/Services/CommandProcessing/CommandExecutor.h @@ -20,6 +20,9 @@ class CommandExecutor { public: + CommandExecutor(const CommandExecutor&) = delete; + CommandExecutor& operator=(const CommandExecutor&) = delete; + #ifndef DISABLE_NETWORK CommandExecutor(TcpClient* cmdClient); CommandExecutor(WebsocketConnection* reqSocket); diff --git a/Sming/Services/CommandProcessing/CommandHandler.cpp b/Sming/Services/CommandProcessing/CommandHandler.cpp index 496a471525..039a1a1816 100644 --- a/Sming/Services/CommandProcessing/CommandHandler.cpp +++ b/Sming/Services/CommandProcessing/CommandHandler.cpp @@ -8,6 +8,12 @@ #include "CommandHandler.h" #include "CommandDelegate.h" #include +#include +#include + +#ifndef DISABLE_NETWORK +#include +#endif #ifndef LWIP_HASH_STR #define LWIP_HASH_STR "" diff --git a/Sming/Services/CommandProcessing/CommandHandler.h b/Sming/Services/CommandProcessing/CommandHandler.h index 03c4419981..c6dbf3d23a 100644 --- a/Sming/Services/CommandProcessing/CommandHandler.h +++ b/Sming/Services/CommandProcessing/CommandHandler.h @@ -61,7 +61,7 @@ class CommandHandler bool unregisterCommand(CommandDelegate reqDelegate); /** @brief Register default system commands - * @note Adds the following system commmands to the command handler + * @note Adds the following system commands to the command handler * - status * - echo * - help @@ -73,7 +73,7 @@ class CommandHandler /** @brief Get the command delegate for a command * @param commandString Command to query - * @retval CommandDelegate The command delegate matchin the command + * @retval CommandDelegate The command delegate matching the command */ CommandDelegate getCommandDelegate(const String& commandString); diff --git a/Sming/SmingCore/SmingCore.h b/Sming/SmingCore/SmingCore.h deleted file mode 100644 index 3bc5bbde27..0000000000 --- a/Sming/SmingCore/SmingCore.h +++ /dev/null @@ -1,2 +0,0 @@ -#include -#pragma GCC warning "Please update to #include - see https://sming.readthedocs.io/en/4.3.0/upgrading/3.8-4.0.html" diff --git a/Sming/System/include/c_types.h b/Sming/System/include/c_types.h index b5d2b1535e..bea535660b 100644 --- a/Sming/System/include/c_types.h +++ b/Sming/System/include/c_types.h @@ -25,3 +25,16 @@ typedef uint64_t uint64; typedef uint64_t u64; typedef float real32; typedef double real64; + +#ifndef BIT +#define BIT(nr) (1UL << (nr)) +#endif + +#ifndef TRUE +#define TRUE true +#define FALSE false +#endif + +#ifndef LOCAL +#define LOCAL static +#endif diff --git a/Sming/System/include/gdb/gdb_hooks.h b/Sming/System/include/gdb/gdb_hooks.h index 98bc1fc21e..9821c29a10 100644 --- a/Sming/System/include/gdb/gdb_hooks.h +++ b/Sming/System/include/gdb/gdb_hooks.h @@ -19,7 +19,7 @@ #pragma once -#include +#include #ifdef __cplusplus extern "C" { @@ -57,8 +57,10 @@ void gdb_enable(bool state); #define gdb_do_break() __asm__("int $0x03") #elif defined(ARCH_ESP8266) #define gdb_do_break() __asm__("break 0,0") -#else +#elif defined(ARCH_ESP32) #define gdb_do_break() cpu_hal_break() +#elif defined(ARCH_RP2040) +#define gdb_do_break() __asm__("bkpt #0") #endif #else #define gdb_do_break() \ diff --git a/Sming/System/include/gdb/gdb_syscall.h b/Sming/System/include/gdb/gdb_syscall.h index 02c0bd9664..e4a62c3e00 100644 --- a/Sming/System/include/gdb/gdb_syscall.h +++ b/Sming/System/include/gdb/gdb_syscall.h @@ -26,11 +26,12 @@ #pragma once -#include +#include #include #include #include #include +#include /** @defgroup gdb_syscall GDB system call API * @ingroup GDB diff --git a/Sming/System/include/m_printf.h b/Sming/System/include/m_printf.h index bc3efc4991..ed36499842 100644 --- a/Sming/System/include/m_printf.h +++ b/Sming/System/include/m_printf.h @@ -56,10 +56,7 @@ size_t m_putc(char c); */ size_t m_nputs(const char* str, size_t length); -static inline size_t m_puts(const char* str) -{ - return m_nputs(str, strlen(str)); -} +size_t m_puts(const char* str); #ifdef __cplusplus } diff --git a/Sming/System/include/sming_attr.h b/Sming/System/include/sming_attr.h index 841b0501d3..16bfc4224d 100644 --- a/Sming/System/include/sming_attr.h +++ b/Sming/System/include/sming_attr.h @@ -10,7 +10,13 @@ #pragma once +#ifndef __forceinline #define __forceinline __attribute__((always_inline)) inline +#endif + +#ifndef __noinline +#define __noinline __attribute__((noinline)) +#endif // Weak attributes don't work for PE #ifdef __WIN32 diff --git a/Sming/System/include/stringutil.h b/Sming/System/include/stringutil.h index cf1bbb92d1..a64950f7db 100644 --- a/Sming/System/include/stringutil.h +++ b/Sming/System/include/stringutil.h @@ -21,10 +21,10 @@ extern "C" { #include "stddef.h" -/** @brief Return pointer to occurence of substring in string. Case insensitive. +/** @brief Return pointer to occurrence of substring in string. Case insensitive. * @param[in] pString string to work with * @param[in] pToken string to locate - * @retval const char* pointer to first occurence in of pToken in pString or NULL if not found + * @retval const char* pointer to first occurrence in of pToken in pString or NULL if not found */ const char* strstri(const char* pString, const char* pToken); diff --git a/Sming/Arch/Esp8266/System/include/user_config.h b/Sming/System/include/user_config.h similarity index 50% rename from Sming/Arch/Esp8266/System/include/user_config.h rename to Sming/System/include/user_config.h index aff24e4258..19380597ba 100644 --- a/Sming/Arch/Esp8266/System/include/user_config.h +++ b/Sming/System/include/user_config.h @@ -1,8 +1,7 @@ #ifndef __USER_CONFIG_H__ #define __USER_CONFIG_H__ -// UART config -#define SERIAL_BAUD_RATE COM_SPEED_SERIAL +#pragma GCC warning "Use of 'user_config.h' is deprecated - see https://sming.readthedocs.io/en/latest/upgrading/4.4-4.5.html" #include @@ -10,6 +9,8 @@ #include // Network base API -#include +#ifndef DISABLE_NETWORK +#include +#endif #endif diff --git a/Sming/System/m_printf.cpp b/Sming/System/m_printf.cpp index 4f0c865955..46b29172ac 100644 --- a/Sming/System/m_printf.cpp +++ b/Sming/System/m_printf.cpp @@ -231,6 +231,10 @@ size_t m_nputs(const char* str, size_t length) return _puts_callback ? _puts_callback(str, length) : 0; } +size_t m_puts(const char* str) +{ + return m_nputs(str, strlen(str)); +} void m_printHex(const char* tag, const void* data, size_t len, int addr, size_t bytesPerLine) { diff --git a/Sming/System/stringconversion.cpp b/Sming/System/stringconversion.cpp index 08756c0e97..a8d38f0f2f 100644 --- a/Sming/System/stringconversion.cpp +++ b/Sming/System/stringconversion.cpp @@ -8,9 +8,10 @@ * ****/ -#include #include -#include +#include +#include +#include #include "stringconversion.h" #include "stringutil.h" diff --git a/Sming/Wiring/Arduino.h b/Sming/Wiring/Arduino.h index 17c9cc8ed8..9f381e2918 100644 --- a/Sming/Wiring/Arduino.h +++ b/Sming/Wiring/Arduino.h @@ -2,7 +2,6 @@ #pragma once -#include #include "WiringFrameworkDependencies.h" #include "SmingCore.h" #include "ArduinoCompat.h" diff --git a/Sming/Wiring/FakePgmSpace.cpp b/Sming/Wiring/FakePgmSpace.cpp index 8ca8ecdeec..156a31df6c 100644 --- a/Sming/Wiring/FakePgmSpace.cpp +++ b/Sming/Wiring/FakePgmSpace.cpp @@ -9,7 +9,7 @@ ****/ #include "FakePgmSpace.h" -#include +#include /* * We implement aligned versions of some system functions to be used strictly on diff --git a/Sming/Wiring/FlashString.h b/Sming/Wiring/FlashString.h deleted file mode 100644 index 2c47de23ed..0000000000 --- a/Sming/Wiring/FlashString.h +++ /dev/null @@ -1,17 +0,0 @@ -/**** - * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. - * Created 2015 by Skurydin Alexey - * http://github.com/SmingHub/Sming - * All files of the Sming Core are provided under the LGPL v3 license. - * - * @author: 2018 - Mikee47 - * - * Defines the FlashString structure and associated macros for efficient flash memory string access. - * - ****/ - -#pragma once - -#include "WString.h" - -#pragma GCC warning "It is no longer necessary to #include FlashString.h in your projects, WString.h is sufficient" diff --git a/Sming/Wiring/Print.h b/Sming/Wiring/Print.h index c4898f11ba..40885eaa19 100644 --- a/Sming/Wiring/Print.h +++ b/Sming/Wiring/Print.h @@ -275,8 +275,8 @@ class Print } /** @brief Prints a formatted c-string to output stream - * @param fmt Pointer to formated c-string to print - * @param "..." Parameters for placeholders within formated string + * @param fmt Pointer to formatted c-string to print + * @param "..." Parameters for placeholders within formatted string * @retval size_t Quantity of characters written to stream * @note Use standard printf placeholders, e.g. %d for integer, %s for c-string, etc. */ diff --git a/Sming/Wiring/SplitString.cpp b/Sming/Wiring/SplitString.cpp index dc7290e946..d2a7b9b209 100644 --- a/Sming/Wiring/SplitString.cpp +++ b/Sming/Wiring/SplitString.cpp @@ -11,7 +11,7 @@ #include "SplitString.h" -int splitString(String& what, char delim, Vector& splits) +unsigned splitString(String& what, char delim, Vector& splits) { what.trim(); splits.removeAllElements(); @@ -39,7 +39,7 @@ int splitString(String& what, char delim, Vector& splits) return splits.count(); } -int splitString(String& what, char delim, Vector& splits) +unsigned splitString(String& what, char delim, Vector& splits) { what.trim(); splits.removeAllElements(); diff --git a/Sming/Wiring/SplitString.h b/Sming/Wiring/SplitString.h index 8ff757154c..2e17d1bc91 100644 --- a/Sming/Wiring/SplitString.h +++ b/Sming/Wiring/SplitString.h @@ -18,18 +18,18 @@ * @param what * @param delim * @param splits - * @retval number of items returned in splits (same as splits.count()) + * @retval unsigned number of items returned in splits (same as splits.count()) * @note leading/trailing whitespace is removed from 'what' before parsing * example: " 1,2,3,4,5" returns [1, 2, 3, 4, 5] */ -int splitString(String& what, char delim, Vector& splits); +unsigned splitString(String& what, char delim, Vector& splits); /** @brief split a delimited string list into an array * @param what * @param delim * @param splits - * @retval number of items returned in splits (same as splits.count()) + * @retval unsigned number of items returned in splits (same as splits.count()) * @note leading/trailing whitespace is removed from 'what' before parsing * example: " a,b,c,d,e" returns ["a", "b", "c", "d", "e"] */ -int splitString(String& what, char delim, Vector& splits); +unsigned splitString(String& what, char delim, Vector& splits); diff --git a/Sming/Wiring/Stream.cpp b/Sming/Wiring/Stream.cpp index 2822dc0d64..b4345b8b5b 100644 --- a/Sming/Wiring/Stream.cpp +++ b/Sming/Wiring/Stream.cpp @@ -119,7 +119,7 @@ long Stream::parseInt(char skipChar) do { if(c == skipChar) { - // ignore this charactor + // ignore this character } else if(c == '-') { isNegative = true; } else if(c >= '0' && c <= '9') { diff --git a/Sming/Wiring/WConstants.h b/Sming/Wiring/WConstants.h index 1c11d7c792..97af55bce0 100644 --- a/Sming/Wiring/WConstants.h +++ b/Sming/Wiring/WConstants.h @@ -41,7 +41,8 @@ //GPIO FUNCTIONS #define INPUT 0x00 #define INPUT_PULLUP 0x02 -#define INPUT_PULLDOWN_16 0x04 // PULLDOWN only possible for pin16 +#define INPUT_PULLDOWN_16 0x04 // PULLDOWN only possible for pin16 on ESP8266 +#define INPUT_PULLDOWN 0x04 #define OUTPUT 0x01 #define OUTPUT_OPEN_DRAIN 0x03 #define WAKEUP_PULLUP 0x05 diff --git a/Sming/Wiring/WString.cpp b/Sming/Wiring/WString.cpp index d32e20afe2..4975d78efb 100644 --- a/Sming/Wiring/WString.cpp +++ b/Sming/Wiring/WString.cpp @@ -20,7 +20,7 @@ #include #include #include -#include +#include const String String::nullstr = nullptr; const String String::empty = ""; @@ -860,14 +860,14 @@ bool String::replace(const char* find_buf, size_t find_len, const char* replace_ char* writeTo = buf; while((foundAt = (char*)memmem(readFrom, end - readFrom, find_buf, find_len)) != nullptr) { size_t n = foundAt - readFrom; - memcpy(writeTo, readFrom, n); + memmove(writeTo, readFrom, n); writeTo += n; memcpy(writeTo, replace_buf, replace_len); writeTo += replace_len; readFrom = foundAt + find_len; len += diff; } - memcpy(writeTo, readFrom, end - readFrom); + memmove(writeTo, readFrom, end - readFrom); setlen(len); } else { size_t size = len; // compute size needed for result @@ -883,7 +883,7 @@ bool String::replace(const char* find_buf, size_t find_len, const char* replace_ } buf = buffer(); int index = len - 1; - while((index = lastIndexOf(find_buf, index, find_len)) >= 0) { + while(index >= 0 && (index = lastIndexOf(find_buf, index, find_len)) >= 0) { readFrom = buf + index + find_len; memmove(readFrom + diff, readFrom, len - (readFrom - buf)); len += diff; @@ -929,7 +929,7 @@ void String::toUpperCase(void) } } -void String::trim(void) +void String::trim(const char* set) { auto len = length(); if(len == 0) { @@ -937,11 +937,11 @@ void String::trim(void) } auto buf = buffer(); char* begin = buf; - while(isspace(*begin)) { + while(strchr(set, *begin)) { begin++; } char* end = buf + len - 1; - while(isspace(*end) && end >= begin) { + while(strchr(set, *end) && end >= begin) { end--; } len = end + 1 - begin; diff --git a/Sming/Wiring/WString.h b/Sming/Wiring/WString.h index a517ec530b..2566f6b620 100644 --- a/Sming/Wiring/WString.h +++ b/Sming/Wiring/WString.h @@ -46,7 +46,7 @@ * * @author Nov 2019 mikee47 * - * Small String Optimisation (SSO). Based on the Arduino ESP8266 core implentation. + * Small String Optimisation (SSO). Based on the Arduino ESP8266 core implementation. * An empty String object now consumes 12 bytes (from 8) but provides an SSO capacity of 11 characters. * Capacity and length types changed to size_t, thus String is no longer restricted to 64K. * @@ -310,7 +310,7 @@ class String * * Works with built-in types. * On failure, the string is left unchanged. - * If the argument is null or invalid, the concatenation is considered unsucessful. + * If the argument is null or invalid, the concatenation is considered unsuccessful. * * @{ */ @@ -583,7 +583,7 @@ class String */ bool endsWith(const String& suffix) const; - // character acccess + // character access /** * @brief Obtain the character at the given index @@ -789,9 +789,10 @@ class String void toUpperCase(void); /** - * @brief Remove all leading and trailing whitespace characters from the String + * @brief Remove all leading and trailing characters from the String + * @param Set of characters to remove, defaults to whitespace set */ - void trim(void); + void trim(const char* set = " \t\n\v\f\r"); // parsing/conversion long toInt(void) const; diff --git a/Sming/Wiring/WiringFrameworkDependencies.h b/Sming/Wiring/WiringFrameworkDependencies.h index 9ef6888ec3..4ced56fa61 100644 --- a/Sming/Wiring/WiringFrameworkDependencies.h +++ b/Sming/Wiring/WiringFrameworkDependencies.h @@ -7,12 +7,11 @@ #pragma once -#include - #include #include #include #include +#include #include "WConstants.h" #include "BitManipulations.h" diff --git a/Sming/build.mk b/Sming/build.mk index c3b8958cca..055a58dea3 100644 --- a/Sming/build.mk +++ b/Sming/build.mk @@ -1,14 +1,48 @@ # Build environment definitions +include $(SMING_HOME)/util.mk + # Add debug variable names to DEBUG_VARS so they can be easily inspected via `make list-config` -DEBUG_VARS := +DEBUG_VARS := SMING_HOME +SMING_HOME := $(patsubst %/,%,$(call FixPath,$(SMING_HOME))) -# -DEBUG_VARS += SMING_HOME SMING_ARCH +# Resolve SMING_ARCH and SMING_SOC settings +DEBUG_VARS += SMING_ARCH SMING_SOC ifeq (,$(SMING_ARCH)) -override SMING_ARCH := Esp8266 + ifeq (,$(SMING_SOC)) + SMING_ARCH := Esp8266 + SMING_SOC := esp8266 + else + override SMING_ARCH := $(notdir $(call dirx,$(filter %/$(SMING_SOC)-soc.json,$(SOC_CONFIG_FILES)))) + ifeq (,$(SMING_ARCH)) + $(error SOC '$(SMING_SOC)' not found) + endif + endif +else ifeq (,$(filter $(SMING_SOC),$(ARCH_$(SMING_ARCH)_SOC))) + SMING_SOC := $(firstword $(ARCH_$(SMING_ARCH)_SOC)) endif + +ifeq (,$(wildcard $(SMING_HOME)/Arch/$(SMING_ARCH)/build.mk)) + $(error Arch '$(SMING_ARCH)' not found) +endif + export SMING_ARCH +export SMING_SOC + +# SOC config for currently selected variant +export SOC_CONFIG_FILE := $(SMING_HOME)/Arch/$(SMING_ARCH)/$(SMING_SOC)-soc.json + +# Paths for standard build tools +DEBUG_VARS += \ + AS \ + CC \ + CXX \ + AR \ + LD \ + NM \ + OBJCOPY \ + OBJDUMP \ + GDB # Paths for standard build tools DEBUG_VARS += \ @@ -31,9 +65,11 @@ else endif export SMING_RELEASE +SMING_TOOLS := $(realpath $(SMING_HOME)/../Tools) + # Detect OS and build environment TOOL_EXT := -DEBUG_VARS += UNAME +DEBUG_VARS += UNAME OS UNAME := $(shell uname -s) ifneq ($(filter MINGW32_NT%,$(UNAME)),) UNAME := Windows @@ -63,20 +99,6 @@ else ifeq ($(UNAME), Freebsd) #BSD endif -# Convert Windows paths to POSIX paths -DEBUG_VARS += OS -ifeq ($(OS),Windows_NT) -FixPath = $(subst //,/,$(subst \,/,$(addprefix /,$(subst :,,$1)))) -else -FixPath = $1 -endif - -SMING_HOME := $(patsubst %/,%,$(call FixPath,$(SMING_HOME))) - -ifeq (,$(wildcard $(SMING_HOME)/Arch/$(SMING_ARCH)/build.mk)) -$(error Arch '$(SMING_ARCH)' not found) -endif - MAKECMDGOALS ?= all # Some components play nicer if they avoid doing stuff doing a cleanup @@ -90,7 +112,6 @@ export COMPILE := gcc DEBUG_VARS += ARCH_BASE ARCH_BASE := $(SMING_HOME)/Arch/$(SMING_ARCH) -ARCH_SYS = $(ARCH_BASE)/System ARCH_CORE = $(ARCH_BASE)/Core ARCH_TOOLS = $(ARCH_BASE)/Tools ARCH_COMPONENTS = $(ARCH_BASE)/Components @@ -130,15 +151,6 @@ $(error Cannot find Python installation - check PATH or PYTHON environment varia endif -V ?= $(VERBOSE) -ifeq ("$(V)","1") - Q := - vecho := @true -else - Q := @ - vecho := @echo -endif - # Common C/C++ flags passed to user libraries CPPFLAGS = \ -Wl,-EL \ @@ -146,6 +158,11 @@ CPPFLAGS = \ -fdata-sections \ -ffunction-sections +# Required to access peripheral registers using structs +# e.g. `uint32_t value: 8` sitting at a byte or word boundary will be 'optimised' to +# an 8-bit fetch/store instruction which will not work; it must be a full 32-bit access. +CPPFLAGS += -fstrict-volatile-bitfields + CPPFLAGS += \ -Wall \ -Wpointer-arith \ @@ -181,12 +198,16 @@ else CPPFLAGS += -Os -g endif -CXXFLAGS += -felide-constructors +CXXFLAGS += \ + -felide-constructors \ + -fno-rtti \ + -fno-exceptions ifneq ($(STRICT),1) CXXFLAGS += -Wno-reorder endif +ifndef MAKE_CLEAN include $(ARCH_BASE)/build.mk # Detect compiler version @@ -194,8 +215,9 @@ DEBUG_VARS += GCC_VERSION GCC_VERSION := $(shell $(CC) -dumpversion) # Use c11 by default. Every architecture can override it -SMING_C_STD ?= c11 -CFLAGS += -std=$(SMING_C_STD) +DEBUG_VARS += SMING_C_STD +SMING_C_STD ?= c11 +CFLAGS += -std=$(SMING_C_STD) # Select C++17 if supported, defaulting to C++11 otherwise DEBUG_VARS += SMING_CXX_STD @@ -215,13 +237,15 @@ ifneq ($(GCC_UPGRADE_URL),) $(info Instructions for upgrading your compiler can be found here: $(GCC_UPGRADE_URL)) endif endif +endif DEBUG_VARS += USER_LIBDIR OUT_BASE BUILD_BASE FW_BASE TOOLS_BASE SMING_ARCH_FULL -ifdef ESP_VARIANT -SMING_ARCH_FULL := $(SMING_ARCH)/$(ESP_VARIANT) -else +# Architectures with multiple variants require an extra subdirectory +ifeq (,$(word 2,$(ARCH_$(SMING_ARCH)_SOC))) SMING_ARCH_FULL := $(SMING_ARCH) +else +SMING_ARCH_FULL := $(SMING_ARCH)/$(SMING_SOC) endif OUT_BASE := out/$(SMING_ARCH_FULL)/$(BUILD_TYPE) @@ -233,13 +257,27 @@ USER_LIBDIR = $(SMING_HOME)/$(OUT_BASE)/lib # Component (user) libraries have a special prefix so linker script can identify them CLIB_PREFIX := clib- -# Convert string to upper/lower case -# 1 -> String -ToUpper = $(shell echo "$1" | tr 'a-z' 'A-Z') -ToLower = $(shell echo "$1" | tr 'A-Z' 'a-z') +# Use with LDFLAGS to define a symbol alias +# $1 -> List of alias=name pairs +define DefSym +$(foreach n,$1,-Wl,--defsym=$n) +endef + +# Use with LDFLAGS to undefine a list of symbols +# $1 -> List of symbols +define Undef +$(foreach n,$1,-u $n) +endef -# Use with LDFLAGS to undefine and wrap a list of functions +# Use with LDFLAGS to wrap a list of symbols +# $1 -> List of symbols define Wrap +$(foreach n,$1,-Wl,-wrap,$n) +endef + +# Use with LDFLAGS to undefine and wrap a list of symbols +# $1 -> List of symbols +define UndefWrap $(foreach n,$1,-u $n -Wl,-wrap,$n) endef @@ -252,124 +290,19 @@ define ClangFormat done endef -# Calculate a hash string for appending to library names, etc. -# $1 -> Name of variable containing data to be hashed -define CalculateVariantHash -$(firstword $(shell echo -n $($1) | md5sum -t)) -endef - -# Fetch full path for submodules matching given pattern -# Note that scanning .gitmodules is considerably quicker than using GIT -# $1 -> Path to repo working directory -# $2 -> Path pattern to match -define ScanGitModules -$(patsubst %,$(abspath $1/%),$(subst path = ,,$(shell grep -o 'path = $2' '$1/.gitmodules'))) -endef - define ListSubmodules $(call ScanGitModules,$(SMING_HOME)/..,.*) endef -# List immediate sub-directories for a list of root directories -# Results are sorted and without trailing path separator -# $1 -> Root paths -define ListSubDirs -$(foreach d,$(dir $(wildcard $1/*/.)),$(d:/=)) -endef - -# Check that $2 is a valid sub-directory of $1. Return empty string if not. -# $1 -> Parent directory -# $2 -> Sub-directory -# During wildcard searches, paths with spaces cause recursion. -define IsSubDir -$(if $(subst $(1:/=),,$(2:/=)),$(findstring $(1:/=),$2),) -endef - -# List sub-directories recursively for a single root directory -# Results are sorted and without trailing path separator -# Sub-directories with spaces are skipped -# $1 -> Root path -define ListAllSubDirsSingle -$(foreach d,$(dir $(wildcard $1/*/.)),$(if $(call IsSubDir,$1,$d),$(d:/=) $(call ListAllSubDirs,$(d:/=)))) -endef - -# List sub-directories recursively for a list of root directories -# Results are sorted and without trailing path separator -# Sub-directories with spaces are skipped -# $1 -> Root paths -define ListAllSubDirs -$(foreach d,$1,$(call ListAllSubDirsSingle,$d)) -endef - -# Recursively search list of directories for matching files -# $1 -> Directories to scan -# $2 -> Filename filter -define ListAllFiles -$(wildcard $(foreach d,$(call ListAllSubDirs,$1),$d/$2)) -endef - - -# Display variable and list values, e.g. $(call PrintVariable,LIBS) -# $1 -> Name of variable containing values -# $2 -> (optional) tag to use instead of variable name -define PrintVariable - $(info $(if $2,$2,$1):) - $(foreach item,$($1),$(info - $(item))) -endef - -define PrintVariableSorted - $(info $(if $2,$2,$1):) - $(foreach item,$(sort $($1)),$(info - $(value item))) -endef - -# Display list of variable references with their values e.g. $(call PrintVariableRefs,DEBUG_VARS) -# $1 -> Name of variable containing list of variable names -# $2 -> (optional) tag to use instead of variable name -define PrintVariableRefs - $(info $(if $2,$2,$1):) - $(foreach item,$(sort $($1)),$(info - $(item) = $(value $(item))) ) -endef - -# -# Get directory without trailing separator -# $1 -> List of directories -dirx = $(patsubst %/,%,$(dir $1)) - # Extract commented target information from makefiles and display -# Based on code from https://suva.sh/posts/well-documented-makefiles/ define PrintHelp @echo @echo Welcome to the Sming build system! - @$(AWK) 'BEGIN { \ - FS = "(:.*##)|(##@)"; \ - printf "Usage:\n make \033[1;36m\033[0m\n"; \ - } /^##@/ { \ - group = $$2; \ - groups[group] = group; \ - } /^[a-zA-Z0-9_-]+:.*?##/ { \ - targets[$$1, group] = $$2; \ - } \ - END { \ - for (g in groups) { \ - printf "\n\033[1m%s\033[0m\n", g; \ - for (t in targets) { \ - split(t, sep, SUBSEP); \ - if (sep[2] == g) \ - printf " \033[1;36m%-20s\033[0m %s\n", sep[1], targets[t] \ - } \ - } \ - } ' $(foreach f,$(MAKEFILE_LIST),"$(f)") + @$(AWK) -f $(SMING_HOME)/help.awk $(foreach f,$(MAKEFILE_LIST),"$(f)") @echo endef -# Give relative or absolute source paths, convert them all to absolute -# $1 -> source root directory -# $2 -> file path(s) -define AbsoluteSourcePath -$(foreach f,$2,$(abspath $(if $(filter /%,$f),$f,$1/$f))) -endef - # Write config variables to a file # $1 -> Output filename # $2 -> List of variable names to output @@ -407,12 +340,22 @@ define TryApplyPatch fi endef +# Fetch and patch a submodule +# $1 -> submodule parent path +# $2 -> submodule name +define FetchAndPatch + $(info ) + $(info Fetching submodule '$2' ...) + $(Q) cd $1 && ( \ + rm -rf $2; \ + if [ -f "$2.no-recursive" ]; then OPTS=""; else OPTS="--recursive"; fi; \ + $(GIT) submodule update --init --force $$OPTS $2 \ + ) + $(Q) $(call TryApplyPatch,$1/$2,$2.patch) +endef + # Update and patch submodule # Patch file is either in submodule parent directory itself or subdirectory .patches from there %/.submodule: - $(info ) - $(info Fetching submodule '$*' ...) - $(Q) cd $(abspath $*/..) && (rm -rf $(*F); $(GIT) submodule update --init --force --recursive $(*F)) - $(Q) $(call TryApplyPatch,$*,$(*F).patch) + $(call FetchAndPatch,$(abspath $*/..),$(*F)) $(Q) touch $@ - diff --git a/Sming/building.rst b/Sming/building.rst index 89fe66115c..81fe2114f1 100644 --- a/Sming/building.rst +++ b/Sming/building.rst @@ -39,11 +39,21 @@ These are the main variables you need to be aware of: - **Esp8266** The default if not specified. :envvar:`ESP_HOME` must also be provided to locate SDK & tools. - - **Esp32** {todo} + - **Esp32** Supports ESP32 architecture. - **Host** builds a version of the library for native host debugging on Linux or Windows + - **Rp2040** Supports Raspberry Pi RP2040-based boards. + + +.. envvar:: SMING_SOC + + Some architectures support families of SOCs with different capabilities. + Set this value to the specific variant being targeted. + + Will automatically set SMING_ARCH to the appropriate value. + .. envvar:: SMING_CPP_STD @@ -190,10 +200,10 @@ Directory layout The main Sming repo. is laid out like this:: |_ sming/ - |_ .appveyor.yml CI testing (Windows) - |_ .travis.yml CI testing (Linux) - |_ .appveyor/ CI scripts (Windows) - |_ .travis CI scripts (Linux) + |_ .appveyor.yml CI testing + |_ .travis.yml CI testing + |_ .readthedocs.yml Documentation build + |_ lgtm.yml CI Static code analysis |_ docs/ Sming documentation |_ samples/ Samples to demonstrate specific Sming features or libraries |_ Sming/ @@ -242,6 +252,13 @@ The main Sming repo. is laid out like this:: | |_ ... |_ tests/ Integration test applications |_ ... + |_ Tools/ + |_ ci CI testing + |_ Docker + |_ ide IDE environment support tools + |_ Python Shared python scripts + |_ travis CI testing + A typical Project looks like this:: @@ -367,7 +384,7 @@ one of the following lists: firmware images re-generated if any of these variables are changed. For example, ``make RBOOT_ROM_0=new-rom-file`` rewrites the firmware image using the given filename. (Also, as the value is cached, if you then do - ``make flashapp`` that same iamge gets flashed.) + ``make flashapp`` that same image gets flashed.) .. envvar:: CACHE_VARS @@ -532,6 +549,11 @@ changed as required. Relative paths to dependent submodule directories for this Component. These will be fetched/patched automatically before building. + Default behaviour is to initialise submodules recursively. + To prevent this behaviour and initialise only the top-level submodule, + add a file to the parent directory with the same name as the submodule + and a ``.no-recursive`` extension. + .. envvar:: COMPONENT_SRCDIRS Locations for source code relative to COMPONENT_PATH (defaults to “. src”) @@ -634,6 +656,9 @@ never overwritten. Will be visible **ONLY** to C++ code within the component. +.. envvar:: COMPONENT_CPPFLAGS + + Will be visible to both C and C++ code within the component. .. important:: diff --git a/Sming/component-wrapper.mk b/Sming/component-wrapper.mk index ae7d2c4cfd..f6da0f6a34 100644 --- a/Sming/component-wrapper.mk +++ b/Sming/component-wrapper.mk @@ -27,6 +27,7 @@ CUSTOM_BUILD := COMPONENT_TARGETS := EXTRA_OBJ := COMPONENT_CFLAGS := +COMPONENT_CPPFLAGS := COMPONENT_CXXFLAGS := COMPONENT_VARS := COMPONENT_RELINK_VARS := @@ -106,6 +107,7 @@ endif ifeq (,$(CUSTOM_BUILD)) CFLAGS += $(COMPONENT_CFLAGS) +CPPFLAGS += $(COMPONENT_CPPFLAGS) CXXFLAGS += $(COMPONENT_CXXFLAGS) # GCC 10 escapes ':' in path names which breaks GNU make for Windows so filter them @@ -151,7 +153,7 @@ endef # $1 -> source root directory # $2 -> file path(s) define ResolveObjPath -$(foreach f,$2,$(patsubst $(SMING_HOME)/%,%,$(patsubst $1/%,%,$f))) +$(foreach f,$2,$(patsubst /%,%,$(patsubst $(SMING_HOME)/%,%,$(patsubst $1/%,%,$f)))) endef # All source files, absolute paths diff --git a/Sming/component.mk b/Sming/component.mk index b24c7014e1..32d727928d 100644 --- a/Sming/component.mk +++ b/Sming/component.mk @@ -38,13 +38,6 @@ COMPONENT_SRCDIRS += Services/CommandProcessing endif GLOBAL_CFLAGS += -DENABLE_CMD_EXECUTOR=$(ENABLE_CMD_EXECUTOR) -# => MQTT -# Flags for compatability with old versions (most of them should disappear with the next major release) -COMPONENT_VARS += MQTT_NO_COMPAT -ifeq ($(MQTT_NO_COMPAT),1) - GLOBAL_CFLAGS += -DMQTT_NO_COMPAT=1 -endif - # RELINK_VARS += DISABLE_NETWORK DISABLE_NETWORK ?= 0 @@ -62,13 +55,6 @@ ifeq ($(DISABLE_WIFI),1) GLOBAL_CFLAGS += -DDISABLE_WIFI=1 endif -# WiFi settings may be provide via Environment variables -CONFIG_VARS += WIFI_SSID WIFI_PWD -ifdef WIFI_SSID - APP_CFLAGS += -DWIFI_SSID=\"$(WIFI_SSID)\" - APP_CFLAGS += -DWIFI_PWD=\"$(WIFI_PWD)\" -endif - # => LOCALE COMPONENT_VARS += LOCALE ifdef LOCALE @@ -108,7 +94,9 @@ COM_SPEED ?= 115200 # Default COM port speed used in code CONFIG_VARS += COM_SPEED_SERIAL COM_SPEED_SERIAL ?= $(COM_SPEED) -APP_CFLAGS += -DCOM_SPEED_SERIAL=$(COM_SPEED_SERIAL) +APP_CFLAGS += \ + -DCOM_SPEED_SERIAL=$(COM_SPEED_SERIAL) \ + -DSERIAL_BAUD_RATE=$(COM_SPEED_SERIAL) # Task queue counter to check for overflows COMPONENT_VARS += ENABLE_TASK_COUNT diff --git a/Sming/help.awk b/Sming/help.awk new file mode 100644 index 0000000000..1eb00312ee --- /dev/null +++ b/Sming/help.awk @@ -0,0 +1,21 @@ +# Extract commented target information from makefiles and display +# Based on code from https://suva.sh/posts/well-documented-makefiles/ +BEGIN { + FS = "(:.*##)|(##@)" + printf "Usage:\n make \033[1;36m\033[0m\n" +} /^##@/ { + group = $2 + groups[group] = group +} /^[a-zA-Z0-9_-]+:.*?##/ { + targets[$1, group] = $2 +} +END { + for (g in groups) { + printf "\n\033[1m%s\033[0m\n", g + for (t in targets) { + split(t, sep, SUBSEP) + if (sep[2] == g) + printf " \033[1;36m%-20s\033[0m %s\n", sep[1], targets[t] + } + } +} diff --git a/Sming/options.json b/Sming/options.json index a713d4bc65..d321da5dce 100644 --- a/Sming/options.json +++ b/Sming/options.json @@ -1,4 +1,20 @@ { + "1m": { + "description": "Set Flash size to 1MByte", + "devices": { + "spiFlash": { + "size": "1M" + } + } + }, + "2m": { + "description": "Set Flash size to 2MByte", + "devices": { + "spiFlash": { + "size": "2M" + } + } + }, "4m": { "description": "Set Flash size to 4MByte", "devices": { diff --git a/Sming/project.mk b/Sming/project.mk index 828ef31c58..515d1cad3c 100644 --- a/Sming/project.mk +++ b/Sming/project.mk @@ -2,7 +2,7 @@ # # Created by Espressif # UDK modifications by CHERTS -# Cross platform compatability by kireevco +# Cross platform compatibility by kireevco # # This makefile is invoked in the application's directory # @@ -18,7 +18,7 @@ endif .NOTPARALLEL: .PHONY: all -all: checkdirs submodules ##(default) Build all Component libraries +all: checksoc checkdirs submodules ##(default) Build all Component libraries $(MAKE) components application # Load current build type from file @@ -31,6 +31,7 @@ BUILD_SUBTYPE_FILE = out/$(SMING_ARCH)/build-subtype.mk # include $(SMING_HOME)/build.mk + # # The build system supports several types of configuration variable. The name of the variable needs to be # added to only one of the xxx_VARS lists below, depending on the required behaviour. @@ -77,13 +78,16 @@ CONFIG_VARS += USER_CFLAGS DEBUG_VARS += GLOBAL_CFLAGS GLOBAL_CFLAGS = \ -DSMING_ARCH=$(SMING_ARCH) \ - -DESP_VARIANT=$(ESP_VARIANT) \ - -DSUBARCH_$(call ToUpper,$(ESP_VARIANT))=1 \ + -DSMING_SOC=$(SMING_SOC) \ -DPROJECT_DIR=\"$(PROJECT_DIR)\" \ -DSMING_HOME=\"$(SMING_HOME)\" \ $(USER_CFLAGS) CPPFLAGS += $(GLOBAL_CFLAGS) +# Provide an SOC_xxxx value for code use, analogous to ARCH_xxx +SMING_SOC_VAR := SOC_$(call ToUpper,$(SMING_SOC)) +GLOBAL_CFLAGS += -D$(SMING_SOC_VAR)=1 + # Targets to be added as dependencies of the application, built directly in this make instance CUSTOM_TARGETS := @@ -109,10 +113,8 @@ DEBUG_VARS += TARGET_OUT_0 CACHE_VARS += APP_NAME APP_NAME ?= app -# Firmware memory layout info files -FW_MEMINFO_NEW := $(FW_BASE)/fwMeminfo.new -FW_MEMINFO_OLD := $(FW_BASE)/fwMeminfo.old -FW_MEMINFO_SAVED := out/fwMeminfo +# Firmware memory layout info file +FW_MEMINFO := $(FW_BASE)/fwMeminfo.txt # List of Components we're going to parse, with duplicate libraries removed COMPONENTS := Sming @@ -147,7 +149,12 @@ COMPONENTS_EXTRA_INCDIR := APPCODE := # Python requirements.txt collected from components -PYTHON_REQUIREMENTS := +PYTHON_REQUIREMENTS := $(abspath $(SMING_HOME)/../Tools/requirements.txt) + +# SOCs supported by project +DEBUG_VARS += PROJECT_SOC +PROJECT_SOC := $(AVAILABLE_SOCS) +export PROJECT_SOC # # This macro sets the default component variables before including the (optional) component.mk file. @@ -157,11 +164,13 @@ PYTHON_REQUIREMENTS := # $3 -> Build directory # $4 -> Output library directory define ParseComponent +ifneq (,$$(findstring $(SMING_SOC),$$(PROJECT_SOC))) $(if $V,$(info -- Parsing $1)) $(if $2,,$(error Component '$1' not found)) SUBMODULES += $(filter $2,$(ALL_SUBMODULES)) CMP_$1_PATH := $2 CMP_$1_LIBDIR := $4 +COMPONENT_SOC := * COMPONENT_LIBDIR := $$(CMP_$1_LIBDIR) COMPONENT_INCDIRS := include COMPONENT_NAME := $1 @@ -193,6 +202,11 @@ LIBS += $$(EXTRA_LIBS) CMP_$1_LDFLAGS := $$(EXTRA_LDFLAGS) LDFLAGS += $$(CMP_$1_LDFLAGS) endif +CMP_$1_SOC := $$(filter $$(subst *,%,$$(COMPONENT_SOC)),$(AVAILABLE_SOCS)) +ifeq (,$$(CMP_$1_SOC)) +$$(error Unknown SOC: $$(COMPONENT_SOC)) +endif +PROJECT_SOC := $$(filter $$(CMP_$1_SOC),$$(PROJECT_SOC)) CMP_$1_PREREQUISITES := $$(COMPONENT_PREREQUISITES) CMP_$1_TARGETS := $$(COMPONENT_TARGETS) CMP_$1_BUILD_DIR := $$(COMPONENT_BUILD_DIR) @@ -212,6 +226,7 @@ PARSED_COMPONENTS += $$(DEPENDENCIES) $$(call ParseComponentList,$$(DEPENDENCIES)) endif endif # App +endif # PROJECT_SOC endef # ParseComponent # Build a list of all available Components @@ -234,10 +249,10 @@ $(eval $(call ParseComponent,App,$(CURDIR),$(BUILD_BASE),$(abspath $(APP_LIBDIR) # Load cached configuration variables. On first run this file won't exist, so all values # will be as specified by defaults or in project's component.mk file. -# Values may be overriden via command line to update the cache. +# Values may be overridden via command line to update the cache. # If file has become corrupted it will prevent cleaning, so make this conditional. CONFIG_CACHE_FILE := $(OUT_BASE)/config.mk -ifndef MAKE_CLEAN +ifeq (,$(filter config-clean dist-clean,$(MAKECMDGOALS))) -include $(CONFIG_CACHE_FILE) endif @@ -245,7 +260,8 @@ endif CONFIG_DEBUG_FILE := $(OUT_BASE)/debug.mk # Append standard search directories to any defined by the application -ALL_SEARCH_DIRS := $(call FixPath,$(abspath $(COMPONENT_SEARCH_DIRS))) +COMPONENT_SEARCH_DIRS := $(call FixPath,$(COMPONENT_SEARCH_DIRS)) +ALL_SEARCH_DIRS := $(abspath $(COMPONENT_SEARCH_DIRS)) COMPONENTS_EXTRA_INCDIR += $(ALL_SEARCH_DIRS) ALL_SEARCH_DIRS += $(ARCH_COMPONENTS) $(SMING_HOME)/Components $(SMING_HOME)/Libraries @@ -343,6 +359,22 @@ $(foreach v,$(EXPORT_VARS),$(eval export $v)) ##@Building +.PHONY: sample +ifeq (,$(findstring $(SMING_SOC),$(PROJECT_SOC))) +sample: + $(info Not building: Sample doesn't support $(SMING_SOC)) +else +sample: all +endif + + +.PHONY: checksoc +checksoc: +ifeq (,$(findstring $(SMING_SOC),$(PROJECT_SOC))) + $(error Project only supports: $(PROJECT_SOC)) +endif + + COMPONENT_DIRS := $(foreach d,$(ALL_SEARCH_DIRS),$(wildcard $d/*)) %/component.mk: @@ -536,7 +568,12 @@ export HOST_PARAMETERS .PHONY: ide-vscode-update ide-vscode-update: $(Q) SMING_HOME=$(SMING_HOME) OUT_BASE=$(OUT_BASE) \ - $(PYTHON) $(SMING_HOME)/../Tools/vscode/setup.py + $(PYTHON) $(SMING_TOOLS)/ide/vscode/setup.py + +.PHONY: ide-eclipse +ide-eclipse: ##Create Eclipse project configuration + $(Q) SMING_HOME=$(SMING_HOME) OUT_BASE=$(OUT_BASE) \ + $(PYTHON) $(SMING_TOOLS)/ide/eclipse/setup.py ##@Testing @@ -558,14 +595,14 @@ tcp-serial-redirect: ##Redirect COM port to TCP port ifdef WSL_ROOT $(Q) cmd.exe /c start /MIN python3 $(WSL_ROOT)/$(TCP_SERIAL_REDIRECT) else - $(Q) gnome-terminal -- bash -c "$(PYTHON) $(TCP_SERIAL_REDIRECT)" + $(Q) $(call DetachCommand,$(PYTHON) $(TCP_SERIAL_REDIRECT)) endif ##@Help .PHONY: list-config -list-config: ##Print the contents of build variables +list-config: checksoc ##Print the contents of build variables $(info ) $(info ** Sming build configuration **) $(info ) @@ -602,7 +639,7 @@ define PrintComponentInfo endef .PHONY: list-components -list-components: ##Print details of all Components for this project +list-components: checksoc ##Print details of all Components for this project $(call PrintVariable,ALL_SEARCH_DIRS) $(if $(V),$(call PrintVariable,ALL_COMPONENT_DIRS)) $(info Components:) @@ -652,8 +689,9 @@ $(shell mkdir -p $(dir $1); endef # Update build type cache -$(eval $(call WriteCacheValues,$(BUILD_TYPE_FILE),SMING_ARCH SMING_RELEASE STRICT)) -$(eval $(call WriteCacheValues,$(BUILD_SUBTYPE_FILE),ESP_VARIANT)) +ifndef MAKE_CLEAN +$(eval $(call WriteCacheValues,$(BUILD_TYPE_FILE),SMING_SOC SMING_RELEASE STRICT)) +endif # Update config cache file # We store the list of variable names to ensure that any not actively in use don't get lost @@ -671,3 +709,42 @@ CACHED_VAR_NAMES := $(sort $(CACHED_VAR_NAMES) $(CONFIG_VARS) $(RELINK_VARS) $(C $(eval $(call WriteConfigCache,$(CONFIG_CACHE_FILE),CACHED_VAR_NAMES)) $(eval $(call WriteCacheValues,$(CONFIG_DEBUG_FILE),$(sort $(DEBUG_VARS)))) endif + + +##@Configuration + +export UNAME +# List of all Kconfig files +export KCONFIG_FILES = $(wildcard $(foreach c,$(filter-out Sming,$(COMPONENTS)),$(CMP_$c_PATH)/Kconfig)) +# File containing list of component Kconfig file paths (created by cfgtool) +export KCONFIG_COMPONENTS = $(OUT_BASE)/kconfig.in + +KCONFIG := $(SMING_HOME)/Kconfig +KCONFIG_CONFIG := $(OUT_BASE)/kconfig.config + +KCONFIG_ENV := \ + CONFIG_= \ + KCONFIG=$(KCONFIG) \ + KCONFIG_CONFIG=$(KCONFIG_CONFIG) + +CFGTOOL_CMDLINE = $(KCONFIG_ENV) $(PYTHON) $(SMING_TOOLS)/cfgtool.py $(CONFIG_CACHE_FILE) + +.PHONY: menuconfig +menuconfig: checksoc ##Run option editor + $(Q) $(CFGTOOL_CMDLINE) --to-kconfig + $(Q) $(KCONFIG_ENV) $(PYTHON) -m menuconfig $(SMING_HOME)/Kconfig + $(Q) $(CFGTOOL_CMDLINE) --from-kconfig + +.PHONY: list-soc +list-soc: ##List supported and available SOCs + @echo "Available SoCs: $(AVAILABLE_SOCS)" + @echo "Project support:" + @$(foreach s,$(AVAILABLE_SOCS),$(MAKE) --no-print-directory --silent MAKE_CLEAN=1 SMING_ARCH= SMING_SOC=$s checksoc-print; ) + +.PHONY: list-soc-check +checksoc-print: +ifeq (,$(findstring $(SMING_SOC),$(PROJECT_SOC))) + $(info - NO: $(SMING_SOC)) +else + $(info - YES: $(SMING_SOC)) +endif diff --git a/Sming/spiffs-2m.hw b/Sming/spiffs-2m.hw new file mode 100644 index 0000000000..eeed997118 --- /dev/null +++ b/Sming/spiffs-2m.hw @@ -0,0 +1,12 @@ +{ + "name": "Single SPIFFS partition (2M flash)", + "base_config": "spiffs", + "options": [ + "2m" + ], + "partitions": { + "spiffs0": { + "address": "0x100000" + } + } +} \ No newline at end of file diff --git a/Sming/util.mk b/Sming/util.mk new file mode 100644 index 0000000000..53d64bcf26 --- /dev/null +++ b/Sming/util.mk @@ -0,0 +1,135 @@ +# +# Make utility definitions +# +# These definitions must have no external dependencies. +# They are used for both code and documentation builds. +# + +# Convert Windows paths to POSIX paths +ifeq ($(OS),Windows_NT) +# Powershell does weird things to this variable, revert to default +override MAKE := make +FixPath = $(subst //,/,$(subst \,/,/$(subst :,,$1))) +else +FixPath = $1 +endif + +V ?= $(VERBOSE) +ifeq ("$(V)","1") + Q := + vecho := @true +else + Q := @ + vecho := @echo +endif + +# Convert string to upper/lower case +# 1 -> String +ToUpper = $(shell echo "$1" | tr 'a-z' 'A-Z') +ToLower = $(shell echo "$1" | tr 'A-Z' 'a-z') + +# Calculate a hash string for appending to library names, etc. +# $1 -> Name of variable containing data to be hashed +define CalculateVariantHash +$(firstword $(shell echo -n $($1) | md5sum -t)) +endef + +# Fetch full path for submodules matching given pattern +# Note that scanning .gitmodules is considerably quicker than using GIT +# $1 -> Path to repo working directory +# $2 -> Path pattern to match +define ScanGitModules +$(patsubst %,$(abspath $1/%),$(subst path = ,,$(shell grep -o 'path = $2' '$1/.gitmodules'))) +endef + +# List immediate sub-directories for a list of root directories +# Results are sorted and without trailing path separator +# $1 -> Root paths +define ListSubDirs +$(foreach d,$(dir $(wildcard $1/*/.)),$(d:/=)) +endef + +# Check that $2 is a valid sub-directory of $1. Return empty string if not. +# $1 -> Parent directory +# $2 -> Sub-directory +# During wildcard searches, paths with spaces cause recursion. +define IsSubDir +$(if $(subst $(1:/=),,$(2:/=)),$(findstring $(1:/=),$2),) +endef + +# List sub-directories recursively for a single root directory +# Results are sorted and without trailing path separator +# Sub-directories with spaces are skipped +# $1 -> Root path +define ListAllSubDirsSingle +$(foreach d,$(dir $(wildcard $1/*/.)),$(if $(call IsSubDir,$1,$d),$(d:/=) $(call ListAllSubDirs,$(d:/=)))) +endef + +# List sub-directories recursively for a list of root directories +# Results are sorted and without trailing path separator +# Sub-directories with spaces are skipped +# $1 -> Root paths +define ListAllSubDirs +$(foreach d,$1,$(call ListAllSubDirsSingle,$d)) +endef + +# Recursively search list of directories for matching files +# $1 -> Directories to scan +# $2 -> Filename filter +define ListAllFiles +$(foreach d,$1 $(call ListAllSubDirs,$1),$(wildcard $(foreach f,$2,$d/$f))) +endef + + +# Display variable and list values, e.g. $(call PrintVariable,LIBS) +# $1 -> Name of variable containing values +# $2 -> (optional) tag to use instead of variable name +define PrintVariable + $(info $(if $2,$2,$1):) + $(foreach item,$($1),$(info - $(item))) +endef + +define PrintVariableSorted + $(info $(if $2,$2,$1):) + $(foreach item,$(sort $($1)),$(info - $(value item))) +endef + +# Display list of variable references with their values e.g. $(call PrintVariableRefs,DEBUG_VARS) +# $1 -> Name of variable containing list of variable names +# $2 -> (optional) tag to use instead of variable name +define PrintVariableRefs + $(info $(if $2,$2,$1):) + $(foreach item,$(sort $($1)),$(info - $(item) = $(value $(item))) ) +endef + +# +# Get directory without trailing separator +# $1 -> List of directories +dirx = $(patsubst %/,%,$(dir $1)) + +# Give relative or absolute source paths, convert them all to absolute +# $1 -> source root directory +# $2 -> file path(s) +define AbsoluteSourcePath +$(foreach f,$2,$(abspath $(if $(filter /%,$f),$f,$1/$f))) +endef + +# Run a command in a new terminal window +# $1 -> Command to execute +ifeq ($(UNAME),Windows) +DetachCommand = start $1 +else +DetachCommand = gnome-terminal -- bash -c "sleep 1; $1" +endif + + +# List of all soc configuration files +export SOC_CONFIG_FILES = $(sort $(wildcard $(SMING_HOME)/Arch/*/*-soc.json)) +AVAILABLE_SOCS := $(patsubst %-soc.json,%,$(notdir $(SOC_CONFIG_FILES))) + +# Provide variable for each architecture listing available SOCs +# $1 -> Architecture name +define SetArchSocs +ARCH_$1_SOC := $(patsubst $1/%-soc.json,%,$(filter $1/%,$(patsubst $(SMING_HOME)/Arch/%,%,$(SOC_CONFIG_FILES)))) +endef +$(foreach a,$(call ListSubDirs,$(SMING_HOME)/Arch),$(eval $(call SetArchSocs,$(notdir $a)))) diff --git a/Tools/Docker/appveyor/Dockerfile-Linux b/Tools/Docker/appveyor/Dockerfile-Linux new file mode 100644 index 0000000000..eec6f2a32c --- /dev/null +++ b/Tools/Docker/appveyor/Dockerfile-Linux @@ -0,0 +1,9 @@ +# Build an appveyor Linux container image with Sming tools installed +FROM appveyor/build-image:minimal-ubuntu-20.04 +ARG SMING_REPO=https://github.com/SmingHub/Sming +ARG SMING_BRANCH=develop +WORKDIR /tmp +RUN git clone ${SMING_REPO} --branch ${SMING_BRANCH} --depth 1 sming && \ + pwsh "sming/Tools/Docker/appveyor/setup.ps1" +USER appveyor +CMD [ "/bin/bash", "/scripts/entrypoint.sh" ] diff --git a/Tools/Docker/appveyor/Dockerfile-Windows b/Tools/Docker/appveyor/Dockerfile-Windows new file mode 100644 index 0000000000..215964f820 --- /dev/null +++ b/Tools/Docker/appveyor/Dockerfile-Windows @@ -0,0 +1,7 @@ +# Build an appveyor Windows container image with Sming tools installed +FROM appveyor/build-image:minimal-windowsservercore-ltsc2019 +ARG SMING_REPO=https://github.com/SmingHub/Sming +ARG SMING_BRANCH=develop +WORKDIR /tmp +RUN git clone %SMING_REPO% --branch %SMING_BRANCH% --depth 1 sming && \ + pwsh "sming/Tools/Docker/appveyor/setup.ps1" diff --git a/Tools/Docker/appveyor/README.rst b/Tools/Docker/appveyor/README.rst new file mode 100644 index 0000000000..41c38392ef --- /dev/null +++ b/Tools/Docker/appveyor/README.rst @@ -0,0 +1,5 @@ +Appveyor Build Images +===================== + +See https://sming.readthedocs.io/en/latest/information/develop/ci.html for details. + diff --git a/Tools/Docker/appveyor/setup.ps1 b/Tools/Docker/appveyor/setup.ps1 new file mode 100644 index 0000000000..66fcd84354 --- /dev/null +++ b/Tools/Docker/appveyor/setup.ps1 @@ -0,0 +1,23 @@ +#!/usr/bin/env pwsh +# +# Called indirectly via appveyor build script +# + +cd /tmp +$env:SMING_HOME = "$(pwd)/sming/Sming" +. sming/Tools/ci/setenv.ps1 + +if($IsWindows) { + choco install -y --no-progress python3 --version 3.9 + choco install -y --no-progress cmake llvm + sming/Tools/ci/install.cmd all doc +} else { + $env:EXTRA_PACKAGES = "clang iproute2" + sming/Tools/install.sh all doc fonts +} + +pushd "$env:IDF_PATH" +git submodule update --init --recursive +popd + +Remove-Item sming, downloads -Force -Recurse diff --git a/Tools/Docker/cli/Dockerfile b/Tools/Docker/cli/Dockerfile index 4a49c5cd20..707e9ded60 100644 --- a/Tools/Docker/cli/Dockerfile +++ b/Tools/Docker/cli/Dockerfile @@ -1,23 +1,5 @@ FROM ubuntu -# ------------------------------------------------------------------------------ -# Set Environment -# ------------------------------------------------------------------------------ - -# Common -ENV SMING_HOME /opt/Sming/Sming -ENV PYTHON /usr/bin/python3 - -# Esp8266 -#ENV UDK_ROOT /opt/esp-open-sdk -ENV EQT_ROOT /opt/esp-quick-toolchain -ENV ESP_HOME $EQT_ROOT - -# Esp32 -ENV IDF_PATH /opt/esp-idf -ENV IDF_TOOLS_PATH /opt/esp32 -ENV ESP32_PYTHON_PATH $PYTHON - # ------------------------------------------------------------------------------ # Pre-requisites # ------------------------------------------------------------------------------ @@ -34,10 +16,13 @@ RUN apt-get -y update \ # Fetch Sming and install tools # ------------------------------------------------------------------------------ +ARG SMING_REPO=https://github.com/SmingHub/Sming ARG SMING_BRANCH=develop -ARG SMING_REPO=SmingHub/Sming ARG INSTALL_ARGS=all -RUN git clone -b $SMING_BRANCH -- https://github.com/$SMING_REPO $(readlink -m $SMING_HOME/..) +RUN git clone $SMING_REPO -b $SMING_BRANCH /opt/sming + +WORKDIR "/opt/sming" -RUN $SMING_HOME/../Tools/install.sh $INSTALL_ARGS +RUN Tools/install.sh $INSTALL_ARGS +RUN echo ". $(pwd)/Tools/export.sh" >> ~/.bashrc diff --git a/Tools/cfgtool.py b/Tools/cfgtool.py new file mode 100644 index 0000000000..df16f5018f --- /dev/null +++ b/Tools/cfgtool.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 +# +# Sming configuration management tool +# +# Used by build system to enable compatibility with Kconfig +# +# + +import argparse, configparser, os, sys, platform, kconfiglib + + +def load_config_vars(filename): + parser = configparser.ConfigParser() + parser.optionxform = str # preserve case + with open(filename) as f: + data = "[config]\n" + f.read() + data = data.replace(' := ', ' = ') + parser.read_string(data) + return parser['config'] + + +def set_kconfig_value(symbol, v): + """Convert values from Sming format to Kconfig format. + + Hidden variables are used to store choice selections and cannot be set directly. + Instead, locate the corresponding choice variable and set that. + """ + if symbol.visibility == 2: + if symbol.type is kconfiglib.BOOL: + v = 'y' if v == '1' else 'n' + elif symbol.type == kconfiglib._T_INT: + v = 0 if v == '' else v + symbol.set_value(v) + else: + for sym, cond in symbol.defaults: + if isinstance(cond, tuple): + cond = cond[1] + if not isinstance(cond, kconfiglib.Symbol): + continue + if v == sym.name and cond.type is kconfiglib.BOOL: + cond.set_value('y') + break + + +def fixpath(path): + """Paths in Windows can get a little weird""" + if len(path) > 2 and path[1] != ':' and platform.system() == 'Windows' and path[2] == '/': + return path[1] + ':' + path[2:] + return path + + +def createComponentsFile(): + fileList = os.environ['KCONFIG_FILES'].split() + compFile = os.environ['KCONFIG_COMPONENTS'] + with open(compFile, "w") as f: + for s in fileList: + f.write('source "%s"\n' % fixpath(s)) + + +def main(): + parser = argparse.ArgumentParser(description='Sming configuration management tool') + parser.add_argument('--to-kconfig', help="Convert Sming configuration to Kconfig format", action='store_true') + parser.add_argument('--from-kconfig', help="Convert Kconfig configuration to Sming format", action='store_true') + parser.add_argument('config_file', help='Source configuration file') + + args = parser.parse_args() + + if args.to_kconfig: + createComponentsFile() + + conf = kconfiglib.Kconfig(os.environ['KCONFIG']) + src = load_config_vars(args.config_file) + for k, v in src.items(): + c = conf.syms.get(k) + if c: + set_kconfig_value(c, v) + conf.write_config(os.environ['KCONFIG_CONFIG']) + elif args.from_kconfig: + conf = kconfiglib.Kconfig(os.environ['KCONFIG']) + conf.load_config(os.environ['KCONFIG_CONFIG']) + dst = load_config_vars(args.config_file) + varnames = set(dst.pop('CACHED_VAR_NAMES').split()) + + for k, sym in conf.syms.items(): + if sym.type is kconfiglib.UNKNOWN: + continue + if sym.env_var is not None: + continue + v = str(sym.user_value) if sym.user_value else "" + if sym.type is kconfiglib.BOOL: + v = "1" if v in ['y', '2'] else "0" + dst[sym.name] = v + varnames.add(sym.name) + with open(args.config_file, "w") as f: + for k, v in dst.items(): + f.write("%s=%s\n" % (k, v)) + f.write("\n") + varnames = list(varnames) + varnames.sort() + f.write("CACHED_VAR_NAMES := " + " ".join(varnames)) + else: + raise RuntimeError("No command specified") + + +if __name__ == '__main__': + try: + main() + except Exception as e: + print("** ERROR! %s" % e, file=sys.stderr) + sys.exit(2) diff --git a/Tools/ci/build.cmd b/Tools/ci/build.cmd index 9b53440f51..5124c44373 100644 --- a/Tools/ci/build.cmd +++ b/Tools/ci/build.cmd @@ -3,6 +3,12 @@ REM Windows build script REM Don't leak this set SMING_SECRET= +REM Build documentation job +if "%BUILD_DOCS%"=="true" ( + make -C %SMING_HOME%\..\docs html || goto :error + goto :EOF +) + subst z: %CI_BUILD_DIR% set SMING_HOME=z:\Sming @@ -11,7 +17,7 @@ call Arch\%SMING_ARCH%\Tools\ci\build.setup.cmd || goto :error env -set MAKE_PARALLEL=make -j2 +set MAKE_PARALLEL=make -j%NUMBER_OF_PROCESSORS% REM Move samples and tests into directory outside of the Sming repo. set SMING_PROJECTS_DIR=%CI_BUILD_DIR%\projects @@ -27,6 +33,10 @@ cd /d %SMING_PROJECTS_DIR%/samples/Basic_Blink make help make list-config +REM HostTests should build and run on all architectures +%MAKE_PARALLEL% -C "%SMING_PROJECTS_DIR%/tests/HostTests" + +REM Start Arch-specific tests cd /d %SMING_HOME% call Arch\%SMING_ARCH%\Tools\ci\build.run.cmd || goto :error goto :EOF diff --git a/Tools/ci/build.sh b/Tools/ci/build.sh index 55ec52efc3..fed80f9876 100755 --- a/Tools/ci/build.sh +++ b/Tools/ci/build.sh @@ -1,11 +1,19 @@ #!/bin/bash set -ex # exit with nonzero exit code if anything fails +# Build documentation job +if [ "$BUILD_DOCS" = "true" ]; then + unset SMING_SECRET + + make -C "$SMING_HOME/../docs" html + exit 0 +fi + # Build times benefit from parallel building -export MAKE_PARALLEL="make -j3" +export MAKE_PARALLEL="make -j$(nproc)" -cd $SMING_HOME -source Arch/$SMING_ARCH/Tools/ci/build.setup.sh +cd "$SMING_HOME" +source "Arch/$SMING_ARCH/Tools/ci/build.setup.sh" # Don't leak this! unset SMING_SECRET @@ -14,21 +22,24 @@ env # Move samples and tests into directory outside of the Sming repo. export SMING_PROJECTS_DIR=$HOME/projects -mkdir -p $SMING_PROJECTS_DIR -cd $SMING_HOME/.. -mv samples $SMING_PROJECTS_DIR -mv tests $SMING_PROJECTS_DIR +mkdir -p "$SMING_PROJECTS_DIR" +cd "$SMING_HOME/.." +mv samples "$SMING_PROJECTS_DIR" +mv tests "$SMING_PROJECTS_DIR" # Full compile checks please export STRICT=1 # Diagnostic info -cd $SMING_PROJECTS_DIR/samples/Basic_Blink +cd "$SMING_PROJECTS_DIR/samples/Basic_Blink" make help make list-config $MAKE_PARALLEL +# HostTests should build and run on all architectures +$MAKE_PARALLEL -C "$SMING_PROJECTS_DIR/tests/HostTests" + # Run ARCH build/tests -cd $SMING_HOME -source Arch/$SMING_ARCH/Tools/ci/build.run.sh +cd "$SMING_HOME" +source "Arch/$SMING_ARCH/Tools/ci/build.run.sh" diff --git a/Tools/ci/deploy.sh b/Tools/ci/deploy.sh index 69c5e7c75f..637858fa83 100755 --- a/Tools/ci/deploy.sh +++ b/Tools/ci/deploy.sh @@ -2,14 +2,14 @@ set -ex # exit with nonzero exit code if anything fails TAG=$1 -if [ -z $TAG ]; then +if [ -z "$TAG" ]; then printf "Usage:\n\t$0 \n"; exit 1; fi # [ Create archive of all submodules used in this release (pulled in during documentation build stage) ] -cd $CI_BUILD_DIR -ALL_SUBMODULE_DIRS=$(find $SMING_HOME -name '.submodule' | xargs dirname | sed 's/^\(.*\)\/\(Sming\/.*\)$/\2/') +cd "$CI_BUILD_DIR" +ALL_SUBMODULE_DIRS=$(find "$SMING_HOME" -name '.submodule' | xargs dirname | sed 's/^\(.*\)\/\(Sming\/.*\)$/\2/') SUBMODULE_ARCHIVE=sming-submodules.tgz tar czf $SUBMODULE_ARCHIVE $ALL_SUBMODULE_DIRS @@ -41,7 +41,7 @@ PACKAGES_TO_CHANGE="sming sming.source" for PACKAGE in $PACKAGES_TO_CHANGE; do - xmlstarlet ed --inplace -N "ns=http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd" -u "/ns:package/ns:metadata/ns:version" -v "$TAG" packages/$PACKAGE/*.nuspec; + xmlstarlet ed --inplace -N "ns=http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd" -u "/ns:package/ns:metadata/ns:version" -v "$TAG" "packages/$PACKAGE/$PACKAGE.nuspec"; done git config user.email "appveyor@sminghub.local" diff --git a/Tools/ci/install.cmd b/Tools/ci/install.cmd index aa49e52a34..90a5e342a5 100644 --- a/Tools/ci/install.cmd +++ b/Tools/ci/install.cmd @@ -1,11 +1,11 @@ -REM Windows install script +REM +REM Windows CI install script +REM -set SMINGTOOLS=https://github.com/SmingHub/SmingTools/releases/download/1.0 +if "%SMING_TOOLS_PREINSTALLED%" NEQ "" goto :EOF -python -m pip install --upgrade pip -r %SMING_HOME%\..\Tools\requirements.txt +if "%BUILD_DOCS%" == "true" ( + set INSTALL_OPTS=doc +) -rmdir /s /q c:\MinGW -curl -Lo MinGW.7z %SMINGTOOLS%/MinGW-2020-10-19.7z -7z -oC:\ x MinGW.7z - -call %SMING_HOME%\Arch\%SMING_ARCH%\Tools\ci\install.cmd +%SMING_HOME%\..\Tools\install.cmd %SMING_ARCH% %INSTALL_OPTS% diff --git a/Tools/ci/install.sh b/Tools/ci/install.sh new file mode 100755 index 0000000000..9fe5da5110 --- /dev/null +++ b/Tools/ci/install.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# +# CI installer script +# +# May also be used for library CI builds. The following variables must be set: +# +# CI_BUILD_DIR +# SMING_HOME +# +set -ex + +if [ -z "$SMING_TOOLS_PREINSTALLED" ]; then + +# appveyor-specific +export PYTHON=$HOME/venv3.9/bin/python +export ESP32_PYTHON_PATH=$HOME/venv3.9/bin +source "$HOME/venv3.9/bin/activate" + +if [ "$BUILD_DOCS" = "true" ]; then + INSTALL_OPTS="doc" +else + INSTALL_OPTS="fonts" +fi + +"$SMING_HOME/../Tools/install.sh" ${SMING_ARCH,,} $INSTALL_OPTS + +fi diff --git a/Tools/ci/library/Makefile b/Tools/ci/library/Makefile new file mode 100644 index 0000000000..01c044601b --- /dev/null +++ b/Tools/ci/library/Makefile @@ -0,0 +1,50 @@ +# +# Build/test a library for either: +# +# One SoC: Define SMING_SOC +# All SoCs for an architecture: Define SMING_ARCH +# All available SoCs: Neither SMING_SOC nor SMING_ARCH defined +# +# + +.SUFFIXES: +.NOTPARALLEL: + +ifeq (,$(SMING_HOME)) +$(error SMING_HOME not set) +endif + +include $(SMING_HOME)/util.mk + +APP_NAMES := $(patsubst $(CURDIR)/%,%,$(call ListSubDirs,samples) $(wildcard test)) + +ifneq (,$(SMING_SOC)) +all: $(SMING_SOC) +else ifneq (,$(SMING_ARCH)) +all: $(ARCH_$(SMING_ARCH)_SOC) +else +all: $(AVAILABLE_SOCS) +endif + +.PHONY: $(AVAILABLE_SOCS) +$(AVAILABLE_SOCS): + $(Q) $(MAKE) --no-print-directory -f $(firstword $(MAKEFILE_LIST)) SMING_SOC=$@ STRICT=1 apps run-test + +.PHONY: apps +apps: $(APP_NAMES) + +.PHONY: $(APP_NAMES) +$(APP_NAMES): + @printf "\n\n** Building $@ for $(SMING_SOC) **\n\n" + $(Q) $(MAKE) --no-print-directory -C $@ PIP_ARGS=-q python-requirements sample + +.PHONY: run-test +run-test: +ifeq (,$(wildcard test)) + @printf "\n\n** No test directory found - skipping **\n\n" +else ifeq ($(SMING_ARCH),Host) + $(Q) $(MAKE) --no-print-directory -C test execute +endif + +clean: + $(Q) rm -rf $(addsuffix /out,$(APP_NAMES)) diff --git a/Tools/ci/library/README.rst b/Tools/ci/library/README.rst new file mode 100644 index 0000000000..1a67036b44 --- /dev/null +++ b/Tools/ci/library/README.rst @@ -0,0 +1,4 @@ +Library CI support +================== + +See https://sming.readthedocs.io/en/latest/information/develop/ci.html for details. diff --git a/Tools/ci/library/appveyor.txt b/Tools/ci/library/appveyor.txt new file mode 100644 index 0000000000..c9f3ec79e3 --- /dev/null +++ b/Tools/ci/library/appveyor.txt @@ -0,0 +1,42 @@ +image: +- Ubuntu2004 +- Visual Studio 2019 + +environment: + SMING_REPO: https://github.com/SmingHub/Sming + SMING_BRANCH: develop + + matrix: + - SMING_ARCH: Host + + - SMING_ARCH: Esp8266 + + - SMING_ARCH: Esp32 + SMING_SOC: esp32 + + - SMING_ARCH: Esp32 + SMING_SOC: esp32s2 + + - SMING_ARCH: Esp32 + SMING_SOC: esp32c3 + + - SMING_ARCH: Rp2040 + +install: + - ps: | + Start-Process -FilePath git -ArgumentList "clone $env:SMING_REPO -b $env:SMING_BRANCH --depth 1 sming" -Wait -NoNewWindow + $env:COMPONENT_SEARCH_DIRS = (resolve-path "$pwd/..").path + sming/Tools/ci/setenv.ps1 + make -C "$env:SMING_HOME" "fetch-$env:APPVEYOR_PROJECT_SLUG" + + - cmd: | + if "%APPVEYOR_BUILD_WORKER_CLOUD%"=="" sming\Tools\ci\install.cmd %SMING_ARCH% %INSTALL_OPTS% + + - sh: | + if [ -z "$APPVEYOR_BUILD_WORKER_CLOUD" ]; then + . sming/Tools/ci/install.sh ${SMING_ARCH,,} $INSTALL_OPTS + fi + +build_script: + - sh: make -j$(nproc) -f $SMING_HOME/../Tools/ci/library/Makefile + - cmd: make -j%NUMBER_OF_PROCESSORS% -f %SMING_HOME%/../Tools/ci/library/Makefile diff --git a/Tools/ci/setenv.ps1 b/Tools/ci/setenv.ps1 new file mode 100644 index 0000000000..9113108898 --- /dev/null +++ b/Tools/ci/setenv.ps1 @@ -0,0 +1,40 @@ +if($IsWindows) { + $TOOLS_DIR = "C:\tools" +} else { + $TOOLS_DIR = "/opt" + sudo chown appveyor:appveyor /opt +} + +$env:CI_BUILD_DIR = (Resolve-Path "$PSScriptRoot/../..").Path +$env:SMING_HOME = Join-Path $env:CI_BUILD_DIR "Sming" + +# Esp8266 +$env:ESP_HOME = Join-Path $TOOLS_DIR "esp-quick-toolchain" + +# Esp32 +$env:IDF_PATH = Join-Path $TOOLS_DIR "esp-idf" +$env:IDF_TOOLS_PATH = Join-Path $TOOLS_DIR "esp32" +$env:IDF_BRANCH = "sming/release/v4.3" + +# Rp2040 +$env:PICO_TOOLCHAIN_PATH = Join-Path $TOOLS_DIR "rp2040" + +if (Test-Path "$env:PICO_TOOLCHAIN_PATH" ) { + $env:SMING_TOOLS_PREINSTALLED = "true" +} + +if ($IsWindows) { + $env:PATH = "C:\MinGW\msys\1.0\bin;C:\MinGW\bin;$env:PATH" + + $env:PATH = "C:\Python39;C:\Python39\Scripts;$env:PATH" + $env:PYTHON = "C:\Python39\python" + $env:ESP32_PYTHON_PATH = "C:\Python39" + + $env:PATH = "$env:PROGRAMFILES\CMake\bin;$env:PATH" + + $env:PATH = "$env:PROGRAMFILES\doxygen\bin;$env:PROGRAMFILES\Graphviz\bin;$env:PATH" + + if (Test-Path "$TOOLS_DIR" ) { + $env:NINJA = (get-childitem -path "$TOOLS_DIR" -recurse -include "ninja.exe" | select-object -first 1).FullName + } +} diff --git a/Tools/export.sh b/Tools/export.sh index 81cf497ea8..a695329944 100755 --- a/Tools/export.sh +++ b/Tools/export.sh @@ -1,3 +1,4 @@ +#!/bin/bash # # Set default environment variables from shell: # @@ -18,23 +19,24 @@ # if [ -z "$SMING_HOME" ]; then - if [ $(basename $SHELL) = "zsh" ]; then + if [ "$(basename $SHELL)" = "zsh" ]; then _SOURCE=${(%):-%N} else _SOURCE=$BASH_SOURCE fi - export SMING_HOME=$(readlink -m $_SOURCE/../../Sming) + export SMING_HOME=$(readlink -m "$_SOURCE/../../Sming") fi # Common export PYTHON=${PYTHON:=/usr/bin/python3} # Esp8266 -#export UDK_ROOT=${UDK_ROOT:=/opt/esp-open-sdk} -export EQT_ROOT=${EQT_ROOT:=/opt/esp-quick-toolchain} -export ESP_HOME=${ESP_HOME:=$EQT_ROOT} +export ESP_HOME=${ESP_HOME:=/opt/esp-quick-toolchain} # Esp32 export IDF_PATH=${IDF_PATH:=/opt/esp-idf} export IDF_TOOLS_PATH=${IDF_TOOLS_PATH:=/opt/esp32} export ESP32_PYTHON_PATH=${ESP32_PYTHON_PATH:=/usr/bin} + +# Rp2040 +export PICO_TOOLCHAIN_PATH=${PICO_TOOLCHAIN_PATH:=/opt/rp2040} diff --git a/Tools/ide/common/sming.py b/Tools/ide/common/sming.py new file mode 100644 index 0000000000..c86f48354b --- /dev/null +++ b/Tools/ide/common/sming.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 +# +# Sming hardware configuration tool +# + +import os, sys, json, shutil, configparser, string + +class Env(dict): + + """Cache build environment variables.""" + + def __init__(self): + self.update(os.environ) + self.updateFromConfig('config.mk') + self.updateFromConfig('debug.mk') + + def updateFromConfig(self, filename): + path = self['OUT_BASE'] + '/' + filename + if not os.path.exists(path): + return + parser = configparser.ConfigParser() + parser.optionxform = str # preserve case + with open(path) as f: + data = "[config]\n" + f.read() + parser.read_string(data) + self.update(parser['config']) + + def replace(self, path, name, prefix): + value = self.get(name) + if value is not None: + s = fix_path(path) + value = fix_path(value) + if value != '' and s.startswith(value): + return '${%s%s}%s' % (prefix, name, s[len(value):]) + return path + + def resolve(self, path): + """Convert any embedded environment variables into real paths.""" + tmp = str(path) + while True: + tmp = tmp.replace('(', '{') + tmp = tmp.replace(')', '}') + new_path = string.Template(tmp).safe_substitute(self) + if new_path == tmp: + return new_path + tmp = new_path + + def subst_path(self, path, prefix=''): + path = self.replace(path, 'SMING_HOME', prefix) + path = self.replace(path, 'ESP_HOME', prefix) + path = self.replace(path, 'IDF_PATH', prefix) + path = self.replace(path, 'IDF_TOOLS_PATH', prefix) + return path + + def isWsl(self): + return self.get('WSL_ROOT', '') != '' + + +env = Env() + + +def fix_path(path): + """Fix path so it conforms to makefile specs.""" + if path[1:3] == ':/': + return '/' + path[0] + path[2:] + return path + +def check_path(path): + """Fix path so it conforms to vscode specs.""" + if sys.platform == 'win32': + if path[:1] == '/': + return path[1:2] + ':' + path[2:] + return path + +def find_tool(name): + name = check_path(name) + if sys.platform == 'win32': + if os.path.splitext(name)[1] != '.exe': + name += '.exe' + if os.path.isabs(name): + path = name + else: + path = shutil.which(name) + if path is None: + sys.stderr.write("Warning! '%s' not found in path\n" % name) + path = name + if not os.path.exists(path): + sys.stderr.write("Warning! '%s' doesn't exist\n" % path) + return env.subst_path(path, 'env:') + +def load_json(filename, must_exist=True): + print(filename) + if must_exist or os.path.exists(filename): + import rjsmin + s = open(filename, 'r').read() + return json.loads(rjsmin.jsmin(s)) + return None + +def save_json(data, filename): + folder = os.path.dirname(filename) + if folder != '': + os.makedirs(folder, exist_ok=True) + with open(filename, 'w') as f: + json.dump(data, f, indent=4) + +def load_template(name, folder = None): + if folder is None: + folder = os.path.dirname(__file__) + filename = os.path.join(folder, 'template', name) + return load_json(filename) + +def find_object(data, name): + for o in data: + if o['name'] == name: + return o + return None + +def get_property(data, name, default): + if not name in data: + data[name] = default + return data[name] diff --git a/Tools/ide/eclipse/setup.py b/Tools/ide/eclipse/setup.py new file mode 100644 index 0000000000..1bcf3cc53b --- /dev/null +++ b/Tools/ide/eclipse/setup.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# +# Sming hardware configuration tool +# + +import os, sys +from shutil import copyfile +from pathlib import Path + +appPath = os.path.dirname(os.path.realpath(__file__)) +libPath = os.path.realpath(os.path.join(appPath, '..', 'common')) +sys.path.append(libPath) + +from sming import env + +def update_project_files(): + projectName = os.path.basename(os.getcwd()) + content = Path(appPath + '/templates/.project').read_text() + content = content % { 'PROJECT_NAME': projectName } + with open(os.getcwd() + '/.project', 'w') as f: + f.write(content) + copyfile(appPath + '/templates/.cproject', os.getcwd() + '/.cproject') + +def main(): + if not env['SMING_HOME'] or not env['SMING_ARCH']: + sys.exit(1) + update_project_files() + + +if __name__ == '__main__': + main() diff --git a/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/.cproject b/Tools/ide/eclipse/templates/.cproject similarity index 100% rename from Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/.cproject rename to Tools/ide/eclipse/templates/.cproject diff --git a/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/.project b/Tools/ide/eclipse/templates/.project similarity index 96% rename from Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/.project rename to Tools/ide/eclipse/templates/.project index 76f0847014..65650d9b9c 100644 --- a/Sming/Libraries/OtaUpgradeMqtt/samples/Upgrade/.project +++ b/Tools/ide/eclipse/templates/.project @@ -1,6 +1,6 @@ - Ota_Mqtt + %(PROJECT_NAME)s SmingFramework diff --git a/Tools/ide/vscode/setup.py b/Tools/ide/vscode/setup.py new file mode 100644 index 0000000000..52e68f7c8f --- /dev/null +++ b/Tools/ide/vscode/setup.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python3 +# +# Sming hardware configuration tool +# + +import os, sys + +appPath = os.path.dirname(os.path.realpath(__file__)) +libPath = appPath + '/../common/' +sys.path.append(libPath) + +from sming import check_path, env, find_object, find_tool, get_property, load_json, load_template, save_json + +def update_intellisense(): + dirs = [check_path(env['PROJECT_DIR']) + '/**'] + for d in env['COMPONENTS_EXTRA_INCDIR'].split(): + d = check_path(d) + if os.path.exists(d): + dirs += [check_path(env.subst_path(d))] + + propertiesFile = '.vscode/c_cpp_properties.json' + if os.path.exists(propertiesFile): + properties = load_json(propertiesFile) + else: + properties = load_template('intellisense/properties.json', appPath) + + env.update(get_property(properties, 'env', {})) + configurations = get_property(properties, 'configurations', []) + + config = find_object(configurations, env['SMING_ARCH']) + + if config is None: + config = load_template('intellisense/configuration.json', appPath) + config['name'] = env['SMING_ARCH'] + config['defines'].append('ARCH_%s=1' % env['SMING_ARCH'].upper()) + configurations.append(config) + + args = env['APP_CFLAGS'].split() + env['GLOBAL_CFLAGS'].split() + args = [env.resolve(v) for v in args] + config['compilerArgs'] = [v for v in args if v != ''] + + config['compilerPath'] = find_tool(env['CXX']) + config['includePath'] = dirs + + save_json(properties, propertiesFile) + + +def update_tasks(): + filename = '.vscode/tasks.json' + launch = load_json(filename, False) + if launch is None: + template = load_template('tasks.json', appPath) + launch = template.copy() + # TODO: Make any changes as required + save_json(launch, filename) + +def update_launch(): + filename = '.vscode/launch.json' + launch = load_json(filename, False) + template = load_template('launch.json', appPath) + if launch is None: + launch = template.copy() + configurations = get_property(launch, 'configurations', []) + config_name = "%s GDB" % env['SMING_ARCH'] + config = find_object(configurations, config_name) + template_config = find_object(template['configurations'], config_name) + if template_config is None: + print("Warning: Template launch configuration '%s' not found" % config_name) + elif not config is None: + configurations.remove(config) + config = template_config.copy() + configurations.append(config) + + if config is None: + return + + config['miDebuggerPath'] = find_tool(env['GDB']) + dbgargs = "-x ${env:SMING_HOME}/Arch/%s/Components/gdbstub/gdbcmds" % env['SMING_ARCH'] + if env['SMING_ARCH'] == 'Host': + args = [] + args += env['CLI_TARGET_OPTIONS'].split() + args += ["--"] + args += env['HOST_PARAMETERS'].split() + config['args'] = args + else: + if not env.isWsl(): + dbgargs += " -b %s" % env.resolve('${COM_SPEED_GDB}') + config['miDebuggerServerAddress'] = env.resolve('${COM_PORT_GDB}') + config['miDebuggerArgs'] = dbgargs + config['program'] = "${workspaceFolder}/" + env.resolve('${TARGET_OUT_0}') + + save_json(launch, filename) + +def update_workspace(): + filename = 'sming.code-workspace' + ws = load_json(filename, False) + template = load_template('workspace.json', appPath) + if ws is None: + ws = template.copy() + schemas = ws['settings']['json.schemas'] = [] + # ws['settings']['json.schemas'] + for schema in template['settings']['json.schemas']: + schema['url'] = env.resolve(schema['url']) + schemas += [schema] + save_json(ws, filename) + +def main(): + if not env['SMING_HOME'] or not env['SMING_ARCH']: + sys.exit(1) + + # So we can find rjsmin.py + sys.path.append(os.path.join(env['SMING_HOME'], '../Tools/Python')) + + update_intellisense() + update_tasks() + update_launch() + update_workspace() + + + +if __name__ == '__main__': + main() diff --git a/Tools/vscode/template/intellisense/configuration.json b/Tools/ide/vscode/template/intellisense/configuration.json similarity index 71% rename from Tools/vscode/template/intellisense/configuration.json rename to Tools/ide/vscode/template/intellisense/configuration.json index a884e7ee5d..2bb85d5044 100644 --- a/Tools/vscode/template/intellisense/configuration.json +++ b/Tools/ide/vscode/template/intellisense/configuration.json @@ -1,5 +1,8 @@ { "name": "", + "browse": { + "limitSymbolsToIncludedHeaders": true + }, "includePath": [], "defines": [], "compilerPath": "", diff --git a/Tools/vscode/template/intellisense/properties.json b/Tools/ide/vscode/template/intellisense/properties.json similarity index 100% rename from Tools/vscode/template/intellisense/properties.json rename to Tools/ide/vscode/template/intellisense/properties.json diff --git a/Tools/vscode/template/launch.json b/Tools/ide/vscode/template/launch.json similarity index 60% rename from Tools/vscode/template/launch.json rename to Tools/ide/vscode/template/launch.json index 5d623e3415..bce3fa183b 100644 --- a/Tools/vscode/template/launch.json +++ b/Tools/ide/vscode/template/launch.json @@ -5,22 +5,31 @@ "name": "Esp8266 GDB", "type": "cppdbg", "request": "launch", - "program": "${workspaceFolder}/out/Esp8266/debug/build/app_0.out", + "program": "", "args": [], "stopAtEntry": true, "cwd": "${workspaceFolder}", "environment": [], "externalConsole": true, - "MIMode": "gdb", - "miDebuggerPath": "${env:ESP_HOME}/xtensa-lx106-elf/bin/xtensa-lx106-elf-gdb", - "miDebuggerArgs": "-x ${env:SMING_HOME}/Arch/Esp8266/Components/gdbstub/gdbcmds -b 115200", - "miDebuggerServerAddress": "192.168.1.101:7778" + "MIMode": "gdb" + }, + { + "name": "Esp32 GDB", + "type": "cppdbg", + "request": "launch", + "program": "", + "args": [], + "stopAtEntry": true, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": true, + "MIMode": "gdb" }, { "name": "Host GDB", "type": "cppdbg", "request": "launch", - "program": "${workspaceFolder}/out/Host/debug/firmware/app", + "program": "", "args": [], "stopAtEntry": true, "cwd": "${workspaceFolder}", @@ -33,9 +42,7 @@ "text": "-enable-pretty-printing", "ignoreFailures": true } - ], - "miDebuggerPath": "/usr/bin/gdb", - "miDebuggerArgs": "-x ${env:SMING_HOME}/Arch/Host/Components/gdbstub/gdbcmds" + ] } ] } \ No newline at end of file diff --git a/Tools/vscode/template/tasks.json b/Tools/ide/vscode/template/tasks.json similarity index 88% rename from Tools/vscode/template/tasks.json rename to Tools/ide/vscode/template/tasks.json index b67d903ec2..f48d685363 100644 --- a/Tools/vscode/template/tasks.json +++ b/Tools/ide/vscode/template/tasks.json @@ -21,17 +21,19 @@ } }, { - "label": "Full rebuild (no debugging0", + "label": "Full rebuild (no debugging)", "detail": "Rebuild application and all Components", "type": "shell", - "command": "make clean components-clean SMING_ARCH=${command:cpptools.activeConfigName} && make -j ENABLE_GDB=", + "command": "make -j ENABLE_GDB=", + "dependsOn": ["Full clean"], "problemMatcher": [] }, { "label": "Full rebuild (with debugging)", "detail": "Rebuild application and all Components", "type": "shell", - "command": "make clean components-clean SMING_ARCH=${command:cpptools.activeConfigName} && make -j ENABLE_GDB=1", + "command": "make -j ENABLE_GDB=1", + "dependsOn": ["Full clean"], "problemMatcher": [] }, { diff --git a/Tools/vscode/template/workspace.json b/Tools/ide/vscode/template/workspace.json similarity index 89% rename from Tools/vscode/template/workspace.json rename to Tools/ide/vscode/template/workspace.json index a79cc17307..78c5eb2397 100644 --- a/Tools/vscode/template/workspace.json +++ b/Tools/ide/vscode/template/workspace.json @@ -5,6 +5,7 @@ } ], "settings": { + "terminal.integrated.defaultProfile.windows": "Command Prompt", "files.associations": { "*.hw": "jsonc", "*.fwfs": "jsonc", diff --git a/Tools/install.cmd b/Tools/install.cmd new file mode 100644 index 0000000000..bf6b93fb7e --- /dev/null +++ b/Tools/install.cmd @@ -0,0 +1,45 @@ +REM +REM Windows install script +REM +REM GIT, Python3 and Chocolatey must be installed and in the system path +REM + +set DOWNLOADS=downloads +mkdir %DOWNLOADS% + +set SMINGTOOLS=https://github.com/SmingHub/SmingTools/releases/download/1.0 + +REM Leave file endings alone +git config --global --add core.autocrlf input + +echo. +echo. +echo ** Installing common python requirements +echo. +python -m pip install --upgrade pip -r %SMING_HOME%\..\Tools\requirements.txt + +echo. +echo. +echo ** Installing MinGW +echo. +rmdir /s /q c:\MinGW +curl -Lo %DOWNLOADS%\MinGW.7z %SMINGTOOLS%/MinGW-2020-10-19.7z +7z -oC:\ x %DOWNLOADS%\MinGW.7z + +:install +if "%1" == "" goto :EOF +if "%1" == "all" ( + call :install Host Esp8266 Esp32 Rp2040 +) else ( + echo. + echo. + echo ** Installing %1 toolchain + echo. + if "%1" == "doc" ( + call %SMING_HOME%\..\docs\Tools\install.cmd + ) else ( + call %SMING_HOME%\Arch\%1\Tools\install.cmd + ) +) +shift +goto :install diff --git a/Tools/install.sh b/Tools/install.sh index e998967777..e45be81e65 100755 --- a/Tools/install.sh +++ b/Tools/install.sh @@ -11,21 +11,28 @@ inst_host=0 inst_doc=0 inst_esp8266=0 inst_esp32=0 +inst_rp2040=0 err=0 +FONT_PACKAGES="fonts-ubuntu fonts-noto-mono xfonts-base fonts-urw-base35 fonts-droid-fallback" + for opt in "$@"; do case $opt in all) inst_host=1 - inst_doc=1 inst_esp8266=1 inst_esp32=1 + inst_rp2040=1 ;; - host | doc | esp8266 | esp32) + host | doc | esp8266 | esp32 | rp2040) eval "inst_$opt=1" ;; + fonts) + EXTRA_PACKAGES+=" $FONT_PACKAGES" + ;; + *) echo "Unknown option '$opt'" err=1 @@ -36,10 +43,12 @@ done if [[ $err -eq 1 ]] || [ $# -eq 0 ]; then echo 'Sming Installation options:' echo ' host Host development tools' - echo ' doc Tools required to build documentation' echo ' esp8266 ESP8266 development tools' echo ' esp32 ESP32 development tools' - echo ' all Install everything' + echo ' rp2040 RP2040 tools (Raspberry Pi Pico)' + echo ' all Install all architectures' + echo ' doc Tools required to build documentation' + echo ' fonts Install fonts used by Graphics library (normally included with Ubuntu)' echo if [ $sourced = 1 ]; then return 1 @@ -51,20 +60,17 @@ fi # Sming repository for binary archives SMINGTOOLS=https://github.com/SmingHub/SmingTools/releases/download/1.0 -# Set default environment variables and WGET options +# Set default environment variables if [ -z "$APPVEYOR" ]; then - source $(dirname $BASH_SOURCE)/export.sh + source $(dirname "$BASH_SOURCE")/export.sh # Ensure default path is writeable sudo mkdir -p /opt sudo chown $USER:$USER /opt - - WGET="wget" -else - # Don't clutter up logfiles for CI builds - WGET="wget --no-verbose" fi +WGET="wget --no-verbose" + # Installers put downloaded archives here DOWNLOADS="downloads" mkdir -p $DOWNLOADS @@ -94,11 +100,7 @@ if [ -n "$APPVEYOR" ] || [ -n "$GITHUB_ACTION" ]; then clang-format-8 \ g++-9-multilib \ python3-setuptools \ - fonts-ubuntu \ - fonts-noto-mono \ - xfonts-base \ - fonts-urw-base35 \ - fonts-droid-fallback + $EXTRA_PACKAGES sudo update-alternatives --set gcc /usr/bin/gcc-9 @@ -108,7 +110,6 @@ else debian) sudo apt-get -y update || echo "Update failed... Try to install anyway..." $PKG_INSTALL \ - clang-format-8 \ cmake \ curl \ git \ @@ -119,7 +120,10 @@ else python3 \ python3-pip \ python3-setuptools \ - wget + wget \ + $EXTRA_PACKAGES + + $PKG_INSTALL clang-format-8 || printf "\nWARNING: Failed to install optional clang-format-8.\n\n" ;; fedora) @@ -148,13 +152,19 @@ fi set -e -sudo update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-8 100 +if [ -f "/usr/bin/clang-format-8" ]; then + sudo update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-8 100 +fi -python3 -m pip install --upgrade pip -r $SMING_HOME/../Tools/requirements.txt +python3 -m pip install --upgrade pip protobuf -r "$SMING_HOME/../Tools/requirements.txt" install() { - source $SMING_HOME/Arch/$1/Tools/install.sh + echo + echo + echo "** Installing $1 toolchain" + echo + source "$SMING_HOME/Arch/$1/Tools/install.sh" } if [ $inst_host -eq 1 ]; then @@ -162,7 +172,7 @@ if [ $inst_host -eq 1 ]; then fi if [ $inst_doc -eq 1 ]; then - source $SMING_HOME/../docs/Tools/install.sh + source "$SMING_HOME/../docs/Tools/install.sh" fi if [ $inst_esp8266 -eq 1 ]; then @@ -173,8 +183,12 @@ if [ $inst_esp32 -eq 1 ]; then install Esp32 fi +if [ $inst_rp2040 -eq 1 ]; then + install Rp2040 +fi + if [ -z "$KEEP_DOWNLOADS" ]; then - rm -f $DOWNLOADS/* + rm -f "$DOWNLOADS/*" fi diff --git a/Tools/requirements.txt b/Tools/requirements.txt index ee96c8f8e1..bc47cf1a0c 100644 --- a/Tools/requirements.txt +++ b/Tools/requirements.txt @@ -1,2 +1,3 @@ pyserial jsonschema +kconfiglib diff --git a/Tools/spelling/codespell.sh b/Tools/spelling/codespell.sh new file mode 100755 index 0000000000..326c8dc140 --- /dev/null +++ b/Tools/spelling/codespell.sh @@ -0,0 +1,73 @@ +#!/bin/bash +# +# Usage $0 +# +# Simple helper script to simplify sending spelling patches to submodules. +# The script requires Github's CLI tool "gh" to be installed. +# +# Sming Framework Project - Open Source framework for high efficiency native ESP8266 development. +# http://github.com/SmingHub/Sming +# This file is provided under the LGPL v3 license. +# @author Nov 2021 - Slavey Karadzhov +# + +set +e +set -x + +if [ -n "$1" ]; then + FOLDERS=$1; +else + FOLDERS=$(git status -s . | grep -i "^ m" | cut -d ' ' -f 3); +fi + +if [ -n "$2" ]; then + TARGET_USER=$2; +fi + +CURRENTDIR=$(pwd); +for i in $FOLDERS; +do + CHECK=${CURRENTDIR}/${i}; + + if [ ! -d "$CHECK" ]; then + continue; + fi + + cd "$CHECK"; + + echo "Checking $CHECK"; + + if [ -n "$TARGET_USER" ]; then + TARGET=$(git remote -v | grep "$TARGET_USER"); + if [ -z "$TARGET" ]; then + continue; + fi + fi + + if [ -z "$(git diff)" ]; then + continue; + fi + + git difftool + + read -p 'Continue? [N/y]: '; + if [ "${REPLY}" != "Y" ] && [ "${REPLY}" != "y" ]; then + continue; + fi + + # Get the original repository + REPO_URL=$(git config --get remote.origin.url) + + # And fork it + gh repo fork "$REPO_URL"; + PROJECT_ID=$(git config --get remote.origin.url | cut -d '/' -f 5) + FORK_URL=git@github.com:slaff/${PROJECT_ID} + if [[ "$FORK_URL" != *.git ]]; then + FORK_URL=${FORK_URL}.git + fi + git remote add my "$FORK_URL" + + git switch -c fix/spelling + git commit -a -m "Fix spelling mistakes" + git push -u my fix/spelling +done diff --git a/Tools/spelling/ignore.txt b/Tools/spelling/ignore.txt new file mode 100644 index 0000000000..9977a4c450 --- /dev/null +++ b/Tools/spelling/ignore.txt @@ -0,0 +1,11 @@ +Sming +ESP8266 +esp8266 +esp +dout +DOUT +ser +ans +esp32 +statics +rebounce diff --git a/Tools/spelling/requirements.txt b/Tools/spelling/requirements.txt new file mode 100644 index 0000000000..e3da9e4b09 --- /dev/null +++ b/Tools/spelling/requirements.txt @@ -0,0 +1 @@ +codespell diff --git a/Tools/spelling/skip.txt b/Tools/spelling/skip.txt new file mode 100644 index 0000000000..dec747b686 --- /dev/null +++ b/Tools/spelling/skip.txt @@ -0,0 +1,38 @@ +./Sming/Arch/Esp8266/Components/esp-lwip +./Sming/Arch/Esp8266/Components/esp-open-lwip +./Sming/Arch/Esp8266/Components/esp8266/sdk +./Sming/Arch/Esp8266/Components/heap/umm_malloc +./Sming/Arch/Esp8266/Components/lwip2 +./Sming/Arch/Host/Components/lwip +./Sming/Arch/Host/Components/SerialLib/seriallib +./Sming/Arch/Rp2040/Components/picotool/picotool +./Sming/Arch/Rp2040/Components/rp2040/pico-sdk +./Sming/Components/axtls-8266/axtls-8266 +./Sming/Components/bearssl-esp8266/bearssl +./Sming/Components/esptool/esptool +./Sming/Components/http-parser +./Sming/Components/rboot/rboot +./Sming/Libraries/Adafruit_SSD1306 +./Sming/Libraries/Arduino_TensorFlowLite/src +./Sming/Libraries/ArduinoJson5/ArduinoJson +./Sming/Libraries/ArduinoJson6/ArduinoJson +./Sming/Libraries/flatbuffers/src +./Sming/Libraries/Graphics/resource/fonts +./Sming/Libraries/IR +./Sming/Libraries/ITEADLIB_Arduino_Nextion +./Sming/Libraries/jerryscript/jerryscript +./Sming/Libraries/jerryscript/jsc +./Sming/Libraries/libsodium +./Sming/Libraries/nanopb/nanopb/* +./Sming/Libraries/Spiffs/spiffs +./tests/HostTests/resource +.git +*.csv +*.ino +*.patch +*.svg +*/out +20K.txt +jquery*.js +library.properties +styles.css diff --git a/Tools/vscode/setup.py b/Tools/vscode/setup.py deleted file mode 100644 index a183d6f18d..0000000000 --- a/Tools/vscode/setup.py +++ /dev/null @@ -1,223 +0,0 @@ -#!/usr/bin/env python3 -# -# Sming hardware configuration tool -# - -import os, sys, json, shutil, configparser, string - -class Env(dict): - """ Cache build environment variables""" - - def __init__(self): - self.update(os.environ) - self.updateFromConfig('config.mk') - self.updateFromConfig('debug.mk') - - def updateFromConfig(self, filename): - path = self['OUT_BASE'] + '/' + filename - if not os.path.exists(path): - return - parser = configparser.ConfigParser() - parser.optionxform = str # preserve case - with open(path) as f: - data = "[config]\n" + f.read() - parser.read_string(data) - self.update(parser['config']) - - def replace(self, path, name, prefix): - value = self.get(name) - if value is not None: - s = fix_path(path) - value = fix_path(value) - if value != '' and s.startswith(value): - return '${%s%s}%s' % (prefix, name, s[len(value):]) - return path - - def resolve(self, path): - """Convert any embedded environment variables into real paths - """ - tmp = str(path) - while True: - tmp = tmp.replace('(', '{') - tmp = tmp.replace(')', '}') - new_path = string.Template(tmp).safe_substitute(self) - if new_path == tmp: - return new_path - tmp = new_path - - def subst_path(self, path, prefix=''): - path = self.replace(path, 'SMING_HOME', prefix) - path = self.replace(path, 'ESP_HOME', prefix) - path = self.replace(path, 'IDF_PATH', prefix) - path = self.replace(path, 'IDF_TOOLS_PATH', prefix) - return path - - def isWsl(self): - return self.get('WSL_ROOT', '') != '' - - -env = Env() - - -def fix_path(path): - """Fix path so it conforms to makefile specs""" - if path[1:3] == ':/': - return '/' + path[0] + path[2:] - return path - -def check_path(path): - """Fix path so it conforms to vscode specs""" - if sys.platform == 'win32': - if path[:1] == '/': - return path[1:2] + ':' + path[2:] - return path - -def find_tool(name): - if sys.platform == 'win32': - if os.path.splitext(name)[1] != '.exe': - name += '.exe' - if os.path.isabs(name): - path = name - else: - path = shutil.which(name) - if path is None: - sys.stderr.write("Warning! '%s' not found in path\n" % name) - path = name - if not os.path.exists(path): - sys.stderr.write("Warning! '%s' doesn't exist\n" % path) - return env.subst_path(path, 'env:') - -def load_json(filename, must_exist=True): - if must_exist or os.path.exists(filename): - import rjsmin - s = open(filename, 'r').read() - return json.loads(rjsmin.jsmin(s)) - return None - -def save_json(data, filename): - dir = os.path.dirname(filename) - if dir != '': - os.makedirs(dir, exist_ok=True) - with open(filename, 'w') as f: - json.dump(data, f, indent=4) - -def load_template(name): - dir = os.path.dirname(__file__) - filename = os.path.join(dir, 'template', name) - return load_json(filename) - -def find_object(data, name): - for o in data: - if o['name'] == name: - return o - return None - -def get_property(data, name, default): - if not name in data: - data[name] = default - return data[name] - -def update_intellisense(): - dirs = [] - for d in env['COMPONENTS_EXTRA_INCDIR'].split(): - if os.path.exists(d): - dirs += [check_path(env.subst_path(d))] - - propertiesFile = '.vscode/c_cpp_properties.json' - if os.path.exists(propertiesFile): - properties = load_json(propertiesFile) - else: - properties = load_template('intellisense/properties.json') - - env.update(get_property(properties, 'env', {})) - configurations = get_property(properties, 'configurations', []) - - config = find_object(configurations, env['SMING_ARCH']) - - if config is None: - config = load_template('intellisense/configuration.json') - config['name'] = env['SMING_ARCH'] - config['defines'].append('ARCH_%s=1' % env['SMING_ARCH'].upper()) - configurations.append(config) - - config['compilerPath'] = find_tool(env['CXX']) - config['includePath'] = dirs - - save_json(properties, propertiesFile) - - -def update_tasks(): - filename = '.vscode/tasks.json' - launch = load_json(filename, False) - if launch is None: - template = load_template('tasks.json') - launch = template.copy() - # TODO: Make any changes as required - save_json(launch, filename) - -def update_launch(): - filename = '.vscode/launch.json' - launch = load_json(filename, False) - template = load_template('launch.json') - if launch is None: - launch = template.copy() - configurations = get_property(launch, 'configurations', []) - config_name = "%s GDB" % env['SMING_ARCH'] - config = find_object(configurations, config_name) - template_config = find_object(template['configurations'], config_name) - if template_config is None: - print("Warning: Template launch configuration '%s' not found" % config_name) - elif not config is None: - configurations.remove(config) - config = template_config.copy() - configurations.append(config) - - if config is None: - return - - config['miDebuggerPath'] = find_tool(env['GDB']) - dbgargs = "-x ${env:SMING_HOME}/Arch/%s/Components/gdbstub/gdbcmds" % env['SMING_ARCH'] - if env['SMING_ARCH'] == 'Esp8266': - if not env.isWsl(): - dbgargs += " -b %s" % env['COM_SPEED_GDB'] - config['miDebuggerServerAddress'] = env['COM_PORT_GDB'] - elif env['SMING_ARCH'] == 'Host': - args = [] - args += env['CLI_TARGET_OPTIONS'].split() - args += ["--"] - args += env['HOST_PARAMETERS'].split() - config['args'] = args - config['miDebuggerArgs'] = dbgargs - config['program'] = "${workspaceFolder}/" + env.resolve('${TARGET_OUT_0}') - - save_json(launch, filename) - -def update_workspace(): - filename = 'sming.code-workspace' - ws = load_json(filename, False) - template = load_template('workspace.json') - if ws is None: - ws = template.copy() - schemas = ws['settings']['json.schemas'] = [] - # ws['settings']['json.schemas'] - for schema in template['settings']['json.schemas']: - schema['url'] = env.resolve(schema['url']) - schemas += [schema] - save_json(ws, filename) - -def main(): - if not env['SMING_HOME'] or not env['SMING_ARCH']: - sys.exit(1) - - # So we can find rjsmin.py - sys.path.append(os.path.join(env['SMING_HOME'], '../Tools/Python')) - - update_intellisense() - update_tasks() - update_launch() - update_workspace() - - - -if __name__ == '__main__': - main() diff --git a/appveyor.yml b/appveyor.yml index ed86a8b7fd..972d188321 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,66 +2,42 @@ image: - Ubuntu2004 - Visual Studio 2019 -platform: x86 - environment: SMING_SECRET: secure: rCs19uNvDR07w1d2pfwJIzewiEQ2zpKXdqFp5BqHQAA= matrix: - SMING_ARCH: Host - INSTALL_OPTS: host doc - SMING_ARCH: Esp8266 - INSTALL_OPTS: esp8266 - BUILD_COMPILER: udk - - SMING_ARCH: Esp8266 - INSTALL_OPTS: esp8266 - BUILD_COMPILER: eqt + - SMING_ARCH: Esp32 + SMING_SOC: esp32 + + - SMING_ARCH: Esp32 + SMING_SOC: esp32s2 - SMING_ARCH: Esp32 - INSTALL_OPTS: esp32 + SMING_SOC: esp32c3 + + - SMING_ARCH: Rp2040 + - BUILD_DOCS: true install: - ps: | # Set up environment variables for all environments and build types - $env:CI_BUILD_DIR = $env:APPVEYOR_BUILD_FOLDER - $env:CI_PROJECT_SLUG = $env:APPVEYOR_PROJECT_SLUG $env:CI_REPO_NAME = $env:APPVEYOR_REPO_NAME if ($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME) { $env:CI_PULL_REQUEST = "true" } - # Esp8266 - $env:UDK_ROOT = Join-Path $env:CI_BUILD_DIR "opt/esp-alt-sdk" - $env:EQT_ROOT = Join-Path $env:CI_BUILD_DIR "opt/esp-quick-toolchain" - if ($env:BUILD_COMPILER -eq "udk") { - $env:ESP_HOME = $env:UDK_ROOT - } else { - $env:ESP_HOME = $env:EQT_ROOT - } - # Esp32 - $env:IDF_PATH = Join-Path $env:CI_BUILD_DIR "opt/esp-idf" - $env:IDF_TOOLS_PATH = Join-Path $env:CI_BUILD_DIR "opt/tools/esp32" - $env:IDF_BRANCH = "sming/dev/v4.3" - # General - $env:SMING_HOME = Join-Path $env:CI_BUILD_DIR "Sming" + Tools/ci/setenv.ps1 - cmd: | - set PATH=C:\Python39;C:\Python39\Scripts;C:\MinGW\msys\1.0\bin;C:\MinGW\bin;%PATH% - set PYTHON=C:\Python39\python - set ESP32_PYTHON_PATH=C:\Python39 Tools\ci\install.cmd - set PATH=C:\tools\doxygen;C:\tools\Graphviz\bin;%PATH% - sh: | - export PYTHON=$HOME/venv3.9/bin/python - export ESP32_PYTHON_PATH=$HOME/venv3.9/bin - source $HOME/venv3.9/bin/activate - Tools/install.sh $INSTALL_OPTS - cd $CI_BUILD_DIR - + . Tools/ci/install.sh before_build: - sh: | @@ -77,7 +53,7 @@ build_script: after_build: - ps: | - if ($env:SMING_ARCH -eq "Host") { + if ($env:BUILD_DOCS) { $docFile = "sming-docs.zip" Compress-Archive -Path $env:CI_BUILD_DIR/docs/build/html -DestinationPath $docFile Push-AppveyorArtifact $docFile diff --git a/docs/Makefile b/docs/Makefile index e8cf78e6f5..c8b8165c34 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -11,6 +11,8 @@ SMINGDIR := .. override SMING_HOME := $(SMINGDIR)/Sming override SMING_ARCH := Host +include $(SMING_HOME)/util.mk + # You can set these variables from the command line, and also from the environment for the first two. SPHINXOPTS ?= SPHINXBUILD ?= sphinx-build @@ -28,18 +30,6 @@ MAKE_DOCS := 1 # Documentation is copied into this directory so it gets pulled into build SOURCE_INCDIR := $(SOURCEDIR)/_inc -# -FixPath = $1 - -V ?= $(VERBOSE) -ifeq ("$(V)","1") -Q := -vecho := @true -else -Q := @ -vecho := @echo -endif - # Define anything required to get all optional code included include defines.mk @@ -47,13 +37,6 @@ define Sphinx @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) endef -# Display variable and list values, e.g. $(call PrintVariable,LIBS) -# $1 -> Name of variable containing values -define PrintVariable - $(info $1) - $(foreach item,$($1),$(info - $(item))) -endef - # $1 -> Directories to look for README and image files define FindSourceFiles $(foreach d,$1,$(wildcard $d/*.rst $d/README.md $d/*.svg $d/*.png $d/*.jpg)) @@ -87,13 +70,6 @@ latexpdf: latex @echo "Running LaTeX files through pdflatex..." $(Q) $(MAKE) -C $(BUILDDIR)/latex all-pdf -# List immediate sub-directories for a list of root directories -# Results are sorted and without trailing path separator -# $1 -> Root paths -define ListSubDirs -$(sort $(foreach d,$(dir $(wildcard $1/*/.)),$(d:/=))) -endef - # Non-component locations to copy docs from SOURCE_DIRS := \ $(SMINGDIR)/docs \ @@ -116,6 +92,7 @@ DOXYGEN_PREDEFINED := \ ICACHE_FLASH= \ ICACHE_FLASH_ATTR= \ __forceinline= \ + __attribute__((packed))= \ SMING_DEPRECATED= \ SMING_ARCH=$(SMING_ARCH) \ ARCH_HOST=1 @@ -136,7 +113,7 @@ COMPONENT_SAMPLES := $(wildcard $(addsuffix /samples/*/component.mk,$(COMPONENT_ COMPONENT_DIRS += $(COMPONENT_SAMPLES:/component.mk=) # Fetch a list of URLs once rather than invoking shell each time we need a lookup -SUBMODULE_URLS := $(shell awk '/path = .*/ { path = $$3 } /url = .*/ { printf "%s=%s ", path, $$3 } ' $(SMINGDIR)/.gitmodules) +SUBMODULE_URLS := $(shell $(AWK) '/path = .*/ { path = $$3 } /url = .*/ { printf "%s=%s ", path, $$3 } ' $(SMINGDIR)/.gitmodules) # Lookup the URL for a submodule given its path # $1 -> path @@ -157,7 +134,7 @@ endif # $1 -> Path to a Component, sample or Library define GetComponentType -$(if $(findstring /samples/,$1),Sample,$(if $(findstring /Libraries/,$1),Library,,Component)) +$(if $(findstring /samples/,$1),Sample,$(if $(findstring /Libraries/,$1),Library,Component)) endef include index.mk @@ -173,11 +150,14 @@ endef # $2 -> path define ParseComponent $(if $V,$(info -- Parsing $2)) +ARCHLIST := $(subst /, ,$(patsubst $(SMING_HOME)/Arch/%,%,$2)) +ARCH_SOC := $$(ARCH_$$(firstword $$(ARCHLIST))_SOC) COMPONENT_SUBMODULES := COMPONENT_DOCFILES := COMPONENT_DOXYGEN_INPUT := COMPONENT_DOXYGEN_INCLUDE := COMPONENT_DOXYGEN_PREDEFINED := +COMPONENT_SOC := $$(if $$(ARCH_SOC),$$(ARCH_SOC),*) # Process any component.mk file (optional) COMPONENT_RULE := __no_build__ COMPONENT_NAME := $1 @@ -193,6 +173,7 @@ COMPONENT_BUILD_BASE := $(BUILD_BASE)/$1 COMPONENT_BUILD_DIR := $(BUILD_BASE)/$1 include defines.mk -include $2/component.mk +CMP_$2_SOC := $$(filter $$(subst *,%,$$(COMPONENT_SOC)),$(AVAILABLE_SOCS)) CMP_$2_VARS := $$(sort $$(COMPONENT_VARS)) CMP_$2_LIBRARIES := $$(ARDUINO_LIBRARIES) CMP_$2_SUBMODULES := $$(COMPONENT_SUBMODULES) @@ -211,7 +192,6 @@ DOXYGEN_PREDEFINED += $$(COMPONENT_DOXYGEN_PREDEFINED) COMPONENT_ENVVARS := $$(sort $$(COMPONENT_VARS) $$(CONFIG_VARS) $$(RELINK_VARS) $$(CACHE_VARS) $$(DEBUG_VARS)) CMP_$2_ENVVARS := $$(COMPONENT_ENVVARS) -CMP_$2_DEPENDS := $$(COMPONENT_DEPENDS) $$(foreach c,$$(COMPONENT_DEPENDS) $$(ARDUINO_LIBRARIES),$$(eval CMP_$$c_XREF += $2)) # Resolve dependencies @@ -223,12 +203,16 @@ FILTERED_DIRS := $$(filter $(dir $2)% $(SMING_HOME)/Components/%,$(COMPONENT_DIR else FILTERED_DIRS := $(COMPONENT_DIRS) endif -CMP_$2_DEPEND_DIRS := \ - $(if $(findstring /samples/,$2),/_inc/Sming) \ - $$(foreach d,$$(call GetDocPath,$$(foreach c,$$(COMPONENT_DEPENDS),$$(filter %/$$c,$$(FILTERED_DIRS)))),$$d) +CMP_$2_DEPENDS := \ + $(if $(findstring /samples/,$2),$(SMING_HOME)) \ + $$(foreach d,$$(foreach c,$$(COMPONENT_DEPENDS) $$(ARDUINO_LIBRARIES),$$(filter %/$$c,$$(FILTERED_DIRS))),$$d) CMP_$2_INDEX = $$(subst $$(NewLine),\n,$$(call GenIndex,$1,$2,$(patsubst $(SMINGDIR)/%,%,$2))) +# Filter SOC dependencies +CMP_$2_UNSUPPORTED_SOC = $$(foreach d,$$(CMP_$2_DEPENDS),$$(filter-out $$(CMP_$$d_SOC),$$(AVAILABLE_SOCS))) +CMP_$2_SOC_DEPENDS = $$(filter-out $$(CMP_$2_UNSUPPORTED_SOC),$$(CMP_$2_SOC)) + $$(call GetIncPath,$$(COMPONENT_PATH))/index.rst: $$(CMP_$2_README) $$(call GetIncPath,$$(CMP_$2_FILES)) ifeq ($V,1) $$(info Creating $$@...) @@ -262,7 +246,6 @@ setup: initdirs $(SOURCE_INCFILES) $(COMPONENT_INDEXFILES) ifeq ($V,1) $(call PrintVariable,SOURCE_DIRS) $(call PrintVariable,SOURCE_FILES) - $(call PrintVariable,COMPONENT_INCFILES) endif $(if $(MISSING_README_DIRS),$(call PrintVariable,MISSING_README_DIRS)) diff --git a/docs/README.rst b/docs/README.rst index 81cbd69be5..8208db9997 100644 --- a/docs/README.rst +++ b/docs/README.rst @@ -1,6 +1,8 @@ Sming Documentation =================== +.. highlight:: bash + This directory contains the build system for Sming's documentation. It is intended to be read online via `Read The Docs `__. @@ -10,42 +12,13 @@ information is obtained from the various README files associated with the source Setup ----- -make -~~~~ - -Should already be available as part of Sming build system - -doxygen & graphviz -~~~~~~~~~~~~~~~~~~ - -.. highlight:: bash - -For Linux:: - - sudo apt install doxygen graphviz-dev - -For Windows, see: - -- **Doxygen** `www.doxygen.nl `__ -- **Graphviz** `graphviz.org `__ - -GraphViz is used by Doxygen (and Sphinx) to render graphs from .dot files. - -Python 3 + Sphinx -~~~~~~~~~~~~~~~~~ - -For Linux:: - - sudo apt install python3-sphinx python3-pip python3-setuptools python3-cairocffi - -For Windows, see `Sphinx Installation Guide `__. +Linux:: -Requirements -~~~~~~~~~~~~ + ../Tools/install.sh doc -Install other required packages:: +Windows:: - pip3 install -r requirements.txt + ..\Tools\install.cmd doc Building diff --git a/docs/Tools/install.cmd b/docs/Tools/install.cmd new file mode 100644 index 0000000000..dfd146312c --- /dev/null +++ b/docs/Tools/install.cmd @@ -0,0 +1,8 @@ +REM Docs install.cmd + +choco install -y --no-progress doxygen.install graphviz +setx PATH "%PROGRAMFILES%\doxygen\bin;%PROGRAMFILES%\Graphviz\bin;%PATH%" + +python -m pip install --upgrade pip wheel +python -m pip install -r %~dp0/../requirements.txt +python -m pip uninstall -y xcffib diff --git a/docs/Tools/install.sh b/docs/Tools/install.sh old mode 100644 new mode 100755 diff --git a/docs/api.dox b/docs/api.dox index 05571c8d11..2278883562 100644 --- a/docs/api.dox +++ b/docs/api.dox @@ -1,4 +1,4 @@ -// This file is used as the main page (index.html) and to define elements of the API documentation such as groups that do not naturaly fit in to a source header file. +// This file is used as the main page (index.html) and to define elements of the API documentation such as groups that do not naturally fit in to a source header file. /** @defgroup constants Sming constant values * @brief Constants and enumerated lists used by Sming functions diff --git a/docs/defines.mk b/docs/defines.mk index 87a483cd0c..7b00b33cc2 100644 --- a/docs/defines.mk +++ b/docs/defines.mk @@ -10,4 +10,4 @@ ENABLE_CUSTOM_LWIP := # Enable optional Components ENABLE_CUSTOM_HEAP := 1 ENABLE_SSL := 1 -SDK_BASE := $(SMING_HOME) + diff --git a/docs/index.mk b/docs/index.mk index 8291d376fc..8892b3d33b 100644 --- a/docs/index.mk +++ b/docs/index.mk @@ -4,8 +4,6 @@ # $2 -> Path # $3 -> Source path relative to working root directory (SMINGDIR) define GenIndex -:custom_pagename: $(patsubst ../%,%,$(CMP_$2_README)) - $(if $(filter %.rst,$(CMP_$2_README)), .. include:: $(call GetIncludePath,$(CMP_$2_README)), .. mdinclude:: $(call GetMdIncludePath,$(CMP_$2_README)) @@ -13,15 +11,10 @@ $(if $(filter %.rst,$(CMP_$2_README)), References ---------- -$(if $(findstring $3=,$(SUBMODULE_URLS)), -* `Source Code <$(call GetSubmoduleURL,$3)>`__ (submodule, may be patched)., -* :source:`Source Code <$3>`) -$(foreach d,$(sort $(CMP_$2_DEPEND_DIRS)), -* :doc:`$d/index` Component -) -$(foreach l,$(sort $(CMP_$2_LIBRARIES)), -* :library:`$l` Library -) + +* :source:`Source Code <$3>` +$(foreach d,$(sort $(CMP_$2_DEPENDS)), +* :doc:`$(call GetDocPath,$d)/index`) $(if $(CMP_$1_XREF), Used by @@ -36,6 +29,12 @@ $(foreach v,$(CMP_$2_ENVVARS), * :envvar:`$v` )) +SoC support +----------- +$(foreach s,$(CMP_$2_SOC_DEPENDS), +- $s) + + $(foreach m,$(CMP_$2_SUBMODULES), Submodule: `$m <$(call GetSubmoduleURL,$3/$m)>`__ ----------------------------------------------------------------------------------------------------- diff --git a/docs/requirements.txt b/docs/requirements.txt index 82e9a08337..bcfe112050 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -2,7 +2,8 @@ # list of Python packages used in documentation build sphinx==4.2.0 sphinx-rtd-theme==1.0.0 -m2r2 +m2r2==0.3.1 +mistune==0.8.4 # Version 2 not compatible with m2r2 breathe==4.31.0 sphinxcontrib-wavedrom sphinx-copybutton diff --git a/docs/source/_templates/breadcrumbs.html b/docs/source/_templates/breadcrumbs.html index 838eb0c453..adb4ce453e 100644 --- a/docs/source/_templates/breadcrumbs.html +++ b/docs/source/_templates/breadcrumbs.html @@ -10,32 +10,15 @@ {% set suffix = '' %} {% endif %} -{% if meta is defined and meta.custom_pagename is defined %} -{% set pagename = meta.custom_pagename %} -{% elif '_inc/' in pagename %} -{% set pagename = pagename|replace('_inc/','') + suffix %} +{% if pagename.startswith('_inc/') %} +{% set github_url = page_urls.get(pagename + suffix) %} {% else %} -{% set pagename = conf_py_path + pagename + suffix %} -{% endif %} - -{% if meta is defined and meta is not none %} -{% if 'github_url' in meta %} -{% set github_url = meta.github_url %} -{% set display_github = True %} -{% endif %} -{% endif %} - -{% if github_url is not defined %} -{% set github_url = 'https://' + github_host|default('github.com') + '/' + github_user + '/' + github_repo + '/' + theme_vcs_pageview_mode|default('blob') + '/' + github_version + '/' + pagename %} +{% set github_url = 'https://' + github_host|default('github.com') + '/' + github_user + '/' + github_repo + '/blob/' + github_version + '/' + conf_py_path + pagename + suffix %} {% endif %}
  • {% if github_url is not none %} - {{ _('Edit on GitHub') }} - {% elif show_source and source_url_prefix %} - {{ _('View page source') }} - {% elif show_source and has_source and sourcename %} - {{ _('View page source') }} + {{ _('View on GitHub') }} {% endif %}
  • diff --git a/docs/source/arch/rp2040/debugging/index.rst b/docs/source/arch/rp2040/debugging/index.rst new file mode 100644 index 0000000000..d439a6364d --- /dev/null +++ b/docs/source/arch/rp2040/debugging/index.rst @@ -0,0 +1,6 @@ +Debugging on RP2040 +=================== + +Currently debugging support on Sming is limited to serial output and inspecting disassembly using GDB. + +See https://www.raspberrypi.org/documentation/microcontrollers/raspberry-pi-pico.html diff --git a/docs/source/conf.py b/docs/source/conf.py index b98da2f033..11d98d2e10 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -19,6 +19,7 @@ from sphinx.util.nodes import set_role_source_info, split_explicit_title # So our custom extensions can be found sys.path.insert(0, os.path.abspath('.')) +from filemap import buildFileMap # -- Project information ----------------------------------------------------- @@ -117,6 +118,7 @@ "github_repo": "Sming", "github_version": "develop", "conf_py_path": "/docs/source/", # Path in the checkout to the docs root + "page_urls": {}, } ## @@ -138,3 +140,5 @@ subprocess.call('make -C ../../Sming submodules SMING_ARCH=Host', shell=True) subprocess.call('make -C .. setup api API_VERSION="' + version + '"', shell=True) + +buildFileMap(html_context) diff --git a/docs/source/filemap.py b/docs/source/filemap.py new file mode 100644 index 0000000000..939af0e9df --- /dev/null +++ b/docs/source/filemap.py @@ -0,0 +1,82 @@ +# +# Build map of output files to source URLs so that edit links are created correctly +# + +import os +import sys +import subprocess +import shutil + +SMINGDIR = "../.." +GIT = shutil.which('git') + + +def gitcmd(args, **kwargs): + kwargs['stdout'] = subprocess.PIPE + with subprocess.Popen([GIT] + args, **kwargs) as child: + return child.stdout.read().decode() + + +def urljoin(elements): + res = '' + for e in elements: + if e == '': + continue + if res != '' and not res.endswith('/'): + res += '/' + res += e + return res + + +def getRemotePath(srcdir): + path = gitcmd(['rev-parse', '--show-prefix'], cwd=srcdir).strip() + return path.rstrip('/') + + +def getRemoteUrl(srcdir): + url = gitcmd(['config', '--get', 'remote.origin.url'], cwd=srcdir).strip() + return os.path.splitext(url)[0] # Remove .git if present + + +def getRemoteCommit(srcdir): + return gitcmd(['describe', '--always', 'HEAD'], cwd=srcdir).strip() + + +# Get map of directories to submodule URLs +def buildFileMap(ctx): + rootmap = {} + + # index.rst files may be generated from README.md or README.rst + def getSourceFilename(srcdir, filename): + if filename != 'index.rst': + return filename + if os.path.exists(f"{srcdir}/README.md"): + return 'README.md' + if os.path.exists(f"{srcdir}/README.rst"): + return 'README.rst' + return filename + + filemap = {} + for dirpath, dirnames, filenames in os.walk('_inc'): + srcpath = dirpath[5:] # skip '_inc/' + srcdir = os.path.join(SMINGDIR, srcpath) + # print(f"srcdir = {srcdir}", file=sys.stderr) + remotePath = getRemotePath(srcdir) + url = getRemoteUrl(srcdir) + commit = getRemoteCommit(srcdir) + if remotePath: + srcpath = srcpath.rsplit(remotePath)[0].rstrip('/') + rootmap[srcpath] = urljoin([url, 'tree', commit]) + for f in filenames: + s = urljoin([url, 'blob', commit, remotePath, getSourceFilename(srcdir, f)]) + filemap[f"{dirpath}/{f}"] = s + + # for k, v in filemap.items(): + # print(f"{k}: {v}", file=sys.stderr) + + # for k, v in rootmap.items(): + # print(f"{k}: {v}", file=sys.stderr) + + ctx['page_urls'] = filemap + ctx['root_urls'] = rootmap + ctx['root_paths'] = sorted(rootmap.keys(), reverse=True) diff --git a/docs/source/framework/core/data/cstring.rst b/docs/source/framework/core/data/cstring.rst index 6283f9eccf..5cca5e7a2e 100644 --- a/docs/source/framework/core/data/cstring.rst +++ b/docs/source/framework/core/data/cstring.rst @@ -8,7 +8,7 @@ Introduction Whilst use of `char*` pointers is very common in Sming code, it is generally advisable to avoid pointers in C++ where possible. -The STL provides class templates such as `unique_ptr` which deals with memory alllocation and de-allocation +The STL provides class templates such as `unique_ptr` which deals with memory allocation and de-allocation to avoid issues with memory leaks. The `CString` class implements this on a `char[]` and adds some additional methods which are similar to the :cpp:class:`String` class. diff --git a/docs/source/framework/core/data/csvreader.rst b/docs/source/framework/core/data/csvreader.rst new file mode 100644 index 0000000000..35082438ec --- /dev/null +++ b/docs/source/framework/core/data/csvreader.rst @@ -0,0 +1,5 @@ +CSV Reader +========== + +.. doxygenclass:: CsvReader + :members: diff --git a/docs/source/framework/core/data/format.rst b/docs/source/framework/core/data/format.rst new file mode 100644 index 0000000000..95b9fa138e --- /dev/null +++ b/docs/source/framework/core/data/format.rst @@ -0,0 +1,10 @@ +Data formatting +=============== + +A standard mechanism is provided for encoding and decoding text in commonly-used text formats +using a :cpp:class:`Format::Formatter` class implementation. + + +.. doxygennamespace:: Format + :members: + diff --git a/docs/source/framework/core/data/linked-object.rst b/docs/source/framework/core/data/linked-object.rst new file mode 100644 index 0000000000..68848643dd --- /dev/null +++ b/docs/source/framework/core/data/linked-object.rst @@ -0,0 +1,6 @@ +Linked Object Lists +=================== + +.. doxygenfile:: Core/Data/LinkedObject.h + +.. doxygenfile:: Core/Data/LinkedObjectList.h diff --git a/docs/source/framework/core/data/object-map.rst b/docs/source/framework/core/data/object-map.rst new file mode 100644 index 0000000000..cde47f4a86 --- /dev/null +++ b/docs/source/framework/core/data/object-map.rst @@ -0,0 +1,4 @@ +Object Map +========== + +.. doxygenfile:: Core/Data/ObjectMap.h diff --git a/docs/source/framework/core/data/object-queue.rst b/docs/source/framework/core/data/object-queue.rst new file mode 100644 index 0000000000..b66d6fd8fa --- /dev/null +++ b/docs/source/framework/core/data/object-queue.rst @@ -0,0 +1,5 @@ +Object Queue +============ + +.. doxygenfile:: Core/Data/ObjectQueue.h + diff --git a/docs/source/framework/core/data/packet.rst b/docs/source/framework/core/data/packet.rst new file mode 100644 index 0000000000..c576e6d21a --- /dev/null +++ b/docs/source/framework/core/data/packet.rst @@ -0,0 +1,4 @@ +Packet writing +============== + +.. doxygenfile:: Core/Data/Packet.h diff --git a/docs/source/framework/core/data/range.rst b/docs/source/framework/core/data/range.rst new file mode 100644 index 0000000000..f2e9023320 --- /dev/null +++ b/docs/source/framework/core/data/range.rst @@ -0,0 +1,4 @@ +Range +===== + +.. doxygenfile:: Core/Data/Range.h diff --git a/docs/source/framework/core/data/streams/streams.rst b/docs/source/framework/core/data/streams/streams.rst index 98c40ba9e2..b962f51bfa 100644 --- a/docs/source/framework/core/data/streams/streams.rst +++ b/docs/source/framework/core/data/streams/streams.rst @@ -2,3 +2,6 @@ Stream Classes ============== .. doxygengroup:: stream + +.. doxygenclass:: StreamTransformer + :members: Callback, transform, saveState, restoreState diff --git a/docs/source/framework/core/data/streams/templates.rst b/docs/source/framework/core/data/streams/templates.rst new file mode 100644 index 0000000000..152052c4e8 --- /dev/null +++ b/docs/source/framework/core/data/streams/templates.rst @@ -0,0 +1,214 @@ +Template Streams +================ + +.. highlight:: c++ + +Sming provides several classes to assist with serving dynamic content: + +Basic Templating +---------------- + +The :cpp:class:`TemplateStream` class is a stream which performs variable-value substitution using +``{varname}`` style markers, which are replaced as the stream is read. + +You can find a simple demonstration of how this class is used in the +:sample:`HttpServer_Bootstrap` sample application. + +.. note:: + + There must be no whitespace after the opening brace. + For example, ``{ varname }`` will be emitted as-is without modification. + + This allows inclusion of CSS fragments such as ``td { padding: 0 10px; }`` in HTML + without resorting to double-braces. + + If necessary, use double-braces ``{{varname}}`` in your template and + call :cpp:func:`TemplateStream::setDoubleBraces` ``(true)``. + + Invalid tags, such as ``{"abc"}`` will be ignored, so JSON templates do not require + special treatment. + + +Variable values can be set using :cpp:func:`TemplateStream::setVar` or :cpp:func:`TemplateStream::setVars`. +These are stored in a :cpp:class:`HashMap` which can be accessing directly via :cpp:func:`TemplateStream::variables`. + +To support calculated values and external lookups, an optional callback may +be provided via :cpp:func:`TemplateStream::onGetValue`. +This is invoked only if a variable is not found in the map. + +Another option is to use TemplateStream as a base class and override the :cpp:func:`TemplateStream::getValue` method. + +.. important:: + + If required, text must be escaped appropriately for the output format. + For example, encoding reserved HTML characters can be handled using :cpp:func:`Format::Html::escape`. + + +Advanced Templating +------------------- + +Introduction +~~~~~~~~~~~~ + +The :cpp:class:`SectionTemplate` class extends :cpp:class:`TemplateStream` to provide more advanced dataset processing capabilities. +It is intended to be used as the base class for a data provider. + +One such implementation is the :cpp:class:`IFS::DirectoryTemplate` class. +The :sample:`Basic_IFS` sample demonstrates how it can be used to provide a formatted directory +listing in multiple formats, using a different template for each format. + +The :sample:`Basic_Templates` sample illustrates a similar appraoch using data from CSV data files. + +If the output format requires escaping, create an instance of the appropriate :cpp:class:`Format::Formatter` +and call :cpp:func:`SectionTemplate::setFormatter`. +If providing custom values via callback, obtain the current formatter via :cpp:func:`SectionTemplate::formatter` +class and call the ``escape`` method. +Note that for performance reasons this is not done automatically as often variable values +do not require escaping. User-provided values or filenames must always be properly escaped. + + +Sections +~~~~~~~~ + +Templates typically contain multiple sections. +The :cpp:class:`IFS::DirectoryTemplate`, for example, uses 3 sections for header, content and footer. +The header and footer are emitted exactly once, but the content section is repeated for each available data record. + +The :cpp:class:`SectionStream` class is used internally so that all sections can be provided within a single file. + +Sections are (by default) marked ``{SECTION}`` ... ``{/SECTION}``. +Everything outside of these markers is ignored, so can contain comments. + + +Using SectionTemplate +~~~~~~~~~~~~~~~~~~~~~ + +Implementations should provide the following methods: + +nextRecord + This method is called before a new content record is about to be output. + Here's the annotated :cpp:class:`IFS::DirectoryTemplate` implementation:: + + // Return true if we have a new valid record, false if not + bool nextRecord() override + { + // Content section we fetch the next directory record, if there is one + if(sectionIndex() == 1) { + return directory->next(); + } + + // This code emits the header and footer sections exactly once + // Returning false suppresses their output completely + return recordIndex() < 0; + } + + This sets up the 'current' directory information record. + + +getValue + Lookup values for a given field:: + + String getValue(const char* name) override + { + // return ... + } + + .. important:: + + If required, text must be escaped appropriately for the output format. + Use :cpp:func:`SectionTemplate::formatter` to obtain the current + For example, encoding reserved HTML characters can be handled using :cpp:func:`Format::Html::escape`. + + +Control language +~~~~~~~~~~~~~~~~ + +A basic control language is implemented using ! escaped tags. +Commands may have zero or more arguments, separated by ``:``. + +- Numbers must be decimal and start with a digit, e.g. ``11`` or ``5.6`` +- Strings must be quoted "..." +- Sub-expressions must be contained in braces {...} + +Anything else is treated as a variable name. +Variable names beginning with $ are reserved for internal use. +The following values are currently defined: + +``$section`` The current section index +``$record`` The current record index + +Conditional if/else/endif statements may be nested. + +This is the current command list: + +- ``{!int:A}`` Output A as integer +- ``{!float:A}`` Output A as float +- ``{!string:A}`` Output A as quoted string +- ``{!mime_type:A}`` Get MIME type string for a filename +- ``{!replace:A:B:C}`` Copy of A with all occurrences of B replaced with C +- ``{!length:A}`` Number of characters in A +- ``{!pad:A:B:C}`` Copy of A padded to at least B characters with C (default is space). Use -ve B to left-pad. C +- ``{!repeat:A:B}`` Repeat A, number of iterations is B +- ``{!kb:A}`` Convert A to KB +- ``{!ifdef:A}`` emit block if A is not zero-length +- ``{!ifdef:A}`` emit block if A is zero-length +- ``{!ifeq:A:B}`` emit block if A == B +- ``{!ifneq:A:B}`` emit block if A != B +- ``{!ifgt:A:B}`` emit block if A > B +- ``{!iflt:A:B}`` emit block if A < B +- ``{!ifge:A:B}`` emit block if A >= B +- ``{!ifle:A:B}`` emit block if A <= B +- ``{!ifbtw:A:B:C}`` emit block if B <= A <= C +- ``{!ifin:A:B}`` emit block if A contains B +- ``{!ifin:A:B}`` emit block if A does not contain B +- ``{!else}`` +- ``{!endif}`` +- ``{!add:A:B}`` A + B +- ``{!sub:A:B}`` A - B +- ``{!goto:A}`` move to section A +- ``{!count:A}`` emit number of records in section A +- ``{!index:A}`` emit current record index for section A + +.. note:: + + See :source:`Sming/Core/Data/Streams/SectionTemplate.h` for an up-to-date list of commands and internal variables. + +Here's an excerpt from the Basic_IFS sample, displaying information for a single file: + +.. code-block:: html + + {!iflt:$record:100} +
    + + + + + + {!ifin:attr:"D"} + Too many records {$record} + {!endif} + + + +API Reference +------------- + +.. doxygenclass:: TemplateStream + :members: + +.. doxygenclass:: SectionTemplate + :members: + +.. doxygenclass:: SectionStream + :members: + diff --git a/docs/source/framework/core/datetime.rst b/docs/source/framework/core/datetime.rst new file mode 100644 index 0000000000..f6a10661a2 --- /dev/null +++ b/docs/source/framework/core/datetime.rst @@ -0,0 +1,13 @@ +Date and Time +============= + +DateTime class +-------------- + +.. doxygenclass:: DateTime + :members: + +System Clock +------------ + +.. doxygenfile:: Core/SystemClock.h diff --git a/docs/source/framework/core/filesystem.rst b/docs/source/framework/core/filesystem.rst new file mode 100644 index 0000000000..26bdae9317 --- /dev/null +++ b/docs/source/framework/core/filesystem.rst @@ -0,0 +1,4 @@ +File System +=========== + +.. doxygenfile:: Core/FileSystem.h diff --git a/docs/source/framework/core/index.rst b/docs/source/framework/core/index.rst index 081c9c6f23..d97bf96fd8 100644 --- a/docs/source/framework/core/index.rst +++ b/docs/source/framework/core/index.rst @@ -6,3 +6,5 @@ Core Framework pgmspace data/index + datetime + filesystem diff --git a/docs/source/framework/core/pgmspace.rst b/docs/source/framework/core/pgmspace.rst index ecbcedd367..b376e93af1 100644 --- a/docs/source/framework/core/pgmspace.rst +++ b/docs/source/framework/core/pgmspace.rst @@ -113,8 +113,8 @@ library, however Sming has some additions and differences. } Both :c:func:`DEFINE_PSTR` and :c:func:`PSTR_ARRAY` load a PSTR into a stack buffer, but using -:c:func:`sizeof` on that buffer will return a larger value than the string itself because it's aligned. -Calling :c:func:`sizeof` on the original flash data will get the right value. +``sizeof`` on that buffer will return a larger value than the string itself because it's aligned. +Calling ``sizeof`` on the original flash data will get the right value. If it's a regular nul-terminated string then :c:func:`strlen_P` will get the length, although it's time-consuming. diff --git a/docs/source/framework/services/profiling/cpu-usage.rst b/docs/source/framework/services/profiling/cpu-usage.rst index 861a6bdb36..b88fd57309 100644 --- a/docs/source/framework/services/profiling/cpu-usage.rst +++ b/docs/source/framework/services/profiling/cpu-usage.rst @@ -26,7 +26,7 @@ Use like this:: } -See :sample:`RingTonePlayer` for a more detailed example. +See :sample:`Basic_Tasks` for a more detailed example. CPU usage is calculated over an update period which begins with a call to :cpp:func:`Profiling::CpuUsage::reset`. The actual update period must be managed elsewhere, using a callback timer, web request diff --git a/docs/source/framework/wiring/wstring.rst b/docs/source/framework/wiring/wstring.rst index 9496ee0c1a..e90a347301 100644 --- a/docs/source/framework/wiring/wstring.rst +++ b/docs/source/framework/wiring/wstring.rst @@ -55,3 +55,5 @@ API Documentation .. doxygenclass:: String :members: + +.. doxygentypedef:: FlashString diff --git a/docs/source/getting-started/config.rst b/docs/source/getting-started/config.rst index 970f0e4250..b3db391ea7 100644 --- a/docs/source/getting-started/config.rst +++ b/docs/source/getting-started/config.rst @@ -1,18 +1,72 @@ -Configuring your device ------------------------ +Configuration +============= .. highlight:: bash +Environment variables +--------------------- + +Certain environment variables should be set globally so that command prompts +and integrated development environments (IDEs) work correctly. + +You can find a list of these in :source:`Tools/export.sh`. + +For Linux and WSL2, append values to your ``~/.bashrc`` file:: + + # All architectures + export SMING_HOME=/opt/sming/Sming + + # Esp8266 + export ESP_HOME=/opt/esp-quick-toolchain + + # Esp32 + export IDF_PATH=/opt/esp-idf + export IDF_TOOLS_PATH=/opt/esp32 + export ESP32_PYTHON_PATH=/usr/bin + + # Rp2040 + export PICO_TOOLCHAIN_PATH=/opt/rp2040 + +Another approach is to place these in a separate file, then add `source ~/.smingrc`. + +For Windows, you can either edit the global variables graphically via control panel, +or use the ``setx`` command: + +.. code-block:: batch + + REM All architectures + setx SMING_HOME "c:\tools\sming\Sming" + + REM Esp8266 + setx ESP_HOME "c:\tools\esp-quick-toolchain" + + REM Esp32 + setx IDF_PATH "c:\tools\esp-idf" + setx IDF_TOOLS_PATH "c:\tools\esp32" + setx ESP32_PYTHON_PATH "c:\Python39" + + REM Rp2040 + setx PICO_TOOLCHAIN_PATH "c:\tools\rp2040" + +In both cases values will only take effect in new sessions so close/reopen command prompts or IDEs. + +Note that project-specific settings should NOT be configured globally. +Please use the project's ``component.mk`` file for that purpose. + + +Configuring your device +----------------------- + You may need to configure your project to support the specific device being programmed: -* :envvar:`COM_PORT` If you haven't set this already, it will need to match the port you're using to talk to the Esp8266. +* :envvar:`COM_PORT` If you haven't set this already, it will need to match the port you're using to talk to the target device. * :envvar:`COM_SPEED_ESPTOOL` The default value should work fine but you can usually set a much faster speed. -You can set these initially on the command line, like this:: +You can change these on the command line:: make SMING_ARCH=Esp8266 COM_PORT=/dev/ttyUSB3 COM_SPEED_ESPTOOL=921600 -(For Windows or :doc:`windows/wsl` expect to use COM2, COM3, etc.) +For Windows or :doc:`windows/wsl` expect to use COM2, COM3, etc. Once you're happy with the settings, you can add them to your project's ``component.mk`` file. You may need to do this to reset the cached values:: diff --git a/docs/source/getting-started/linux/index.rst b/docs/source/getting-started/linux/index.rst index b2575b35a3..9c237ab553 100644 --- a/docs/source/getting-started/linux/index.rst +++ b/docs/source/getting-started/linux/index.rst @@ -49,7 +49,8 @@ Get a list of available options like this:: /opt/sming/Tools/install.sh Install locations can be customised by setting environment variables before -running the install. See ``/opt/sming/Tools/export.sh`` for details. +running the install. Certain variables should also be set globally. +See :doc:`/getting-started/config` for details. If you want to use the stable (release) branch:: diff --git a/docs/source/getting-started/windows/wsl.rst b/docs/source/getting-started/windows/wsl.rst index 71b25d9f3b..1061aeccce 100644 --- a/docs/source/getting-started/windows/wsl.rst +++ b/docs/source/getting-started/windows/wsl.rst @@ -1,5 +1,5 @@ -Windows WSL -=========== +WSL +=== .. highlight:: batch @@ -8,9 +8,9 @@ This is because the current build system requires a Posix emulation layer (MinGW However, it does offer the simplest way to use Sming on a Windows PC and does not affect the quality or functionality of your applications. -However, there are situations where it is highly desirable to build Sming in a Linux environment, such as: +There are situations where it is highly desirable to build Sming in a Linux environment: -- Making use of linux-only development tools, such as valgrind (dynamic bug detection system) +- Making use of linux-only development tools, e.g. valgrind (dynamic bug detection system) - Integration building/testing prior to submitting a PR to the Sming repository - Need/want faster builds @@ -34,8 +34,7 @@ https://docs.microsoft.com/en-us/windows/wsl/ -- including most command-line tools, utilities, and applications -- directly on Windows, unmodified, without the overhead of a traditional virtual machine or dual-boot setup." -There are currently two versions of WSL, dubbed WSL1 and WSL2. -Either is fine, and you can switch between versions but WSL2 is recommended. +There are currently two versions of WSL: this documentation relates to **WSL2**. .. note:: @@ -45,7 +44,7 @@ Either is fine, and you can switch between versions but WSL2 is recommended. Installing WSL -------------- -See instructions here https://docs.microsoft.com/en-us/windows/wsl/install-win10#manual-installation-steps. +See instructions here https://docs.microsoft.com/en-us/windows/wsl/install. Install an up-to-date Linux distribution from the Microsoft store, currently ``Ubuntu-20.04``. @@ -80,16 +79,22 @@ Installing Sming Open a WSL command prompt and follow the instructions in :doc:`../linux/index`. +Please note: + +- A native Windows python3 distribution is required to enable access to serial ports. +- Ensure that python is available in the system path for both WSL2 and Windows. +- Do not set the :envvar:`PYTHON` environment variable. + +This will ensure that the build system can run python scripts either in WSL2 or in Windows as necessary. + Flashing devices ---------------- -WSL2 does not currently support access to USB serial devices, so the Sming build system incorporates a workaround -which runs the appropriate application (esptool) directly under Windows (via powershell). - -Therefore, use the normal Windows COM port name rather than the linux ones (such as /dev/ttyUSB0). +WSL2 does not currently support access to USB serial devices, so the Sming build system runs +the appropriate application directly under Windows using ``powershell.exe``. -For example:: +Therefore, use the normal Windows COM port name rather than the linux ones (such as /dev/ttyUSB0):: make flash COM_PORT=COM4 diff --git a/docs/source/index.rst b/docs/source/index.rst index 7019f1eeb8..72100bea81 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -5,9 +5,8 @@ Welcome to Sming Framework **Let's do smart things!!!** -Sming is an asynchronous C/C++ framework with superb performance and multiple network features. -Sming is open source and is tailored towards embedded devices. -It supports multiple architectures as ESP8266 for example. +Sming is an asynchronous embedded C/C++ framework with superb performance and multiple network features. +Sming is open source, modular and supports :doc:`multiple architectures ` including ESP8266 and ESP32. |samples|_ @@ -19,31 +18,57 @@ Summary ------- - Superb performance and memory usage (Sming compiles to native firmware!) - Fast and user friendly development -- Simple yet powerful hardware API wrappers -- Compatible with standard :doc:`libraries` - use any popular hardware in few lines of code -- Multiple file system support: :component:`IFS`, :library:`Spiffs`, :library:`LittleFS` +- Integrated :doc:`host emulator ` to assist with developing, testing and debugging + libraries and applications on a PC before uploading them to an actual microcontroller. + Try it out online `here `__. - Built-in powerful wireless modules -- Powerful asynchronous (async) network stack. +- Compatible with standard :doc:`libraries` - use popular hardware in few lines of code +- Simple yet powerful hardware API wrappers + + - Standard Arduino-style wrappers for simplicity and flexibility + - :library:`HardwareSPI` library provides advanced asynchronous SPI device master capability + including use of ESP8266 'overlapped' mode for reduced pin usage and dual/quad I/O support. + - :library:`Graphics` implements asynchronous display control model with low memory usage, + transparency (alpha-blending) and flexible scripted resource management. + +- Modular C++ installable file system interface + + - Supports popular :library:`SPIFFS ` and :library:`LittleFS ` filing systems + - New :component:`FWFS ` read-only filesystem can be used as base file system, + with read/write filesystems mounted in sub-directories + - Integrated metadata support (file times, security descriptors, user metadata) + - Access to Host (linux / Windows / MacOS) filing system via same API + - Integrated streaming archival system to support backups or file system compaction operations + +- Powerful asynchronous (async) :doc:`network stack ` including: + + - Async TCP and UDP stack based on `LWIP `__. + - With clients supporting: HTTP, MQTT, WebSockets and SMTP. + - And servers for: DNS, FTP, HTTP(+ WebSockets), Telnet. + - With :doc:`SSL support <_inc/Sming/Components/ssl/index>` for all network clients and servers. + Based on `axTLS `__ and `BearSSL `__. + - Over-The-Air (OTA) firmware upgrades via HTTP(S) and MQTT(S). + +- :library:`Universal Plug and Play (UPnP) ` + framework supports both standard and custom devices with full ControlPoint support. + + - Generates C++ code from standard :library:`UPnP XML schema `. + - Companion :library:`SSDP` library independently supports discovery on local network. + - :library:`GoogleCast` library allows control of ChromeCast devices or smart TVs supporting the GoogleCast protocol. + - :library:`HueEmulator` provides simple way to implement devices compatible with Amazon Alexa. - - Async TCP and UDP stack based on `LWIP `__. - - With clients supporting: HTTP, MQTT, WebSockets and SMTP. - - And servers for: DNS, FTP, HTTP(+ WebSockets), Telnet. - - With :doc:`SSL support <_inc/Sming/Components/ssl/index>` for all network clients and servers. - Based on `axTLS `__ and `BearSSL `__. - - Over-The-Air(OTA) firmware upgrades via HTTP(S) and MQTT(S). +- ESP8266 features -- ESP8266 specific features + - Integrated boot loader :component:`rboot` with support for 1MB ROMs, OTA firmware updating and ROM switching. + - :doc:`Crash handlers ` for analyzing/handling system restarts due to fatal errors or WDT resets. + - :component-esp8266:`PWM support ` based on `Stefan Bruens PWM `__. + - Optional :component-esp8266:`custom heap allocation ` based on `Umm Malloc `__. + - Based on :component-esp8266:`Espressif NONOS SDK Version 3 `. - - Integrated boot loader :component:`rboot` with support for 1MB ROMs, OTA firmware updating and ROM switching. - - :doc:`Crash handlers ` for analyzing/handling system restarts due to fatal errors or WDT resets. - - :component-esp8266:`PWM support ` based on `Stefan Bruens PWM `__. - - Optional :component-esp8266:`custom heap allocation ` based on `Umm Malloc `__. - - Based on :component-esp8266:`Espressif NONOS SDK `. Tested with versions 1.5, 2.0 and 3.0. +- ESP32 features -- Linux/Windows features + - Based on :component-esp32:`ESP IDF SDK ` - - Sming has a :doc:`host emulator ` that allows libraries and sample applications to be compiled on a Linux/Windows host system - and be tested before uploading them to an actual microcontroller. .. toctree:: :caption: Contents: diff --git a/docs/source/information/debugging.rst b/docs/source/information/debugging.rst index 00cd5b6f78..aa1b8ffdda 100644 --- a/docs/source/information/debugging.rst +++ b/docs/source/information/debugging.rst @@ -18,4 +18,4 @@ The links below will give you more information and step-by-step instructions. /arch/host/debugging/index /arch/esp8266/debugging/index /arch/esp32/debugging/index - + /arch/rp2040/debugging/index diff --git a/docs/source/information/develop/ci.rst b/docs/source/information/develop/ci.rst new file mode 100644 index 0000000000..c149a33a70 --- /dev/null +++ b/docs/source/information/develop/ci.rst @@ -0,0 +1,250 @@ +Continuous Integration Testing +============================== + +.. highlight:: bash + +It is important to ensure that any change made to framework code does not introduce additional bugs. +In practice, this is impossible to guarantee but we can at least perform a full build of the entire +framework with all samples (both in the framework any any associated libraries). + +This is done using the integration testing framework using linux and Windows build environments. + +In addition, a number of integration tests are run using Host builds which verify the logic of a large +proportion of the code. +Testing low-level operation requires real hardware and this must be done manually, but in general +libraries and samples can be largely tested using Host builds and carefully constructed tests. + +The :library:`SmingTest` library should be used for such test applications to ensure they +are supported on all architectures. +It also provides a mechanism for logging test results. + + +Appveyor +-------- + +We use `appveyor `__ to manage all test builds. +This service is free of charge for open-source projects. + +Note: We used to use `Travis `__ but this is no longer free of charge. + +The build is controlled via the ``appveyor.yml`` file in the sming root directory. +Sming performs the build and test logic is handled using scripts, which are intended to be easily +portable to other CI services if necessary. +Mostly batch scripts (.cmd) are used for Windows, and bash scripts (.sh) for GNU/Linux but +where practical powershell core is used as this runs on either. + + +.. note:: + + Appveyor also supports macOS but at present Sming doesn't perform CI builds on that platform. + + +Configuration +~~~~~~~~~~~~~ + +Sming developers may use integration testing for their own projects, libraries or framework changes. + +Configure as follows: + +- Visit https://www.appveyor.com/ and create an account. It's usually easiest to sign up using the ``GitHub`` link. +- Select ``Projects`` from the toolbar and click on ``New Project``. If there are no projects listed make sure + AppVeyor has been authorised as a GitHub App. +- You can now click ``New Build`` to build the default branch. + This may not be what you require so visit the project settings page and configure as necessary. + +By default, pull requests are built automatically. + +The `Rolling builds `__ +setting ensures that only the most recent commit to a branch is built, so should usually be enabled. + + +Library CI support +------------------ + +Appveyor may be configured to test a Sming library separately. Steps to enable: + +Add project to appveyor account + ``Projects`` -> ``New Project`` and select from list + +Set ``Custom Configuration`` + to https://raw.githubusercontent.com/SmingHub/Sming/develop/Tools/ci/library/appveyor.txt. + +Set ``Project URL slug`` + If the library under test already exists in the Sming framework then the test directory + MUST have the same name to ensure it gets picked up. + + For example, testing the ``Sming-jerryscript`` library requires this value to be set to ``jerryscript`` + to match the Sming library name. + Build logs should then report a warning ``Multiple matches found for Component 'jerryscript'. + +Set sming fork/branch + By default builds use the main Sming ``develop`` branch. + If testing a library which requires changes to the framework, you'll need to use a fork + and add ``SMING_REPO`` and ``SMING_BRANCH`` environment variables to the project settings. + + Note that environment variables set here will override any values set in appveyor.txt. + +The provided default :source:`makefile ` +builds all applications within the library's ``samples`` directory. +If a test application is provided then that should be located in a ``test`` directory. +This is built for all architectures, and also executed for Host. + + +Build on your own 'cloud' +------------------------- + +Resources are limited to one concurrent build job per appveyor account. +Each build gets two virtual CPUs but they're not particular fast. +Network connectivity is, on the other hand, excellent! + +One very useful feature that appveyor provides is `Bring Your Own Cloud or Computer `__. +This allows the actual builds to be run on other hardware. + +Builds can have up to 5 concurrent jobs and as many CPUs as are available. +In addition, build images can be pre-installed with toolchains. +This can reduce total run times from 5+ hours to around 30 minutes. + + +Configuration +~~~~~~~~~~~~~ + +Full support requires a Windows server with Hyper-V, WSL2 and `Docker `__ installed. +Hyper-V is built into Windows 10/11 professional edition. +WSL2 should be available on all Windows versions. + +Linux/MacOS are supported but only for GNU/Linux images. + +Note that whilst Docker supports both Windows and Linux images, both cannot be used at the same time: +it is necessary to manually switch between Linux/Windows containers. +However, testing shows much better performance using Hyper-V for Windows builds. + +1. Add Docker build cloud for Linux builds: + + - Appveyor -> BYOC -> Add Cloud + + - Cloud Provider: Docker + + - Operating system: Windows + + - Base Image: ``Ubuntu 20.04 Minimal`` + + - Shell commands:: + + git clone https://github.com/SmingHub/Sming --branch develop --depth 1 /tmp/sming + pwsh /tmp/sming/Tools/Docker/appveyor/setup.ps1 + + - Image name: ``linux`` + + Execute commands as indicated in the resulting screen. + + Wait for the image to be built. + + The final stage updates the cloud information in your appveyor account. + Customise as follows: + + - Name + Change this so it contains only letters, numbers and dash (-). + Default names contain a space, e.g. ``COMPUTER Docker`` so change to ``COMPUTER-Docker`` + + - Custom Docker command arguments + Customise CPU resources, RAM usage, etc. For example:: + + --cpus=8 + + See https://docs.docker.com/engine/reference/commandline/run/. + + - Failover strategy + Default values will fail a job if no worker is available to service it. + The following settings are suggested:: + + Job start timeout: 60 + Provisioning attempts: 100 + + +2. Add Hyper-V build cloud for Windows builds: + +Same as (1) above except: + +- Cloud Provider: Hyper-V +- Base Image: ``Windows Server Core 2019 Minimal`` +- Image name: ``windows`` + +When complete, fix the build cloud name as previously, e.g. ``COMPUTER-HyperV``. +Also check CPU cores, RAM allocation, failover strategy. + + +3. Fix authorization token + +The above steps will also install the Appveyor Host Agent software on your computer. +This is the software which communicates with the Appveyor server and directs the build jobs. + +The authorization token used by the agent can be found in the registry: + +.. code-block:: text + + Computer\HKEY_LOCAL_MACHINE\SOFTWARE\AppVeyor\HostAgent + +Make sure that both clouds have the same token. + + +4. Configure BYOC images + + Select ``BYOC`` -> ``Images`` and amend mappings as follows: + + (1) + + - Image Name: ``Ubuntu2004`` + - OS Type: ``Linux`` + - Build cloud: "COMPUTER-Docker" (as configured above) + + (2) + + - Image Name: ``Visual Studio 2019`` + - OS Type: ``Windows`` + - Build cloud: "COMPUTER-HyperV" (as configured above) + + Now, when a build is started it should use your own server. + To revert back to normal operation change the ``Image Name`` fields in the entries. + It's not necessary to delete them: just add, say, "X" to the name so they're not recognised. + + + .. note:: + + Clouds may also be configured on a per-project basis by setting the ``APPVEYOR_BUILD_WORKER_CLOUD`` + environment variable to the appropriate cloud name. + + To get both Linux and Windows builds working concurrently using this approach would require a single + cloud to support dual images. + + +Rebuilding docker images +~~~~~~~~~~~~~~~~~~~~~~~~ + +Appveyor images are customised by pre-installing Sming build tools. +When these are updated images must be re-built. + +The easiest way to do this is using the provided dockerfiles:: + + cd $SMING_HOME/../Tools/Docker/appveyor + docker build --no-cache -t linux -f Dockerfile-Linux . + docker build --no-cache -t windows -f Dockerfile-Windows . + + +Custom images +------------- + +To use a Sming fork for building the image simply replace the repo URL and branch in the ``Shell Commands`` given above. + +These may also be passed to docker build as follows:: + + docker build -t linux-test -f Dockerfile-Linux --build-arg SMING_REPO=https://github.com/myrepo/Sming --build-arg SMING_BRANCH=feature/appveyor-revisions . + + +Issues +------ + +If you get error ``image not supported by cloud`` this probably means an image has been mapped to the wrong clould. +Goto Appveyor -> BYOC -> Images and update/delete the offending entries. + +If either cloud is shown as ``offline`` then check the authorization token (step 4 above). +It may be necessary to restart the ``Appveyor Host Agent`` service (via Windows service manager). diff --git a/docs/source/information/develop/coding-style.rst b/docs/source/information/develop/coding-style.rst index 9531e94e79..a9bfa632b1 100644 --- a/docs/source/information/develop/coding-style.rst +++ b/docs/source/information/develop/coding-style.rst @@ -86,7 +86,7 @@ Variables Local variables, instance variables, and class variables must also be written in lowerCamelCase. Variable names must not start with, end with or contain underscore (\_) or dollar sign ($) characters. - This is in constrast to some coding conventions which prefix all instance variables with underscore, + This is in contrast to some coding conventions which prefix all instance variables with underscore, however this is reserved by the C++ standard and can create problems. Variable names should be short yet meaningful. The choice of a variable name should be mnemonic — that is, diff --git a/docs/source/information/develop/documentation.rst b/docs/source/information/develop/documentation.rst index d9164045e8..c2164682fe 100644 --- a/docs/source/information/develop/documentation.rst +++ b/docs/source/information/develop/documentation.rst @@ -6,7 +6,7 @@ Documentation System Read the Docs and Sphinx ------------------------ -Online documention is managed via +Online documentation is managed via `Read the Docs `_, which uses `Sphinx `_ as the documentation build system. @@ -71,7 +71,7 @@ All Components, Libraries and Samples must include a ``README.rst`` or ``README. - **References**: Is this based on or does it use existing code? Please include details. - **Datasheets**: If appropriate, please include links to manufacturer's or external development websites. Note that any submodules or dependencies are automatically documented: see :doc:`/_inc/Sming/building` for details, - specifically `COMPONENT_SUBMODULES` and `COMPONENT_DEPENDS`. + specifically :envvar:`COMPONENT_SUBMODULES` and :envvar:`COMPONENT_DEPENDS`. You should also try to include any other information which could be useful information for a new developer. The purpose of samples projects is to demonstrate specific features or libraries, so please ensure this is adequately described. @@ -212,16 +212,12 @@ component.mk file to direct doxygen parsing: Build (environment) variables ----------------------------- -These are defined in the README for the corresponding Component using: - -:: +These are defined in the README for the corresponding Component using:: :envvar::`COM_SPEED` Determines default serial port speed -You can refer to them like this: - -:: +You can refer to them like this:: Change baud rate using the :envvar:`COM_SPEED` variable. @@ -236,9 +232,7 @@ The documentation build system provides some custom roles for creating links. Components ~~~~~~~~~~ -Inserting a link to a Component page, using the title of that page by default: - -:: +Inserting a link to a Component page, using the title of that page by default:: See :library:`Spiffs` for details of the flash filing system. @@ -252,9 +246,7 @@ the README description. Libraries ~~~~~~~~~ -As for Components, refer to libraries like this: - -:: +As for Components, refer to libraries like this:: Use the :library:`Adafruit_ST7735` library to do some fancy display stuff. @@ -262,32 +254,64 @@ As for Components, refer to libraries like this: Sample applications ~~~~~~~~~~~~~~~~~~~ -To refer to a sample application README: - -:: +To refer to a sample application README:: See the :sample:`Basic_Blink` sample for a simple introduction to Sming. +Samples may be located in the main Sming :source:`samples`, but a growing number +are located in a **samples** sub-directory of the associated Component or library. + +Another example:: + + Where is the :sample:`generic` sample? + +There are currently three libraries with a sample called 'generic'. +Documents within the appropriate library will be matched correctly. + +The given target 'generic' is matched as follows: + +- Is the document contained in a Component or library? + - Yes: Look in the Component's **samples** sub-directory, if there is one +- No match? Then check the main sming **samples** directory. +- Still no match? Pick the first match from any other Component. +- No match found? Text will appear unchanged in the output document. + +To refer to a sample in a specific Component, do this:: + + I'm looking for the :sample:`CS5460/generic` sample. + Where is :sample:`Generic CS5460 sample ` sample? + +Within main samples directory:: + + Is there a main :sample:`/generic` sample? Actually, no. + But there is a :sample:`/CanBus` sample! + Source code ~~~~~~~~~~~ -To refer to source code use the path relative to the root working directory, for example: +Use within the framework + Use the file or directory path relative to the root directory. For example:: + + See :source:`Sming/Core/DateTime.h` + + will create a hyperlink to the source file in the Sming repository on github. -:: +Use within a Component or library + The source link will be interpreted relative to the Component root directory. + You can find an example of this usage in the :library:`UPnP` README:: - See :source:`Sming/Core/DateTime.h` + :source:`samples/Basic_UPnP/include/Wemo.h#L59-L91` -If the documentation is built locally, it will use the local file path, otherwise it will create -a link to the source file on github. + If you wish to refer to a source file elsewhere in Sming, prefix with '/':: + + See :source:`/tests/HostTests/modules/Timers.cpp` for an example. Issues and Pull Requests ~~~~~~~~~~~~~~~~~~~~~~~~ -If you want to refer to discussions on github, insert links like this: - -:: +If you want to refer to discussions on github, insert links like this:: See :pull-request:`787` @@ -300,16 +324,12 @@ Eclipse You can find a good plugin editor for Eclipse by searching the marketplace for ``rest editor``. For example, http://resteditor.sourceforge.net/. A useful feature is dealing with -heading underscores, just type this: - -:: +heading underscores, just type this:: My Heading == -Then when you save the file it gets formatted like this: - -:: +Then when you save the file it gets formatted like this:: My Heading ========== @@ -323,7 +343,7 @@ Sphinx Extensions The documentation system is easily extended to support new features. This section summarises the extensions included. -`m2r `__ +`m2r2 `__ Provides support for markdown content. @@ -338,3 +358,6 @@ This section summarises the extensions included. `sphinxcontrib.wavedrom `__ For implementing timing and other waveform diagrams within documents. See :library:`Servo` for an example. + +`sphinxcontrib.seqdiag `__ + For embedding sequence diagrams, such as in the :doc:`/information/tasks` page. diff --git a/docs/source/information/develop/external-sources.rst b/docs/source/information/develop/external-sources.rst index 9f094edabb..065e52b1a2 100644 --- a/docs/source/information/develop/external-sources.rst +++ b/docs/source/information/develop/external-sources.rst @@ -113,7 +113,7 @@ Applications can use it by adding the name to their COMPONENT_DEPENDS or ARDUINO entries in component.mk as appropriate. Submodules contained within a Component must be declared by adding them to the -COMPONENT_SUBMODULES entry in component.mk. +:envvar:`COMPONENT_SUBMODULES` entry in component.mk. Moving submodules diff --git a/docs/source/information/multitasking.rst b/docs/source/information/multitasking.rst index 4220613862..c1f287cd2d 100644 --- a/docs/source/information/multitasking.rst +++ b/docs/source/information/multitasking.rst @@ -27,7 +27,7 @@ FreeRTOS is perhaps the most well-known example of a pre-emptive embedded OS. Co-operative Multitasking ------------------------- -By constrast, *Co-operative Multitasking*, requires applications to 'play fair' and not hog the CPU. +By contrast, *Co-operative Multitasking*, requires applications to 'play fair' and not hog the CPU. This means that whenever you get called to do some work, you must release control back to the system in a timely manner. diff --git a/docs/source/information/rboot-ota.rst b/docs/source/information/rboot-ota.rst index 5f22026f90..6cbe1e17fc 100644 --- a/docs/source/information/rboot-ota.rst +++ b/docs/source/information/rboot-ota.rst @@ -12,7 +12,7 @@ bootloader allows you to have more than one application on the esp8266, either completely different apps, or different version of the same app, which can be updated over the air. -The example :sample:`Basic_rBoot` demonstrates the use of rBoot, but if you want +The example :sample:`Basic_Ota` demonstrates the use of rBoot, but if you want to add it to an existing project this little tutorial will guide you. Need to know @@ -108,5 +108,3 @@ products. A more lightweight solution is provided by :cpp:class:`RbootOutputStream`, which is just a thin wrapper around rBoot's flash API, in combination with :cpp:class:`RbootHttpUpdater`, which pulls individual ROM image from an HTTP server. - -For details, refer to the `OtaUpdate()` function in the :sample:`Basic_rBoot` sample. diff --git a/docs/source/link-roles.py b/docs/source/link-roles.py index 7ae29a2727..bbf7152f0c 100644 --- a/docs/source/link-roles.py +++ b/docs/source/link-roles.py @@ -12,6 +12,9 @@ from docutils import nodes, utils from sphinx import roles, addnodes from sphinx.util.nodes import set_role_source_info, split_explicit_title +from sphinx.util import logging + +logger = logging.getLogger(__name__) github_url = 'https://github.com/SmingHub/Sming' @@ -29,30 +32,23 @@ def get_github_rev(): def setup(app): - baseurl = os.path.splitext(run_cmd_get_output('git ls-remote --get-url'))[0] - - sming_home = os.environ.get('SMING_HOME', None) - if sming_home: - smingdir = os.path.abspath(sming_home + '/..') - print('SMINGDIR = ' + smingdir) - basepath = 'file://' + smingdir - else: - basepath = baseurl + '/blob/' + get_github_rev() - - app.add_role('source', autolink(basepath + '/{}')) + app.add_role('source', SourceRole()) app.add_role('issue', autolink('Issue #{0} <' + github_url + '/issue/{0}>')) app.add_role('pull-request', autolink('Pull Request #{0} <' + github_url + '/pull/{0}>')) - app.add_role('sample', doclink('/_inc/samples/{}/index')) + app.add_role('sample', SampleRole) app.add_role('component', doclink('/_inc/Sming/Components/{}/index')) app.add_role('component-esp8266', doclink('/_inc/Sming/Arch/Esp8266/Components/{}/index')) app.add_role('component-esp32', doclink('/_inc/Sming/Arch/Esp32/Components/{}/index')) app.add_role('component-host', doclink('/_inc/Sming/Arch/Host/Components/{}/index')) + app.add_role('component-rp2040', doclink('/_inc/Sming/Arch/Rp2040/Components/{}/index')) app.add_role('library', doclink('/_inc/Sming/Libraries/{}/index')) -# Insert a link to a file or issue in the repo -# Both pattern and user text may use optional format, e.g. `title ` def autolink(pattern): + """Insert a link to a file or issue in the repo. + Both pattern and user text may use optional format, e.g. `title ` + """ + def role(name, rawtext, text, lineno, inliner, options={}, content=[]): text_has_explicit_title, link_text, link = split_explicit_title(text) pattern_has_explicit_title, pattern_text, pattern_link = split_explicit_title(pattern) @@ -64,8 +60,9 @@ def role(name, rawtext, text, lineno, inliner, options={}, content=[]): return role -# Default title is extracted from target document def doclink(pattern): + """Default title is extracted from target document.""" + def DocumentRole(typ, rawtext, text, lineno, inliner, options={}, content=[]): # type: (unicode, unicode, unicode, int, Inliner, Dict, List[unicode]) -> Tuple[List[nodes.Node], List[nodes.Node]] # NOQA env = inliner.document.settings.env @@ -86,3 +83,119 @@ def DocumentRole(typ, rawtext, text, lineno, inliner, options={}, content=[]): return [refnode], [] return DocumentRole + + +def SampleRole(typ, rawtext, text, lineno, inliner, options={}, content=[]): + """Sample may be in current component/library or main sample repository.""" + + # split title and target in role content + has_explicit_title, title, target = split_explicit_title(text) + title = utils.unescape(title) + target = utils.unescape(target) + + env = inliner.document.settings.env + pageUrls = env.config.html_context['page_urls'] + docname = env.docname + + # Target can be "{sample name}" or "{component name}/{sample name}" + if target.startswith('/'): + expr = f"_inc/samples{target}/index.rst" + else: + segs = target.split('/') + if len(segs) == 2: + expr = f"/{segs[0]}/samples/{segs[1]}/index.rst" + else: + expr = f"/samples/{target}/index.rst" + + # Search for all sample matches + pageList = list(filter(lambda page: page.endswith(expr), pageUrls)) + + logger.verbose(f">> :sample:`{target}` found {pageList}") + + sampleTarget = None + if len(pageList) == 1: + # One match, use it + sampleTarget = pageList[0] + elif len(pageList) > 1: + # Multiple matches: we have some decisions to make + # If document page is in a Component then check that first + cmp = getComponentPath(docname) + if cmp is not None: + sampleTarget = next(filter(lambda page: page.startswith(cmp), pageList), None) + # Not found? Then check main samples directory + if sampleTarget is None: + sampleTarget = next(filter(lambda page: page.startswith('_inc/samples'), pageList), None) + # Still not found? Default to first match + if sampleTarget is None: + sampleTarget = pageList[0] + + # No match found, leave target unchanged + if sampleTarget is None: + sampleTarget = target + else: + # Absolute path required, without extension + sampleTarget = "/" + os.path.splitext(sampleTarget)[0] + + logger.verbose(f">> sample '{target}' -> '{sampleTarget}'") + + # create the reference node + refnode = addnodes.pending_xref(rawtext, reftype='doc', refdomain='std', refexplicit=has_explicit_title) + # we may need the line number for warnings + set_role_source_info(inliner, lineno, refnode) # type: ignore + # now that the target and title are finally determined, set them + refnode['reftarget'] = sampleTarget + refnode += nodes.inline(rawtext, title, classes=['xref', 'doc']) + # we also need the source document + refnode['refdoc'] = docname + refnode['refwarn'] = True + return [refnode], [] + + +def getComponentPath(path): + """Obtain name of Component or library from document path. + Return None if document is not in a Component or library. + """ + + a, b, c = path.partition("/Components/") + if b == "": + a, b, c = path.partition("/Libraries/") + if b == "": + return None + + return f"{a}{b}{c.split('/')[0]}" + + +def SourceRole(): + """Create hyperlink to source code, which may be in a submodule.""" + + def role(name, rawtext, text, lineno, inliner, options={}, content=[]): + _, link_text, link = split_explicit_title(text) + + env = inliner.document.settings.env + rootUrls = env.config.html_context['root_urls'] + rootPaths = env.config.html_context['root_paths'] + + def getRoot(srcpath): + path = next(filter(link.startswith, rootPaths), '') + return rootUrls[path], link[len(path):] + + if link.startswith('/'): + # Absolute links are relative to Sming repo + linkUrl = rootUrls[''] + link + else: + # Resolve link paths within Components + path = getComponentPath(env.docname) + if path is not None: + path = path[5:] # skip '_inc/' + if not link.startswith(path): + # print(f">> {link} -> {path}/{link}") + link = f"{path}/{link}" + linkUrl, linkPath = getRoot(link) + linkUrl = f"{linkUrl}/{linkPath}" + + logger.verbose(f">> source '{link}' -> '{linkUrl}'") + node = nodes.reference(rawtext, link_text, refuri=linkUrl, **options) + return [node], [] + + + return role diff --git a/docs/source/tools/clion.rst b/docs/source/tools/clion.rst index 036f1ef986..e95f5a2818 100644 --- a/docs/source/tools/clion.rst +++ b/docs/source/tools/clion.rst @@ -1,7 +1,21 @@ -**************** Using with CLion **************** +.. note:: + + This information is no longer current. + + However, if you are able to set up an external ``make`` project with CLion that should work. + + To get intelliense (or whatever the equivalent for CLion is) will require setting up a list of the correct #include paths. + For vscode we have a tool to handle that: + + - run ``make ide-vscode`` from a sample project directory + - examine generated path list in ``.vscode/c_cpp_properties.json`` + + Something similar could be done for CLion perhaps? + + Developing with the Sming framework can also be done in CLion. 1. Copy and paste Makefiles into the project diff --git a/docs/source/tools/eclipse.rst b/docs/source/tools/eclipse.rst new file mode 100644 index 0000000000..4bbeb3201b --- /dev/null +++ b/docs/source/tools/eclipse.rst @@ -0,0 +1,54 @@ +Using with Eclipse CDT +====================== + +.. highlight:: bash + +The Eclipse CDT Project provides a fully functional C and C++ Integrated Development Environment based on the Eclipse platform. +Eclipse is a free (as in "free beer") and Open Source code editor for Windows, Linux and Mac. + +For easier integration make sure you have both :envvar:`ESP_HOME` and +:envvar:`SMING_HOME` exported in your working environment. + + +Software involved +----------------- + +- `Eclipse CDT `__ + +Installation +------------ + +- Install Eclipse CDT using your operating system packaging tools. + +Configuration +------------- + +First you should import the Sming project. +This can be done by going to menu ``File`` -> ``Import`` and from there choosing +``General`` -> ``Existing project into Workspace``. When asked for the location of the project +point Eclipse to the location of your SMING_HOME folder. + +Once you have imported the Sming project you can import some of the samples. +You need to open in terminal the location of the sample of your interest and type:: + + cd /path/to/sample/ + make ide-eclipse + +This will create the minimum required meta files for an Eclipse CDT project which you can import into your Workspace. +``/path/to/sample/`` should be replaced with the actual location of the sample. +For the ``Basic_Blink`` sample we can use the following commands:: + + cd $SMING_HOME/../samples/Basic_Blink # Replace $SMING_HOME with %SMING_HOME% if you use Windows + make ide-eclipse + +After this you go back to your Eclipse and run again ``File`` -> ``Import`` and from there choose ``General`` -> ``Existing project into Workspace``. +Then select the ``Basic_Blink`` directory under ``samples``. Once the project is imported and the Eclipse CDT indexes +are build you will be able to program like a pro and have code completion and debug your code. +For the latter see :sample:`LiveDebug`. + +You can import also your own Sming-based applications in Eclipse. +If your application is not containing `.project` and `.cproject` files inside its root folder then +you can create such files by going to the root folder of your application and then typing the command below:: + + make ide-eclipse + diff --git a/docs/source/tools/index.rst b/docs/source/tools/index.rst index 34ce3ebee5..fef10c8fc0 100644 --- a/docs/source/tools/index.rst +++ b/docs/source/tools/index.rst @@ -7,4 +7,5 @@ Details of Sming support for Integrated Development Environments (IDEs). :maxdepth: 1 clion + eclipse vscode diff --git a/docs/source/tools/vscode.rst b/docs/source/tools/vscode.rst index 015efd36d5..bf5d254aa7 100644 --- a/docs/source/tools/vscode.rst +++ b/docs/source/tools/vscode.rst @@ -6,9 +6,6 @@ Using with MS Visual Studio Code Microsoft `Visual Studio Code `__ is a free (as in "free beer") and Open Source code editor for Windows, Linux and Mac. -For easier integration make sure you have both :envvar:`ESP_HOME` and -:envvar:`SMING_HOME` exported in your working environment. - Software involved ----------------- @@ -30,6 +27,9 @@ Installation Configuration ------------- +Please make sure you have critical environment variables set globally **before** starting vscode. +See :doc:`/getting-started/config` for details. + One of the strengths of vscode is the use of well-documented configuration files. You can find comprehensive documentation for these online. @@ -104,4 +104,6 @@ Known issues / features - ``make ide-vscode`` may overwrite parts of your configuration: be warned! - When debugging for esp8266 output in the console is not formatted correctly. Lines appear with @ in front of them. -- A debugging configuration is not currently provided for ESP32. +- You may find vscode uses powershell instead of cmd.exe to execute tasks. + Sming should work OK with either, but you can change this in the `sming.code-workspace` file + via the ``terminal.integrated.defaultProfile.windows`` setting. diff --git a/docs/source/upgrading/4.1-4.2.rst b/docs/source/upgrading/4.1-4.2.rst index 3e76580158..021eec78dc 100644 --- a/docs/source/upgrading/4.1-4.2.rst +++ b/docs/source/upgrading/4.1-4.2.rst @@ -12,10 +12,10 @@ Summary Stream methods -------------- -The :c:func:`Stream::readBytes` has been virtualised and overriden for :cpp:class:`IDataSourceStream` +The :cpp:func:`Stream::readBytes` has been virtualised and overridden for :cpp:class:`IDataSourceStream` descendents for more efficient operation, especially with ArduinoJson. For normal read operations where the stream position is to be updated, applications should use -this method in preference to :c:func:`IDataSourceStream::readMemoryBlock`. +this method in preference to :cpp:func:`IDataSourceStream::readMemoryBlock`. An addition method :cpp:func:`IDataSourceStream::moveString` has been added to support extracting the content of a memory-based stream into a String object without duplicating the data. @@ -32,7 +32,7 @@ and also by file system functions. Mappings are:: SeekOrigin::End instead of eSO_FileEnd These map to the standard C *SEEK_SET*, *SEEK_CUR* and *SEEK_END* but as SeekOrigin is strongly typed -it offers compile-time checking, and has a `toString(SeekOrigin)` overload. +it offers compile-time checking, and has a ``toString(SeekOrigin)`` overload. getBody methods @@ -48,6 +48,6 @@ then an invalid String will be returned. In this situation you should use :cpp:f ContentType / MIME types ------------------------ -:cpp:func:`toString(MimeType)` has been moved out of the ``ContentType`` namespace, +:cpp:func:`String toString(MimeType)` has been moved out of the ``ContentType`` namespace, so no longer requires the ``ContentType::`` qualifier. diff --git a/docs/source/upgrading/4.3-4.4.rst b/docs/source/upgrading/4.3-4.4.rst index a6e32914e7..8c104887d0 100644 --- a/docs/source/upgrading/4.3-4.4.rst +++ b/docs/source/upgrading/4.3-4.4.rst @@ -18,7 +18,7 @@ Note that ``Network/WebHelpers/aw-sha1.h`` has been removed in favour of the :co Ethernet support has been added, currently only for the ESP32 embedded MAC. If WiFi is not used then the :envvar:`DISABLE_WIFI` setting can be used to reduce code size. -The :envvar:`DISABLE_NETWORK` setting can be used to exclude all networking support for signficant code size reduction. +The :envvar:`DISABLE_NETWORK` setting can be used to exclude all networking support for significant code size reduction. ESP32 diff --git a/docs/source/upgrading/4.4-4.5.rst b/docs/source/upgrading/4.4-4.5.rst new file mode 100644 index 0000000000..800cb30d2a --- /dev/null +++ b/docs/source/upgrading/4.4-4.5.rst @@ -0,0 +1,124 @@ +From v4.4 to v4.5 +================= + +.. highlight:: c++ + +Template Streams +---------------- + +The :cpp:class:`TemplateStream` class has been updated to improve tag recognition (:pull-request:`2400`). +This means regular ``{varname}`` tags are sufficient for most purposes, including JSON templates. + +The :cpp:class:`IFS::JsonDirectoryTemplate` previously used double-brace tags such as ``{{varname}}``. +It now uses regular tags by default, so if you use this class either: + +1. Add a call to :cpp:func:`TemplateStream::setDoubleBraces` in your code, or +2. Update your templates to use single braces + + +Eclipse Project Files +--------------------- + +Starting with version 4.5.x we don't provide Eclipse meta files in our samples. +These can be generated using the ``ide-eclipse`` makefile target. +For more information read the updated :doc:`/tools/eclipse`. + + +Esp8266 toolchain +----------------- + +Sming now requires the :doc:`/arch/esp8266/getting-started/eqt` for building. + +Support for the old legacy toolchains (ESP open SDK, UDK) have been dropped. +They may still work but are no longer tested. + + +user_config.h +------------- + +This header file is part of the original ESP8266 SDK code and is now deprecated. +Libraries should use only the necessary headers. +Applications do not require it. + +Breaking Changes +---------------- + +Undeprecated :cpp:func:`HttpRequest::getQueryParameter` and removed a lot of old deprecated code. + +- Removed ``WebsocketClient::disconnect()``. Use :cpp:func:`WebsocketClient::close` instead. +- Removed ``TimerDelegateStdFunction``. Use :cpp:type:`TimerDelegate` instead. +- Removed class ``URL``. Use class :cpp:class:`Url` instead. +- Removed ``TemplateVariables``. Use :cpp:type:`TemplateStream::Variables` instead. +- Removed ``StreamTransformer::transformCallback``. Create inherited class and override :cpp:func:`StreamTransformer::transform` method instead. +- Removed ``StreamTransformer::StreamTransformer(IDataSourceStream* stream, const StreamTransformerCallback& callback, size_t resultSize, size_t blockSize)``. + Instead, create inherited class, override :cpp:func:`StreamTransformer::transform` method and use alternative constructor. +- Removed ``SslValidatorCallback``. Use :cpp:type:`Ssl::ValidatorCallback` instead. +- Removed ``SslSessionId`` and ``SSLSessionId``. Use :cpp:class:`Ssl::SessionId` instead. +- Removed ``SslKeyCertPair`` and ``SSLKeyCertPair``. Use :cpp:class:`Ssl::KeyCertPair` instead. +- Removed ``SslCertificate``. Use :cpp:class:`Ssl::Certificate` instead. +- Removed ``SeekOriginFlags``. Use :cpp:enum:`SeekOrigin` instead. +- Removed ``eSO_FileStart``. Use :cpp:enumerator:`SeekOrigin::Start` instead. +- Removed ``eSO_CurrentPos``. Use :cpp:enumerator:`SeekOrigin::Current` instead. +- Removed ``eSO_FileEnd``. Use :cpp:enumerator:`SeekOrigin::End` instead. +- Removed ``OtaUpgrade::BasicStream::errorToString()``. Use :cpp:func:`toString() ` instead. +- Removed deprecated stuff in Mqtt, including ``MQTT_MAX_BUFFER_SIZE`` and ``MQTT_MSG_PUBREC``. +- Removed ``MqttClient::publishWithQoS(const String& topic, const String& message, int QoS, bool retained, MqttMessageDeliveredCallback onDelivery)``. + Use :cpp:func:`bool MqttClient::publish(const String& topic, const String& message, uint8_t flags)` instead. + If you want to have a callback that should be triggered on successful delivery of messages, use :cpp:func:`MqttClient::setEventHandler`. +- Removed ``MqttClient::setCallback(MqttStringSubscriptionCallback subscriptionCallback)``. + Use :cpp:func:`MqttClient::setEventHandler` instead. +- Removed ``MqttClient::setWill (const String& topic, const String& message, int QoS, bool retained)``. + Use :cpp:func:`MqttClient::setWill` instead. +- Removed ``MqttMessageDeliveredCallback`` and ``MqttStringSubscriptionCallback``. Use :cpp:type:`MqttDelegate` instead. +- Removed ``IDataSourceStream::length()``. Use :cpp:func:`IDataSourceStream::available` instead. +- Removed ``HttpServer::setDefaultResource(HttpResource* resource)``. Use :cpp:func:`paths.setDefault() ` instead. +- Removed ``HttpServer::addPath(String path, const HttpPathDelegate& callback)``, + ``HttpServer::addPath (const String& path, const HttpResourceDelegate& onRequestComplete)`` and + ``HttpServer::addPath (const String& path, HttpResource* resource)``. + Use **paths.set()** instead. +- Removed ``HttpResponse::toString(const HttpResponse& res)``. + Use ::cpp:func:`HttpResponse::toString` method or :cpp:func:`toString() ` global function instead. +- Removed ``HttpResponse::sendTemplate(IDataSourceStream* newTemplateInstance)``. + Use :cpp:func:`HttpResponse::sendNamedStream` instead. +- Renamed ``commandFunctionDelegate`` to :cpp:type:`CommandFunctionDelegate`. +- Removed ``DateTime::convertFromUnixTime(time_t timep, int8_t* psec, int8_t* pmin, int8_t* phour, int8_t* pday, int8_t* pwday, int8_t* pmonth, int16_t* pyear)``. + Use :cpp:func:`DateTime::fromUnixTime` instead. +- Removed ``DateTime::convertToUnixTime (uint8_t sec, uint8_t min, uint8_t hour, uint8_t day, uint8_t month, uint16_t year)``. + Use :cpp:func:`DateTime::toUnixTime` instead. +- Removed ``DateTime::fromUnixTime(time_t timep, int8_t* psec, int8_t* pmin, int8_t* phour, int8_t* pday, int8_t* pwday, int8_t* pmonth, int16_t* pyear)``. + Use **unsigned** version instead :cpp:func:`void DateTime::fromUnixTime(time_t, uint8_t\*, uint8_t\*, uint8_t\*, uint8_t\*, uint8_t\*, uint8_t\*, uint16_t\*)`. +- Removed ``DateTime::parseHttpDate(const String& httpDate)``. Use :cpp:func:`DateTime::fromHttpDate` instead. +- Renamed ``DNSServer`` class to :cpp:class:`DnsServer`. +- Removed ``eFO_Append``. Use :cpp:var:`File::Append ` instead. +- Removed ``eFO_CreateIfNotExist``. Use :cpp:any:`File::Create` instead. +- Removed ``eFO_CreateNewAlways``. Use :cpp:member:`File::CreateNewAlways` instead. +- Removed ``eFO_ReadOnly``. Use :cpp:member:`File::ReadOnly` instead. +- Removed ``eFO_ReadWrite``. Use :cpp:member:`File::ReadWrite` instead. +- Removed ``eFO_Truncate``. Use :cpp:member:`File::Truncate` instead. +- Removed ``eFO_WriteOnly``. Use :cpp:member:`File::WriteOnly` instead. +- Removed ``eSO_FileStart``. Use :cpp:enumerator:`SeekOrigin::Start` instead. +- Removed ``eSO_CurrentPos``. Use :cpp:enumerator:`SeekOrigin::Current` instead. +- Removed ``eSO_FileEnd``. Use :cpp:enumerator:`SeekOrigin::End` instead. +- Removed ``fileList()`` function. Use :cpp:class:`Directory` object, or :cpp:func:`fileOpenDir` / :cpp:func:`fileReadDir` / :cpp:func:`fileCloseDir` functions. +- Removed ``FileStream::attach(const String& fileName, FileOpenFlags openFlags=File::ReadOnly)``. Use :cpp:func:`FileStream::open` instead. +- Removed ``FTPServer``. Use :cpp:class:`FtpServer` instead. +- Removed ``FtpServer::checkUser(const String& login, const String& pass)``. Use :cpp:func:`FtpServer::validateUser` instead +- Renamed ``Hardware_Timer`` to :cpp:type:`HardwareTimer`. +- Renamed ``HardwareSerial::setCallback(StreamDataReceivedDelegate dataReceivedDelegate)`` to :cpp:func:`HardwareSerial::onDataReceived`. +- Removed ``HttpClient::request(const String& url)``. Use :cpp:func:`HttpClient::createRequest` instead. +- Removed ``HttpConnection::getLastModifiedDate()``. Use ``getResponse()->headers.getLastModifiedDate()`` instead. +- Removed ``HttpConnection::getResponseCode()``. Use ``getResponse()->code`` instead. +- Removed ``HttpConnection::getResponseHeader(const String& headerName, const String& defaultValue)``. Use ``getResponse()->headers[]`` instead. +- Removed ``HttpConnection::getResponseHeaders()``. Use ``getResponse()->headers`` instead. +- Removed ``HttpConnection::getResponseString (). Use ``getResponse()->getBody()`` instead. +- Removed ``HttpConnection::getServerDate (). Use ``getResponse()->headers.getServerDate()`` instead. +- Removed ``httpGetErrorName (HttpError err)``. Use :cpp:func:`toString() ` instead. +- Renamed ``HttpPartProducerDelegate`` type to :cpp:type:`MultipartStream::Producer`. +- Renamed ``HttpPartResult`` type to :cpp:class:`MultipartStream::BodyPart`. +- Removed ``HttpRequest::getPath()``. Use :cpp:var:`request.uri.Path ` instead. +- Removed ``HttpRequest::operator=(const HttpRequest& rhs)``. Use :cpp:func:`HttpRequest::clone` instead. +- Removed ``HttpRequest::setPostParameters(const HttpParams& params)``. Use :cpp:var:`request.postParams = params ` instead. +- Removed ``HttpResponse::hasHeader(const String& name)``. Use :cpp:func:`headers.contains() ` instead. +- Removed ``HttpResponse::forbidden()``. Use :cpp:var:`response.code = HTTP_STATUS_FORBIDDEN ` instead. +- Removed ``HttpResponse::notFound()``. Use :cpp:var:`response.code = HTTP_STATUS_NOT_FOUND ` instead. +- Removed ``HttpResponse::redirect(const String& location)``. Use :cpp:var:`headers[HTTP_HEADER_LOCATION] ` instead. diff --git a/docs/source/upgrading/index.rst b/docs/source/upgrading/index.rst index 0365edf5b5..5dde9f953d 100644 --- a/docs/source/upgrading/index.rst +++ b/docs/source/upgrading/index.rst @@ -7,6 +7,7 @@ For newer versions we have dedicated pages. .. toctree:: :maxdepth: 1 + 4.4-4.5 4.3-4.4 4.2-4.3 4.1-4.2 diff --git a/samples/Accelerometer_MMA7455/.cproject b/samples/Accelerometer_MMA7455/.cproject deleted file mode 100644 index 381169c7e1..0000000000 --- a/samples/Accelerometer_MMA7455/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Accelerometer_MMA7455/.project b/samples/Accelerometer_MMA7455/.project deleted file mode 100644 index f9207c9ce6..0000000000 --- a/samples/Accelerometer_MMA7455/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Accelerometer_MMA7455 - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Accelerometer_MMA7455/component.mk b/samples/Accelerometer_MMA7455/component.mk index 2d423a2a56..ab1a9565ee 100644 --- a/samples/Accelerometer_MMA7455/component.mk +++ b/samples/Accelerometer_MMA7455/component.mk @@ -1 +1,2 @@ ARDUINO_LIBRARIES := MMA_7455 +DISABLE_NETWORK := 1 diff --git a/samples/Arducam/.cproject b/samples/Arducam/.cproject deleted file mode 100644 index 0d63e8af6b..0000000000 --- a/samples/Arducam/.cproject +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - - all - true - true - true - - - make - - clean - true - true - true - - - - diff --git a/samples/Arducam/.project b/samples/Arducam/.project deleted file mode 100644 index b94ed3eb86..0000000000 --- a/samples/Arducam/.project +++ /dev/null @@ -1,27 +0,0 @@ - - - Arducam - - - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Arducam/component.mk b/samples/Arducam/component.mk index 961e2d7ea9..a1e75ed048 100644 --- a/samples/Arducam/component.mk +++ b/samples/Arducam/component.mk @@ -1,3 +1,4 @@ +COMPONENT_SOC := esp* ARDUINO_LIBRARIES := ArduCAM HWCONFIG = spiffs SPIFF_FILES = web/build diff --git a/samples/Basic_APA102/.cproject b/samples/Basic_APA102/.cproject deleted file mode 100644 index e1450b6031..0000000000 --- a/samples/Basic_APA102/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Basic_APA102/.project b/samples/Basic_APA102/.project deleted file mode 100644 index 97036b7c8e..0000000000 --- a/samples/Basic_APA102/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Basic_APA102 - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Basic_APA102/component.mk b/samples/Basic_APA102/component.mk index 3c540d9c36..6fc9a3b0be 100644 --- a/samples/Basic_APA102/component.mk +++ b/samples/Basic_APA102/component.mk @@ -1 +1,2 @@ +COMPONENT_SOC := esp* ARDUINO_LIBRARIES := APA102 diff --git a/samples/Basic_AWS/.cproject b/samples/Basic_AWS/.cproject deleted file mode 100644 index ed83788380..0000000000 --- a/samples/Basic_AWS/.cproject +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Basic_AWS/.project b/samples/Basic_AWS/.project deleted file mode 100644 index 685876e484..0000000000 --- a/samples/Basic_AWS/.project +++ /dev/null @@ -1,29 +0,0 @@ - - - Basic_AWS - - - SmingFramework - Sming - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Basic_AWS/component.mk b/samples/Basic_AWS/component.mk index 6e25c28d7d..75d34a5e87 100644 --- a/samples/Basic_AWS/component.mk +++ b/samples/Basic_AWS/component.mk @@ -1,3 +1,4 @@ +COMPONENT_SOC := esp* host ENABLE_SSL := 1 MQTT_NO_COMPAT := 1 ENABLE_CUSTOM_HEAP := 1 diff --git a/samples/Basic_Audio/.cproject b/samples/Basic_Audio/.cproject deleted file mode 100644 index ed83788380..0000000000 --- a/samples/Basic_Audio/.cproject +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Basic_Audio/.project b/samples/Basic_Audio/.project deleted file mode 100644 index 74bb7b7dd0..0000000000 --- a/samples/Basic_Audio/.project +++ /dev/null @@ -1,29 +0,0 @@ - - - Basic_Audio - - - SmingFramework - Sming - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Basic_Audio/component.mk b/samples/Basic_Audio/component.mk index 3da06ba826..52b6db3eb0 100644 --- a/samples/Basic_Audio/component.mk +++ b/samples/Basic_Audio/component.mk @@ -1,3 +1,5 @@ +COMPONENT_SOC := esp8266 + # Required if compiling with ENABLE_GDB=1, you must connect debug terminal to alternative serial pins GDB_UART_SWAP=1 diff --git a/samples/Basic_Blink/.cproject b/samples/Basic_Blink/.cproject deleted file mode 100644 index 67c056d24e..0000000000 --- a/samples/Basic_Blink/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Basic_Blink/.project b/samples/Basic_Blink/.project deleted file mode 100644 index 045ddeccff..0000000000 --- a/samples/Basic_Blink/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Basic_Blink - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Basic_Blink/app/application.cpp b/samples/Basic_Blink/app/application.cpp index 14d1fdf458..65422d0701 100644 --- a/samples/Basic_Blink/app/application.cpp +++ b/samples/Basic_Blink/app/application.cpp @@ -1,6 +1,10 @@ #include +#ifdef ARCH_RP2040 +#define LED_PIN PICO_DEFAULT_LED_PIN +#else #define LED_PIN 2 // GPIO2 +#endif Timer procTimer; bool state = true; diff --git a/samples/Basic_Blink/component.mk b/samples/Basic_Blink/component.mk index fcff50daf3..5390d3f653 100644 --- a/samples/Basic_Blink/component.mk +++ b/samples/Basic_Blink/component.mk @@ -2,6 +2,12 @@ ## Parameters configured here will override default and ENV values ## Uncomment and change examples: +## If appropriate, declare which SOCs your project supports +# COMPONENT_SOC := + +## If project doesn't require networking, saves RAM and build time +DISABLE_NETWORK := 1 + ## Add your source directories here separated by space # COMPONENT_SRCDIRS := app # COMPONENT_SRCFILES := diff --git a/samples/Basic_Capsense/.cproject b/samples/Basic_Capsense/.cproject deleted file mode 100644 index 67c056d24e..0000000000 --- a/samples/Basic_Capsense/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Basic_Capsense/.project b/samples/Basic_Capsense/.project deleted file mode 100644 index 30cf310a93..0000000000 --- a/samples/Basic_Capsense/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Basic_Capsense - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Basic_DateTime/.cproject b/samples/Basic_DateTime/.cproject deleted file mode 100644 index ed202cb727..0000000000 --- a/samples/Basic_DateTime/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Basic_DateTime/.project b/samples/Basic_DateTime/.project deleted file mode 100644 index c3d5ab9a58..0000000000 --- a/samples/Basic_DateTime/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Basic_DateTime - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Basic_DateTime/app/application.cpp b/samples/Basic_DateTime/app/application.cpp index 3378cc7ab2..5888a6760d 100644 --- a/samples/Basic_DateTime/app/application.cpp +++ b/samples/Basic_DateTime/app/application.cpp @@ -79,7 +79,7 @@ void onRx(Stream& source, char arrivedChar, unsigned short availableCharsCount) case '\n': Serial.println(); Serial.println(); - Serial.print(_F("****Showing DateTime formating options for Unix timestamp: ")); + Serial.print(_F("****Showing DateTime formatting options for Unix timestamp: ")); Serial.println(timestamp); showTime(timestamp); Serial.print(commandPrompt); diff --git a/samples/Basic_DateTime/component.mk b/samples/Basic_DateTime/component.mk index 3596ab71d1..250bb9a77d 100644 --- a/samples/Basic_DateTime/component.mk +++ b/samples/Basic_DateTime/component.mk @@ -1,2 +1,3 @@ # Emulate UART 0 ENABLE_HOST_UARTID := 0 +DISABLE_NETWORK := 1 diff --git a/samples/Basic_Delegates/.cproject b/samples/Basic_Delegates/.cproject deleted file mode 100644 index b762d6dcae..0000000000 --- a/samples/Basic_Delegates/.cproject +++ /dev/null @@ -1,152 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Basic_Delegates/.project b/samples/Basic_Delegates/.project deleted file mode 100644 index 8aff0fa764..0000000000 --- a/samples/Basic_Delegates/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Basic_Delegates - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Basic_Delegates/app/speed.cpp b/samples/Basic_Delegates/app/speed.cpp index dfd42cb38c..208f8e9c59 100644 --- a/samples/Basic_Delegates/app/speed.cpp +++ b/samples/Basic_Delegates/app/speed.cpp @@ -23,7 +23,7 @@ static void printTime(const char* name, unsigned ticks) Serial.printf("%s: %u cycles, %s\r\n", name, ticks, timer.ticksToTime(ticks).toString().c_str()); } -static void __attribute__((noinline)) evaluateCallback(const char* name, TestCallback callback, int testParam) +static void __noinline evaluateCallback(const char* name, TestCallback callback, int testParam) { timer.start(); for(unsigned i = 0; i < ITERATIONS; ++i) { @@ -33,7 +33,7 @@ static void __attribute__((noinline)) evaluateCallback(const char* name, TestCal printTime(name, ticks / ITERATIONS); } -static void __attribute__((noinline)) evaluateDelegate(const char* name, TestDelegate delegate, int testParam) +static void __noinline evaluateDelegate(const char* name, TestDelegate delegate, int testParam) { timer.start(); for(unsigned i = 0; i < ITERATIONS; ++i) { diff --git a/samples/Basic_Delegates/component.mk b/samples/Basic_Delegates/component.mk index 7e4d03795a..730fe2541e 100644 --- a/samples/Basic_Delegates/component.mk +++ b/samples/Basic_Delegates/component.mk @@ -1 +1,2 @@ DEBUG_VERBOSE_LEVEL = 3 +DISABLE_NETWORK := 1 diff --git a/samples/Basic_Ethernet/app/application.cpp b/samples/Basic_Ethernet/app/application.cpp index 6abde8a8b6..944e5bdd00 100644 --- a/samples/Basic_Ethernet/app/application.cpp +++ b/samples/Basic_Ethernet/app/application.cpp @@ -2,8 +2,6 @@ // #define USE_EMBEDDED ARCH_ESP32 -#ifdef ARCH_ESP32 - #if USE_EMBEDDED // The Embedded MAC @@ -76,11 +74,3 @@ void init() // Set a static IP // ethernet.setIP(IpAddress("192.168.1.12"), IpAddress("255.255.255.0"), IpAddress("192.168.1.254")); } - -#else // ARCH_ESP32 - -void init() -{ -} - -#endif diff --git a/samples/Basic_Ethernet/component.mk b/samples/Basic_Ethernet/component.mk index 664701618a..5a18bbc960 100644 --- a/samples/Basic_Ethernet/component.mk +++ b/samples/Basic_Ethernet/component.mk @@ -1,2 +1,3 @@ +COMPONENT_SOC := esp32* DISABLE_WIFI := 1 COMPONENT_DEPENDS := HardwareSPI diff --git a/samples/Basic_HwPWM/.cproject b/samples/Basic_HwPWM/.cproject deleted file mode 100644 index 8186e42ff8..0000000000 --- a/samples/Basic_HwPWM/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Basic_HwPWM/.project b/samples/Basic_HwPWM/.project deleted file mode 100644 index 7ba2554d28..0000000000 --- a/samples/Basic_HwPWM/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Basic_HwPWM - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Basic_HwPWM/app/application.cpp b/samples/Basic_HwPWM/app/application.cpp index f239713890..e04e7d050a 100644 --- a/samples/Basic_HwPWM/app/application.cpp +++ b/samples/Basic_HwPWM/app/application.cpp @@ -9,7 +9,7 @@ * Calculate the Duty as per the formulae give in ESP8266 SDK * Duty = (Period *1000)/45 * - * PWM can be generated on upto 8 pins (ie All pins except pin 16) + * PWM can be generated on up to 8 pins (ie All pins except pin 16) * Created on August 17, 2015, 2:27 PM * * See also ESP8266 Technical Reference, Chapter 12: diff --git a/samples/Basic_HwPWM/component.mk b/samples/Basic_HwPWM/component.mk index 81bf5015ae..ec78f78162 100644 --- a/samples/Basic_HwPWM/component.mk +++ b/samples/Basic_HwPWM/component.mk @@ -1,2 +1,5 @@ +COMPONENT_SOC := esp8266 + # Uncomment the line below if you want to use Espressif's PWM library. #ENABLE_CUSTOM_PWM=0 + diff --git a/samples/Basic_IFS/.cproject b/samples/Basic_IFS/.cproject deleted file mode 100644 index a217ffc882..0000000000 --- a/samples/Basic_IFS/.cproject +++ /dev/null @@ -1,154 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Basic_IFS/.project b/samples/Basic_IFS/.project deleted file mode 100644 index 56fba6c6ed..0000000000 --- a/samples/Basic_IFS/.project +++ /dev/null @@ -1,29 +0,0 @@ - - - Basic_IFS - - - SmingFramework - Sming - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Basic_IFS/Kconfig b/samples/Basic_IFS/Kconfig new file mode 100644 index 0000000000..9cf1c781ba --- /dev/null +++ b/samples/Basic_IFS/Kconfig @@ -0,0 +1,9 @@ +menu "Basic IFS sample" + config ENABLE_FLASHSTRING_IMAGE + bool "Store filesystem image in a FlashString object instead of partition" + + config HWCONFIG + string "Project hardware configuration" + default "basic_ifs_$(SMING_ARCH)" if ENABLE_FLASHSTRING_IMAGE + default "spiffs" if !ENABLE_FLASHSTRING_IMAGE +endmenu diff --git a/samples/Basic_IFS/README.rst b/samples/Basic_IFS/README.rst index ec0ddd2b0d..d607593f02 100644 --- a/samples/Basic_IFS/README.rst +++ b/samples/Basic_IFS/README.rst @@ -19,9 +19,9 @@ Use the format ``archive`` to retrieve an archive/backup of the directory tree a Building -------- -By default, data is stored in a read-only FWFS (Firmware Filesytem) partition. +By default, data is stored in a read-only FWFS (Firmware Filesystem) partition. -This sample also demonstrates how to store the data in a :cpp:class:`FlashString` object:: +This sample also demonstrates how to store the data in a :cpp:type:`FlashString` object:: make config-clean make ENABLE_FLASHSTRING_IMAGE=1 diff --git a/samples/Basic_IFS/component.mk b/samples/Basic_IFS/component.mk index feec6c667e..ffe779282a 100644 --- a/samples/Basic_IFS/component.mk +++ b/samples/Basic_IFS/component.mk @@ -1,3 +1,4 @@ +COMPONENT_SOC := esp* host COMPONENT_DEPENDS := LittleFS # Empty SPIFFS partition please diff --git a/samples/Basic_IFS/resource/listing.html b/samples/Basic_IFS/resource/listing.html index dba33cb68f..271c1a7a8f 100644 --- a/samples/Basic_IFS/resource/listing.html +++ b/samples/Basic_IFS/resource/listing.html @@ -11,6 +11,9 @@ Index of '{path}' +

    Basic IFS demo

    diff --git a/samples/Basic_IFS/resource/listing.json b/samples/Basic_IFS/resource/listing.json index 262a56e2b8..be790e8afb 100644 --- a/samples/Basic_IFS/resource/listing.json +++ b/samples/Basic_IFS/resource/listing.json @@ -1,26 +1,25 @@ {SECTION} { - {{!ifdef:parent}}"parent":"{{parent}}", - {{!endif}}"files": [ +{!ifdef:parent}"parent":"{parent}", +{!endif}"files":[ {/SECTION} -{SECTION}{{!ifgt:$record:0}}, -{{!endif}} { - "record": {{!as_int:$record}}, - "id": "{{file_id}}", - "name": "{{name}}", - "modified": "{{modified}}", - "size": {{!as_int:size}}, - "original_size": {{!as_int:original_size}}, - "attr": "{{attr}}", - "access": "{{access}}", - "compression": "{{compression}}" - }{/SECTION} +{SECTION}{!ifgt:$record:0}, +{!endif}{"record": {!as_int:$record}, +"id":"{file_id}", +"name":"{name}", +"modified":"{modified}", +"size":{!as_int:size}, +"original_size":{!as_int:original_size}, +"attr":"{attr}", +"access":"{access}", +"compression":"{compression}" +}{/SECTION} {SECTION} - ], - "count": {{!as_int:{!count:1}}}, - "total_size": {{!as_int:total_size}}, - "last_error": "{{last_error}}" +], +"count":{!as_int:{!count:1}}, +"total_size":{!as_int:total_size}, +"last_error":"{last_error}" } {/SECTION} diff --git a/samples/Basic_Interrupts/.cproject b/samples/Basic_Interrupts/.cproject deleted file mode 100644 index 02b7829f92..0000000000 --- a/samples/Basic_Interrupts/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Basic_Interrupts/.project b/samples/Basic_Interrupts/.project deleted file mode 100644 index fa385b5790..0000000000 --- a/samples/Basic_Interrupts/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Basic_Interrupts - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Basic_Interrupts/component.mk b/samples/Basic_Interrupts/component.mk new file mode 100644 index 0000000000..5c4d4e7499 --- /dev/null +++ b/samples/Basic_Interrupts/component.mk @@ -0,0 +1 @@ +DISABLE_NETWORK := 1 diff --git a/samples/Basic_NFC/.cproject b/samples/Basic_NFC/.cproject deleted file mode 100644 index e1450b6031..0000000000 --- a/samples/Basic_NFC/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Basic_NFC/.project b/samples/Basic_NFC/.project deleted file mode 100644 index a46c7140f6..0000000000 --- a/samples/Basic_NFC/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Basic_NFC - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Basic_NFC/component.mk b/samples/Basic_NFC/component.mk index 61d0cfc5e2..d428c401d4 100644 --- a/samples/Basic_NFC/component.mk +++ b/samples/Basic_NFC/component.mk @@ -1 +1,3 @@ +COMPONENT_SOC := esp* ARDUINO_LIBRARIES := MFRC522 +DISABLE_NETWORK := 1 diff --git a/samples/Basic_Neopixel/.cproject b/samples/Basic_Neopixel/.cproject deleted file mode 100644 index 67c056d24e..0000000000 --- a/samples/Basic_Neopixel/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Basic_Neopixel/.project b/samples/Basic_Neopixel/.project deleted file mode 100644 index 56ad4dcf81..0000000000 --- a/samples/Basic_Neopixel/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Basic_Neopixel - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Basic_Ota/.cproject b/samples/Basic_Ota/.cproject deleted file mode 100644 index e1450b6031..0000000000 --- a/samples/Basic_Ota/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Basic_Ota/.project b/samples/Basic_Ota/.project deleted file mode 100644 index 2d511edc6e..0000000000 --- a/samples/Basic_Ota/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Basic_Ota - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Basic_Ota/README.rst b/samples/Basic_Ota/README.rst index c099370144..5cdec1dd46 100644 --- a/samples/Basic_Ota/README.rst +++ b/samples/Basic_Ota/README.rst @@ -6,7 +6,7 @@ Basic Ota Introduction ------------ -This sample integrates :component:`Ota`, :component:`OtaNetwork` and Sming. +This sample integrates :library:`Ota`, :library:`OtaNetwork` and Sming. It demonstrates dual rom booting, big flash support, OTA updates and dual spiffs filesystems. This sample should work on all supported architectures. @@ -56,22 +56,15 @@ the same offset inside their 1MB blocks, only a single rom is created. See :component:`rboot` for further details. - If using a very small flash (e.g. 512k) there may be no room for a - spiffs fileystem, so use *HWCONFIG = standard* + spiffs filesystem, so use *HWCONFIG = standard* - After building copy all the rom*.bin files to the root of your web server. If you want more than two roms you must be an advanced user and should -be able to work out what to copy and edit to acheive this! +be able to work out what to copy and edit to achieve this! Configuration ------------- -.. envvar:: RBOOT_TWO_ROMS - - Default: 1 (enabled) - - Allows specifying two different URLs for ROM0 and ROM1. - - If not set then only the URL defined in ROM_0_URL will be used. .. envvar:: ROM_0_URL diff --git a/samples/Basic_Ota/app/application.cpp b/samples/Basic_Ota/app/application.cpp deleted file mode 100644 index dbeabcaf06..0000000000 --- a/samples/Basic_Ota/app/application.cpp +++ /dev/null @@ -1,210 +0,0 @@ -#include -#include -#include -#include -#include - -// If you want, you can define WiFi settings globally in Eclipse Environment Variables -#ifndef WIFI_SSID -#define WIFI_SSID "PleaseEnterSSID" // Put your SSID and password here -#define WIFI_PWD "PleaseEnterPass" -#endif - -Ota::Network::HttpUpgrader* otaUpdater; -Storage::Partition spiffsPartition; -OtaUpgrader ota; - -Storage::Partition findSpiffsPartition(Storage::Partition partition) -{ - String name = F("spiffs"); - name += ota.getSlot(partition); - auto part = Storage::findPartition(name); - if(!part) { - debug_w("Partition '%s' not found", name.c_str()); - } - return part; -} - -void upgradeCallback(Ota::Network::HttpUpgrader& client, bool result) -{ - Serial.println("In callback..."); - if(result == true) { - // success - ota.end(); - - auto part = ota.getNextBootPartition(); - // set to boot new rom and then reboot - Serial.printf("Firmware updated, rebooting to %s @ ...\r\n", part.name().c_str()); - ota.setBootPartition(part); - System.restart(); - } else { - ota.abort(); - // fail - Serial.println("Firmware update failed!"); - } -} - -void doUpgrade() -{ - Serial.println("Updating..."); - - // need a clean object, otherwise if run before and failed will not run again - if(otaUpdater) { - delete otaUpdater; - } - otaUpdater = new Ota::Network::HttpUpgrader(); - - // select rom slot to flash - auto part = ota.getNextBootPartition(); - -#ifndef RBOOT_TWO_ROMS - // flash rom to position indicated in the rBoot config rom table - otaUpdater->addItem(ROM_0_URL, part); -#else - // flash appropriate ROM - otaUpdater->addItem((ota.getSlot(part) == 0) ? ROM_0_URL : ROM_1_URL, part); -#endif - - ota.begin(part); - - auto spiffsPart = findSpiffsPartition(part); - if(spiffsPart) { - // use user supplied values (defaults for 4mb flash in hardware config) - otaUpdater->addItem(SPIFFS_URL, spiffsPart, new Storage::PartitionStream(spiffsPart)); - } - - // request switch and reboot on success - //otaUpdater->switchToRom(slot); - // and/or set a callback (called on failure or success without switching requested) - otaUpdater->setCallback(upgradeCallback); - - // start update - otaUpdater->start(); -} - -void doSwitch() -{ - auto before = ota.getRunningPartition(); - auto after = ota.getNextBootPartition(); - - Serial.printf(_F("Swapping from %s @ 0x%08x to %s @ 0x%08x.\r\n"), before.name().c_str(), before.address(), - after.name().c_str(), after.address()); - if(ota.setBootPartition(after)) { - Serial.println(F("Restarting...\r\n")); - System.restart(); - } else { - Serial.println(F("Switch failed.")); - } -} - -void showInfo() -{ - Serial.printf("\r\nSDK: v%s\r\n", system_get_sdk_version()); - Serial.printf("Free Heap: %d\r\n", system_get_free_heap_size()); - Serial.printf("CPU Frequency: %d MHz\r\n", system_get_cpu_freq()); - Serial.printf("System Chip ID: %x\r\n", system_get_chip_id()); - Serial.printf("SPI Flash ID: %x\r\n", Storage::spiFlash->getId()); - Serial.printf("SPI Flash Size: %x\r\n", Storage::spiFlash->getSize()); - - auto before = ota.getRunningPartition(); - auto after = ota.getNextBootPartition(); - - Serial.printf(_F("Current %s @ 0x%08x, future %s @ 0x%08x\r\n"), before.name().c_str(), before.address(), - after.name().c_str(), after.address()); -} - -void serialCallBack(Stream& stream, char arrivedChar, unsigned short availableCharsCount) -{ - int pos = stream.indexOf('\n'); - if(pos > -1) { - char str[pos + 1]; - for(int i = 0; i < pos + 1; i++) { - str[i] = stream.read(); - if(str[i] == '\r' || str[i] == '\n') { - str[i] = '\0'; - } - } - - if(!strcmp(str, "connect")) { - // connect to wifi - WifiStation.config(WIFI_SSID, WIFI_PWD); - WifiStation.enable(true); - WifiStation.connect(); - } else if(!strcmp(str, "ip")) { - Serial.print("ip: "); - Serial.print(WifiStation.getIP()); - Serial.print(" mac: "); - Serial.println(WifiStation.getMacAddress()); - } else if(!strcmp(str, "ota")) { - doUpgrade(); - } else if(!strcmp(str, "switch")) { - doSwitch(); - } else if(!strcmp(str, "restart")) { - System.restart(); - } else if(!strcmp(str, "ls")) { - Directory dir; - if(dir.open()) { - while(dir.next()) { - Serial.print(" "); - Serial.println(dir.stat().name); - } - } - Serial.printf("filecount %d\r\n", dir.count()); - } else if(!strcmp(str, "cat")) { - Directory dir; - if(dir.open() && dir.next()) { - auto filename = dir.stat().name.c_str(); - Serial.printf("dumping file %s:\r\n", filename); - // We don't know how big the is, so streaming it is safest - FileStream fs; - fs.open(filename); - Serial.copyFrom(&fs); - Serial.println(); - } else { - Serial.println("Empty spiffs!"); - } - } else if(!strcmp(str, "info")) { - showInfo(); - } else if(!strcmp(str, "help")) { - Serial.println(); - Serial.println("available commands:"); - Serial.println(" help - display this message"); - Serial.println(" ip - show current ip address"); - Serial.println(" connect - connect to wifi"); - Serial.println(" restart - restart the device"); - Serial.println(" switch - switch to the other rom and reboot"); - Serial.println(" ota - perform ota update, switch rom and reboot"); - Serial.println(" info - show device info"); - if(spiffsPartition) { - Serial.println(" ls - list files in spiffs"); - Serial.println(" cat - show first file in spiffs"); - } - Serial.println(); - } else { - Serial.println("unknown command"); - } - } -} - -void init() -{ - Serial.begin(SERIAL_BAUD_RATE); // 115200 by default - Serial.systemDebugOutput(true); // Debug output to serial - - // mount spiffs - auto partition = ota.getRunningPartition(); - spiffsPartition = findSpiffsPartition(partition); - if(spiffsPartition) { - debugf("trying to mount %s @ 0x%08x, length %d", spiffsPartition.name().c_str(), spiffsPartition.address(), - spiffsPartition.size()); - spiffs_mount(spiffsPartition); - } - - WifiAccessPoint.enable(false); - - Serial.printf("\r\nCurrently running %s @ 0x%08x.\r\n", partition.name().c_str(), partition.address()); - Serial.println("Type 'help' and press enter for instructions."); - Serial.println(); - - Serial.onDataReceived(serialCallBack); -} diff --git a/samples/Basic_Ota/component.mk b/samples/Basic_Ota/component.mk index e3cab59ca4..b46c243c8c 100644 --- a/samples/Basic_Ota/component.mk +++ b/samples/Basic_Ota/component.mk @@ -1,3 +1,4 @@ +COMPONENT_SOC := esp* COMPONENT_DEPENDS := OtaNetwork HWCONFIG := ota diff --git a/samples/Basic_ProgMem/.cproject b/samples/Basic_ProgMem/.cproject deleted file mode 100644 index 5d682c9c93..0000000000 --- a/samples/Basic_ProgMem/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Basic_ProgMem/.project b/samples/Basic_ProgMem/.project deleted file mode 100644 index 43e7079280..0000000000 --- a/samples/Basic_ProgMem/.project +++ /dev/null @@ -1,27 +0,0 @@ - - - Basic_ProgMem - - - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - \ No newline at end of file diff --git a/samples/Basic_ProgMem/app/TestProgmem.cpp b/samples/Basic_ProgMem/app/TestProgmem.cpp index bfe023e568..90999f58eb 100644 --- a/samples/Basic_ProgMem/app/TestProgmem.cpp +++ b/samples/Basic_ProgMem/app/TestProgmem.cpp @@ -10,6 +10,11 @@ #include #include #include +#include + +#ifndef __INT32 +#define __INT32 +#endif // Note: contains nulls which won't display, but will be stored #define DEMO_TEST_TEXT "This is a flash string -\0Second -\0Third -\0Fourth." @@ -147,8 +152,8 @@ void testFSTR(Print& out) // Table entries may be accessed directly as they are word-aligned out.println(_F("FSTR tables -")); out.printf(_F(" fstr1 = '%s'\n"), String(table[0]).c_str()); - out.printf(_F(" fstr1.length() = %u\n"), table[0].length()); - out.printf(_F(" entries = %u\n"), table.length()); + out.printf(_F(" fstr1.length() = %" PRIu32 "\n"), table[0].length()); + out.printf(_F(" entries = %" PRIu32 "\n"), table.length()); out.println("< testFSTR() end\n"); } @@ -170,11 +175,11 @@ void testSpeed(Print& out) for(unsigned i = 0; i < iterations; ++i) tmp += sumBuffer(demoText, sizeof(demoText)); baseline = timer.elapsedTime(); - out.printf("Elapsed: %u\n", baseline); + out.printf("Elapsed: %" PRIu32 "\n", baseline); #define END() \ elapsed = timer.elapsedTime(); \ - out.printf("Elapsed: %u (baseline + %u)\n", elapsed, elapsed - baseline); + out.printf("Elapsed: %" PRIu32 " (baseline + %" PRIu32 ")\n", elapsed, elapsed - baseline); _FPUTS("Load PSTR into stack buffer..."); timer.start(); diff --git a/samples/Basic_ProgMem/component.mk b/samples/Basic_ProgMem/component.mk new file mode 100644 index 0000000000..5c4d4e7499 --- /dev/null +++ b/samples/Basic_ProgMem/component.mk @@ -0,0 +1 @@ +DISABLE_NETWORK := 1 diff --git a/samples/Basic_ScannerI2C/.cproject b/samples/Basic_ScannerI2C/.cproject deleted file mode 100644 index 882cf4bfc8..0000000000 --- a/samples/Basic_ScannerI2C/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Basic_ScannerI2C/.project b/samples/Basic_ScannerI2C/.project deleted file mode 100644 index e325d694b8..0000000000 --- a/samples/Basic_ScannerI2C/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Basic_ScannerI2C - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Basic_ScannerI2C/app/application.cpp b/samples/Basic_ScannerI2C/app/application.cpp index dccd5416bc..afda8fc274 100644 --- a/samples/Basic_ScannerI2C/app/application.cpp +++ b/samples/Basic_ScannerI2C/app/application.cpp @@ -57,7 +57,7 @@ void scanBus() nDevices++; } else if(error == 4) { - Serial.print("Unknow error at address 0x"); + Serial.print("Unknown error at address 0x"); if(address < 16) Serial.print("0"); Serial.println(address, HEX); diff --git a/samples/Basic_ScannerI2C/component.mk b/samples/Basic_ScannerI2C/component.mk new file mode 100644 index 0000000000..5c4d4e7499 --- /dev/null +++ b/samples/Basic_ScannerI2C/component.mk @@ -0,0 +1 @@ +DISABLE_NETWORK := 1 diff --git a/samples/Basic_Serial/.cproject b/samples/Basic_Serial/.cproject deleted file mode 100644 index e1450b6031..0000000000 --- a/samples/Basic_Serial/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Basic_Serial/.project b/samples/Basic_Serial/.project deleted file mode 100644 index 57245ee613..0000000000 --- a/samples/Basic_Serial/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Basic_Serial - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Basic_Serial/component.mk b/samples/Basic_Serial/component.mk index 96def499d3..da266c7dea 100644 --- a/samples/Basic_Serial/component.mk +++ b/samples/Basic_Serial/component.mk @@ -1,4 +1,5 @@ -HWCONFIG := spiffs +DISABLE_NETWORK := 1 +HWCONFIG := spiffs-2m CUSTOM_TARGETS += files/README.md diff --git a/samples/Basic_Servo/.cproject b/samples/Basic_Servo/.cproject deleted file mode 100644 index 278d9edf4e..0000000000 --- a/samples/Basic_Servo/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Basic_Servo/.project b/samples/Basic_Servo/.project deleted file mode 100644 index 6771dc18c2..0000000000 --- a/samples/Basic_Servo/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Basic_Servo - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Basic_Servo/component.mk b/samples/Basic_Servo/component.mk index b3fea3a944..25e6a42c56 100644 --- a/samples/Basic_Servo/component.mk +++ b/samples/Basic_Servo/component.mk @@ -1 +1,2 @@ ARDUINO_LIBRARIES := Servo +DISABLE_NETWORK := 1 diff --git a/samples/Basic_SmartConfig/.cproject b/samples/Basic_SmartConfig/.cproject deleted file mode 100644 index 76d7689a24..0000000000 --- a/samples/Basic_SmartConfig/.cproject +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Basic_SmartConfig/.project b/samples/Basic_SmartConfig/.project deleted file mode 100644 index dcb29d479e..0000000000 --- a/samples/Basic_SmartConfig/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Basic_SmartConfig - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Basic_SmartConfig/component.mk b/samples/Basic_SmartConfig/component.mk index c24c9ac9d9..7d1cc32f5b 100644 --- a/samples/Basic_SmartConfig/component.mk +++ b/samples/Basic_SmartConfig/component.mk @@ -1 +1,2 @@ +COMPONENT_SOC := esp8266 ENABLE_SMART_CONFIG = 1 diff --git a/samples/Basic_Ssl/.cproject b/samples/Basic_Ssl/.cproject deleted file mode 100644 index e1450b6031..0000000000 --- a/samples/Basic_Ssl/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Basic_Ssl/.project b/samples/Basic_Ssl/.project deleted file mode 100644 index 301a14428b..0000000000 --- a/samples/Basic_Ssl/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Basic_Ssl - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Basic_Ssl/component.mk b/samples/Basic_Ssl/component.mk index b994d8280f..f37a7e4a1a 100644 --- a/samples/Basic_Ssl/component.mk +++ b/samples/Basic_Ssl/component.mk @@ -1,3 +1,5 @@ +COMPONENT_SOC := esp* host + # ifeq ($(ENABLE_MALLOC_COUNT),1) COMPONENT_DEPENDS += malloc_count diff --git a/samples/Basic_Storage/.cproject b/samples/Basic_Storage/.cproject deleted file mode 100644 index 1c32c9a8a2..0000000000 --- a/samples/Basic_Storage/.cproject +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Basic_Storage/.project b/samples/Basic_Storage/.project deleted file mode 100644 index 96b9a5cf41..0000000000 --- a/samples/Basic_Storage/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Basic_Storage - - - Sming - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Basic_Storage/basic_storage-2m.hw b/samples/Basic_Storage/basic_storage-2m.hw new file mode 100644 index 0000000000..844e2357fd --- /dev/null +++ b/samples/Basic_Storage/basic_storage-2m.hw @@ -0,0 +1,29 @@ +{ + "name": "Basic Storage sample (2M)", + "base_config": "basic_storage", + "options": [ + "2m" + ], + "partitions": { + "rom0": { + "size": "512k" + }, + "user0": { + "address": "0x000fa000" + }, + "user1": { + "address": "0x000fe000" + }, + "spiffs0": { + "address": "0x00102000" + }, + "spiffs1": { + "address": "0x00182000", + "size": "240K" + }, + "spiffs2": { + "address": "0x001be000", + "size": "216K" + } + } +} \ No newline at end of file diff --git a/samples/Basic_Storage/component.mk b/samples/Basic_Storage/component.mk index cfe43013d0..60dcb2fe6e 100644 --- a/samples/Basic_Storage/component.mk +++ b/samples/Basic_Storage/component.mk @@ -1,5 +1,11 @@ +DISABLE_NETWORK := 1 + # Use our custom hardware configuration +ifeq ($(SMING_ARCH),Esp32) HWCONFIG := basic_storage +else +HWCONFIG := basic_storage-2m +endif HOST_NETWORK_OPTIONS := --nonet diff --git a/samples/Basic_Tasks/.cproject b/samples/Basic_Tasks/.cproject deleted file mode 100644 index ed83788380..0000000000 --- a/samples/Basic_Tasks/.cproject +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Basic_Tasks/.project b/samples/Basic_Tasks/.project deleted file mode 100644 index 115a7af435..0000000000 --- a/samples/Basic_Tasks/.project +++ /dev/null @@ -1,30 +0,0 @@ - - - Basic_Tasks - - - SmingFramework - Sming - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - org.eclipse.linuxtools.tmf.project.nature - - diff --git a/samples/Basic_Tasks/component.mk b/samples/Basic_Tasks/component.mk index ba03b6dbd5..a6afd10a26 100644 --- a/samples/Basic_Tasks/component.mk +++ b/samples/Basic_Tasks/component.mk @@ -1,3 +1,4 @@ +COMPONENT_SOC := esp* host ARDUINO_LIBRARIES := ArduinoFFT SignalGenerator ENABLE_TASK_COUNT := 1 diff --git a/samples/Basic_Templates/Makefile b/samples/Basic_Templates/Makefile new file mode 100644 index 0000000000..ff51b6c3a7 --- /dev/null +++ b/samples/Basic_Templates/Makefile @@ -0,0 +1,9 @@ +##################################################################### +#### Please don't change this file. Use component.mk instead #### +##################################################################### + +ifndef SMING_HOME +$(error SMING_HOME is not set: please configure it as an environment variable) +endif + +include $(SMING_HOME)/project.mk diff --git a/samples/Basic_Templates/README.rst b/samples/Basic_Templates/README.rst new file mode 100644 index 0000000000..5fb782fb3a --- /dev/null +++ b/samples/Basic_Templates/README.rst @@ -0,0 +1,14 @@ +Basic Templates +=============== + +Simple demonstration of how to use Template streams. + +The program uses two sets of data: + +- cars.csv from https://corgis-edu.github.io/corgis/csv/cars/ +- classics.csv from https://corgis-edu.github.io/corgis/csv/classics/ + +Templates are used to display filtered data from these in text, JSON and XML formats. + +Although the data is just printed to the serial terminal, it can just as easily be +sent over a network link as in the :sample:`Basic_IFS` sample. diff --git a/samples/Basic_Templates/app/CsvTemplate.h b/samples/Basic_Templates/app/CsvTemplate.h new file mode 100644 index 0000000000..b29b4ae349 --- /dev/null +++ b/samples/Basic_Templates/app/CsvTemplate.h @@ -0,0 +1,39 @@ +#pragma once + +#include +#include + +/** + * @brief SectionTemplate implementation for data stored in CSV file + */ +class CsvTemplate : public SectionTemplate +{ +public: + CsvTemplate(IDataSourceStream* templateSource, IDataSourceStream* csvSource) + : SectionTemplate(templateSource), csv(csvSource) + { + } + + // Return true if we have a new valid record, false if not + bool nextRecord() override + { + // Content section we fetch the next data record, if there is one + if(sectionIndex() == 1) { + return csv.next(); + } + + // This code emits the header and footer sections exactly once + // `recordIndex` starts at -1 (before first record) + return recordIndex() < 0; + } + +protected: + String getValue(const char* name) override + { + String s = SectionTemplate::getValue(name); + return s ?: csv.getValue(name); + } + +private: + CsvReader csv; +}; diff --git a/samples/Basic_Templates/app/application.cpp b/samples/Basic_Templates/app/application.cpp new file mode 100644 index 0000000000..efca95a384 --- /dev/null +++ b/samples/Basic_Templates/app/application.cpp @@ -0,0 +1,110 @@ +#include +#include +#include +#include +#include "CsvTemplate.h" + +namespace +{ +/* + * Templates are small and benefit from faster access as they're read repeatedly, + * so they're stored in program memory. + */ +namespace Resource +{ +IMPORT_FSTR(cars_txt, PROJECT_DIR "/templates/cars.txt") +IMPORT_FSTR(classics_json, PROJECT_DIR "/templates/classics.json") +IMPORT_FSTR(classics_xml, PROJECT_DIR "/templates/classics.xml") +} // namespace Resource + +/* + * CSV files are large and read strictly sequentially so store these in filesystem + */ +namespace Filename +{ +DEFINE_FSTR(cars_csv, "cars.csv") +DEFINE_FSTR(classics_csv, "classics.csv") +} // namespace Filename + +/* + * Demonstrate use of custom Template class using CSV source data. + * Records are filtered by the template. + */ +void printCars() +{ + // Set up our templating class + CsvTemplate tmpl(new FSTR::Stream(Resource::cars_txt), // The template source + new FileStream(Filename::cars_csv) // The CSV data source + ); + + // Set the variable used by the template to filter records + tmpl.setVar("make_filter", "Volkswagen"); + + // Dump result to terminal + Serial.copyFrom(&tmpl); +} + +/* + * Demonstrate using callbacks instead of CsvTemplate class, + * and performing record filtering outside of template. + */ +void printClassics(const FlashString& templateSource, Format::Formatter& formatter) +{ + // The CSV data source + CsvReader csv(new FileStream(Filename::classics_csv)); + + // Use a regular SectionTemplate class to process the template + SectionTemplate tmpl(new FSTR::Stream(templateSource)); + + // We're going to filter the data based on publication year + String year_filter("1996"); + // Provide this to the template so it can show it in the header + tmpl.setVar(_F("year_filter"), year_filter); + // Improve speed by pre-fetching the filter column index + unsigned yearColumn = csv.getColumn(_F("bibliography.publication.year")); + + // Set up callback to handle fetching/filtering records + tmpl.onNextRecord([&]() -> bool { + if(tmpl.sectionIndex() == 1) { + while(csv.next()) { + // Could also use a more generic (but slower) approach: + // if(year_filter == tmpl.getValue("bibliography.publication.year")) + + if(year_filter == csv.getValue(yearColumn)) { + return true; + } + } + return false; + } + return tmpl.recordIndex() < 0; + }); + + // Set up callback to fetch values from CSV record + tmpl.onGetValue([&](const char* name) -> String { + String s = csv.getValue(name); + formatter.escape(s); + return s; + }); + + // Dump result to terminal + Serial.copyFrom(&tmpl); +} + +} // namespace + +void init() +{ +#if DEBUG_BUILD + Serial.begin(COM_SPEED_SERIAL); + + Serial.systemDebugOutput(true); + debug_i("\n\n********************************************************\n" + "Hello\n"); +#endif + + fwfs_mount(); + + printCars(); + printClassics(Resource::classics_json, Format::json); + printClassics(Resource::classics_xml, Format::xml); +} diff --git a/samples/Basic_Templates/basic_templates.hw b/samples/Basic_Templates/basic_templates.hw new file mode 100644 index 0000000000..82d2938aef --- /dev/null +++ b/samples/Basic_Templates/basic_templates.hw @@ -0,0 +1,27 @@ +{ + "name": "Basic Templates sample", + "base_config": "standard", + "options": [ + "2m" + ], + "partitions": { + "fwfs1": { + "address": "0x00100000", + "size": "860K", + "type": "data", + "subtype": "fwfs", + "filename": "out/fwfs1.bin", + "build": { + "target": "fwfs-build", + "config": { + "name": "Basic Templates demo volume", + "source": { + "/": "files" + } + } + }, + "readonly": true, + "encrypted": false + } + } +} \ No newline at end of file diff --git a/samples/Basic_Templates/component.mk b/samples/Basic_Templates/component.mk new file mode 100644 index 0000000000..092ca88129 --- /dev/null +++ b/samples/Basic_Templates/component.mk @@ -0,0 +1,3 @@ +HWCONFIG := basic_templates +DISABLE_NETWORK := 1 + diff --git a/samples/Basic_Templates/files/cars.csv b/samples/Basic_Templates/files/cars.csv new file mode 100644 index 0000000000..85bf4abcc1 --- /dev/null +++ b/samples/Basic_Templates/files/cars.csv @@ -0,0 +1,1002 @@ +"Dimensions.Height","Dimensions.Length","Dimensions.Width","Engine Information.Driveline","Engine Information.Engine Type","Engine Information.Hybrid","Engine Information.Number of Forward Gears","Engine Information.Transmission","Fuel Information.City mpg","Fuel Information.Fuel Type","Fuel Information.Highway mpg","Identification.Classification","Identification.ID","Identification.Make","Identification.Model Year","Identification.Year","Engine Information.Engine Statistics.Horsepower","Engine Information.Engine Statistics.Torque" +"140","143","202","All-wheel drive","Audi 3.2L 6 cylinder 250hp 236ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","25","Automatic transmission","2009 Audi A3 3.2","Audi","2009 Audi A3","2009","250","236" +"140","143","202","Front-wheel drive","Audi 2.0L 4 cylinder 200 hp 207 ft-lbs Turbo","True","6","6 Speed Automatic Select Shift","22","Gasoline","28","Automatic transmission","2009 Audi A3 2.0 T AT","Audi","2009 Audi A3","2009","200","207" +"140","143","202","Front-wheel drive","Audi 2.0L 4 cylinder 200 hp 207 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","30","Manual transmission","2009 Audi A3 2.0 T","Audi","2009 Audi A3","2009","200","207" +"140","143","202","All-wheel drive","Audi 2.0L 4 cylinder 200 hp 207 ft-lbs Turbo","True","6","6 Speed Automatic Select Shift","21","Gasoline","28","Automatic transmission","2009 Audi A3 2.0 T Quattro","Audi","2009 Audi A3","2009","200","207" +"140","143","202","All-wheel drive","Audi 2.0L 4 cylinder 200 hp 207 ft-lbs Turbo","True","6","6 Speed Automatic Select Shift","21","Gasoline","28","Automatic transmission","2009 Audi A3 2.0 T Quattro","Audi","2009 Audi A3","2009","200","207" +"91","17","62","All-wheel drive","Audi 3.2L 6 cylinder 265hp 243 ft-lbs","True","6","6 Speed Manual","16","Gasoline","27","Manual transmission","2009 Audi A5 3.2","Audi","2009 Audi A5","2009","265","243" +"91","17","62","All-wheel drive","Audi 3.2L 6 cylinder 265hp 243 ft-lbs","True","6","6 Speed Automatic Select Shift","17","Gasoline","26","Automatic transmission","2009 Audi A5 3.2 AT","Audi","2009 Audi A5","2009","265","243" +"201","221","191","All-wheel drive","Audi 4.2L 8 cylinder 350 hp 325 ft-lbs","True","6","6 Speed Automatic Select Shift","13","Gasoline","18","Automatic transmission","2009 Audi Q7 4.2","Audi","2009 Audi Q7","2009","350","325" +"201","221","191","All-wheel drive","Audi 3.6L 6 cylinder 280hp 266 ft-lbs","True","6","6 Speed Automatic Select Shift","14","Gasoline","20","Automatic transmission","2009 Audi Q7 3.6","Audi","2009 Audi Q7","2009","280","266" +"147","96","34","All-wheel drive","Audi 2.0L 4 cylinder 211 hp 258 ft-lbs Turbo","True","6","6 Speed Manual","22","Gasoline","30","Manual transmission","2009 Audi A4 Sedan 2.0 T Quattro","Audi","2009 Audi A4 Sedan","2009","211","258" +"147","96","34","All-wheel drive","Audi 2.0L 4 cylinder 211 hp 258 ft-lbs Turbo","True","6","6 Speed Automatic Select Shift","21","Gasoline","27","Automatic transmission","2009 Audi A4 Sedan 2.0 T Quattro AT","Audi","2009 Audi A4 Sedan","2009","211","258" +"147","96","34","All-wheel drive","Audi 3.2L 6 cylinder 265hp 243 ft-lbs","True","6","6 Speed Automatic Select Shift","17","Gasoline","26","Automatic transmission","2009 Audi A4 Sedan 3.2","Audi","2009 Audi A4 Sedan","2009","265","243" +"172","63","87","Front-wheel drive","Acura 3.5L 6 Cylinder 280 hp 254 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","29","Automatic transmission","2012 Acura TL","Acura","2012 Acura TL","2012","280","254" +"172","63","87","All-wheel drive","Acura 3.7L 6 Cylinder 305 hp 273 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","26","Automatic transmission","2012 Acura TL SH-AWD","Acura","2012 Acura TL","2012","305","273" +"226","243","201","All-wheel drive","BMW 4.4L 8 cylinder 555hp 500 ft-lbs Turbo","True","6","6 Speed Automatic Select Shift","12","Gasoline","17","Automatic transmission","2010 BMW X5 M SUV","BMW","2010 BMW X5","2010","555","500" +"226","243","201","All-wheel drive","BMW 4.4L 8 cylinder 555hp 500 ft-lbs Turbo","True","6","6 Speed Automatic Select Shift","12","Gasoline","17","Automatic transmission","2011 BMW X5 M SUV","BMW","2011 BMW X5","2011","555","500" +"148","12","191","All-wheel drive","BMW 4.4L 8 cylinder 555hp 500 ft-lbs Turbo","True","6","6 Speed Automatic Select Shift","12","Gasoline","17","Automatic transmission","2010 BMW X6 M","BMW","2010 BMW X6","2010","555","500" +"148","12","191","All-wheel drive","BMW 4.4L 8 cylinder 555hp 500 ft-lbs Turbo","True","6","6 Speed Automatic Select Shift","12","Gasoline","17","Automatic transmission","2011 BMW X6 M","BMW","2011 BMW X6","2011","555","500" +"112","22","181","Rear-wheel drive","Chevrolet 2.9L 4 Cylinder 185 hp 190 ft-lbs","True","5","5 Speed Manual","18","Gasoline","25","Manual transmission","2012 Chevrolet Colorado Work Truck","Chevrolet","2012 Chevrolet Colorado","2012","185","190" +"112","140","181","Rear-wheel drive","Chevrolet 2.9L 4 Cylinder 185 hp 190 ft-lbs","True","5","5 Speed Manual","18","Gasoline","25","Manual transmission","2012 Chevrolet Colorado Extended Cab Work Truck","Chevrolet","2012 Chevrolet Colorado","2012","185","190" +"120","140","181","Rear-wheel drive","Chevrolet 2.9L 4 Cylinder 185 hp 190 ft-lbs","True","4","4 Speed Automatic","18","Gasoline","25","Automatic transmission","2012 Chevrolet Colorado Crew Cab 1LT","Chevrolet","2012 Chevrolet Colorado","2012","185","190" +"112","22","181","Rear-wheel drive","Chevrolet 2.9L 4 Cylinder 185 hp 190 ft-lbs","True","5","5 Speed Manual","18","Gasoline","25","Manual transmission","2011 Chevrolet Colorado Work Truck","Chevrolet","2011 Chevrolet Colorado","2011","185","190" +"112","140","181","Rear-wheel drive","Chevrolet 2.9L 4 Cylinder 185 hp 190 ft-lbs","True","5","5 Speed Manual","18","Gasoline","25","Manual transmission","2011 Chevrolet Colorado Extended Cab Work Truck","Chevrolet","2011 Chevrolet Colorado","2011","185","190" +"120","140","181","Rear-wheel drive","Chevrolet 2.9L 4 Cylinder 185 hp 190 ft-lbs","True","4","4 Speed Automatic","18","Gasoline","25","Automatic transmission","2011 Chevrolet Colorado Crew Cab 1LT","Chevrolet","2011 Chevrolet Colorado","2011","185","190" +"112","22","181","Rear-wheel drive","Chevrolet 2.9L 4 Cylinder 185 hp 190 ft-lbs","True","5","5 Speed Manual","18","Gasoline","25","Manual transmission","2010 Chevrolet Colorado Work Truck","Chevrolet","2010 Chevrolet Colorado","2010","185","190" +"112","140","181","Rear-wheel drive","Chevrolet 2.9L 4 Cylinder 185 hp 190 ft-lbs","True","5","5 Speed Manual","20","Gasoline","26","Manual transmission","2010 Chevrolet Colorado Extended Cab Work Truck","Chevrolet","2010 Chevrolet Colorado","2010","185","190" +"120","140","181","Rear-wheel drive","Chevrolet 2.9L 4 Cylinder 185 hp 190 ft-lbs","True","4","4 Speed Automatic","18","Gasoline","25","Automatic transmission","2010 Chevrolet Colorado Crew Cab LT1","Chevrolet","2010 Chevrolet Colorado","2010","185","190" +"77","60","219","Rear-wheel drive","Chevrolet 5.3L 8 Cylinder 310 hp 334 ft-lbs FFV","True","4","4 Speed Automatic","13","Gasoline","18","Automatic transmission","2012 Chevrolet Express LS 1500","Chevrolet","2012 Chevrolet Express","2012","310","334" +"77","60","219","All-wheel drive","Chevrolet 5.3L 8 Cylinder 310 hp 334 ft-lbs FFV","True","4","4 Speed Automatic","9","E85","12","Automatic transmission","2012 Chevrolet Express LS 1500 AWD","Chevrolet","2012 Chevrolet Express","2012","310","334" +"77","60","219","Rear-wheel drive","Chevrolet 5.3L 8 Cylinder 310 hp 334 ft-lbs FFV","True","4","4 Speed Automatic","13","Gasoline","17","Automatic transmission","2011 Chevrolet Express LS 1500","Chevrolet","2011 Chevrolet Express","2011","310","334" +"77","60","219","All-wheel drive","Chevrolet 5.3L 8 Cylinder 310 hp 334 ft-lbs FFV","True","4","4 Speed Automatic","13","Gasoline","17","Automatic transmission","2011 Chevrolet Express LS 1500 AWD","Chevrolet","2011 Chevrolet Express","2011","310","334" +"22","60","219","Rear-wheel drive","Chevrolet 4.8L 8 Cylinder 280 hp 295 ft-lbs FFV","True","6","6 Speed Automatic","8","E85","12","Automatic transmission","2011 Chevrolet Express LS 2500","Chevrolet","2011 Chevrolet Express","2011","280","295" +"22","60","219","Rear-wheel drive","Chevrolet 6.0L 8 Cylinder 324 hp 373 ft-lbs FFV","True","6","6 Speed Automatic","8","E85","12","Automatic transmission","2011 Chevrolet Express LS 2500 6.0L","Chevrolet","2011 Chevrolet Express","2011","324","373" +"24","60","224","Rear-wheel drive","Chevrolet 5.3L 8 Cylinder 310 hp 334 ft-lbs FFV","True","4","4 Speed Automatic","10","E85","13","Automatic transmission","2010 Chevrolet Express LS 1500","Chevrolet","2010 Chevrolet Express","2010","310","334" +"24","60","224","All-wheel drive","Chevrolet 5.3L 8 Cylinder 310 hp 334 ft-lbs FFV","True","4","4 Speed Automatic","13","Gasoline","17","Automatic transmission","2010 Chevrolet Express LS 1500 AWD","Chevrolet","2010 Chevrolet Express","2010","310","334" +"77","102","237","Rear-wheel drive","Chevrolet 4.3L 6 Cylinder 195 hp 260 ft-lbs","True","4","4 Speed Automatic","15","Gasoline","20","Automatic transmission","2011 Chevrolet Silverado 1500 Work Truck","Chevrolet","2011 Chevrolet Silverado 1500","2011","195","260" +"82","215","240","Rear-wheel drive","Chevrolet 4.8L 8 Cylinder 302 hp 305 ft-lbs FFV","True","4","4 Speed Automatic","14","Gasoline","19","Automatic transmission","2011 Chevrolet Silverado 1500 Crew Cab Work Truck","Chevrolet","2011 Chevrolet Silverado 1500","2011","302","305" +"85","215","237","Rear-wheel drive","Chevrolet 4.3L 6 Cylinder 195 hp 260 ft-lbs","True","4","4 Speed Automatic","15","Gasoline","20","Automatic transmission","2011 Chevrolet Silverado 1500 Extended Cab Work Truck","Chevrolet","2011 Chevrolet Silverado 1500","2011","195","260" +"85","215","237","Rear-wheel drive","Chevrolet 4.3L 6 Cylinder 195 hp 260 ft-lbs","True","4","4 Speed Automatic","15","Gasoline","20","Automatic transmission","2010 Chevrolet Silverado 1500 Extended Cab Work Truck","Chevrolet","2010 Chevrolet Silverado 1500","2010","195","260" +"77","102","237","Rear-wheel drive","Chevrolet 4.3L 6 Cylinder 195 hp 260 ft-lbs","True","4","4 Speed Automatic","15","Gasoline","20","Automatic transmission","2010 Chevrolet Silverado 1500 Work Truck","Chevrolet","2010 Chevrolet Silverado 1500","2010","195","260" +"82","215","240","Rear-wheel drive","Chevrolet 4.8L 8 Cylinder 302 hp 305 ft-lbs FFV","True","4","4 Speed Automatic","14","Gasoline","19","Automatic transmission","2010 Chevrolet Silverado 1500 Crew Cab Work Truck","Chevrolet","2010 Chevrolet Silverado 1500","2010","302","305" +"43","52","52","Rear-wheel drive","Nissan 3.7L 6 Cylinder 350hp 276 ft-lbs","True","6","6 Speed Manual","18","Gasoline","26","Manual transmission","2011 Nissan 370Z NISMO","Nissan","2011 Nissan 370Z Coupe","2011","350","276" +"35","75","52","Rear-wheel drive","Nissan 3.7L 6 Cylinder 350hp 276 ft-lbs","True","6","6 Speed Manual","18","Gasoline","26","Manual transmission","2010 Nissan 370Z NISMO","Nissan","2010 Nissan 370Z Coupe","2010","350","276" +"35","75","52","Rear-wheel drive","Nissan 3.7L 6 Cylinder 350hp 276 ft-lbs","True","6","6 Speed Manual","18","Gasoline","26","Manual transmission","2009 Nissan 370Z NISMO","Nissan","2009 Nissan 370Z Coupe","2009","350","276" +"167","168","247","Front-wheel drive","Volvo 2.5L 5 Cylinder 227 hp 236 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","29","Manual transmission","2011 Volvo C30 T5","Volvo","2011 Volvo C30","2011","227","236" +"167","168","247","Front-wheel drive","Volvo 2.5L 5 Cylinder 227 hp 236 ft-lbs Turbo","True","5","5 Speed Automatic","21","Gasoline","30","Automatic transmission","2011 Volvo C30 T5 AT","Volvo","2011 Volvo C30","2011","227","236" +"167","155","247","Front-wheel drive","Volvo 2.5L 5 Cylinder 227 hp 236 ft-lbs Turbo","True","5","5 Speed Automatic","21","Gasoline","30","Automatic transmission","2010 Volvo C30 T5 AT","Volvo","2010 Volvo C30","2010","227","236" +"167","155","247","Front-wheel drive","Volvo 2.5L 5 Cylinder 227 hp 236 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","29","Manual transmission","2010 Volvo C30 T5","Volvo","2010 Volvo C30","2010","227","236" +"193","34","107","Rear-wheel drive","Bentley 6.8L 8 cylinder 530hp 774 ft-lbs Turbo","True","6","6 Speed Automatic","9","Gasoline","15","Automatic transmission","2010 Bentley Brooklands","Bentley","2010 Bentley Brooklands","2010","530","774" +"99","195","153","All-wheel drive","Bentley 6.0L 12 Cylinder 621 hp 590 ft-lbs FFV Turbo","True","6","6 Speed Automatic","8","E85","14","Automatic transmission","2012 Bentley Continental Supersports Convertible","Bentley","2012 Bentley Continental Supersports Convertible","2012","621","590" +"110","199","153","All-wheel drive","Bentley 6.0L 12 Cylinder 621 hp 590 ft-lbs FFV Turbo","True","6","6 Speed Automatic Select Shift","8","E85","14","Automatic transmission","2012 Bentley Continental Supersports Coupe","Bentley","2012 Bentley Continental Supersports Coupe","2012","621","590" +"99","195","153","All-wheel drive","Bentley 6.0L 12 Cylinder 621 hp 590 ft-lbs FFV Turbo","True","6","6 Speed Automatic","8","E85","14","Automatic transmission","2011 Bentley Continental Supersports Convertible","Bentley","2011 Bentley Continental Supersports Convertible","2011","621","590" +"99","195","153","All-wheel drive","Bentley 6.0L 12 Cylinder 621 hp 590 ft-lbs FFV Turbo","True","6","6 Speed Automatic","12","Gasoline","19","Automatic transmission","2010 Bentley Continental Supersports","Bentley","2010 Bentley Continental Supersports","2010","621","590" +"118","170","184","All-wheel drive","Bentley 6.0L 12 Cylinder 552 hp 479 ft-lbs FFV Turbo","True","6","6 Speed Automatic","8","E85","13","Automatic transmission","2012 Bentley Continental Flying Spur","Bentley","2012 Bentley Continental Flying Spur","2012","552","479" +"108","170","184","All-wheel drive","Bentley 6.0L 12 Cylinder 600 hp 553 ft-lbs FFV Turbo","True","6","6 Speed Automatic","11","Gasoline","19","Automatic transmission","2012 Bentley Continental Flying Spur Speed","Bentley","2012 Bentley Continental Flying Spur","2012","600","553" +"185","170","184","All-wheel drive","Bentley 6.0L 12 Cylinder 600 hp 553 ft-lbs FFV Turbo","True","6","6 Speed Automatic","10","Gasoline","17","Automatic transmission","2011 Bentley Continental Flying Spur Speed","Bentley","2011 Bentley Continental Flying Spur","2011","600","553" +"185","170","184","All-wheel drive","Bentley 6.0L 12 cylinder 600hp 553 ft-lbs Turbo","True","6","6 Speed Automatic","10","Gasoline","17","Automatic transmission","2010 Bentley Continental Flying Spur Speed","Bentley","2010 Bentley Continental Flying Spur","2010","600","553" +"195","170","184","All-wheel drive","Bentley 6.0L 12 cylinder 552 hp 479 ft-lbs Turbo","True","6","6 Speed Automatic","10","Gasoline","17","Automatic transmission","2010 Bentley Continental Flying Spur","Bentley","2010 Bentley Continental Flying Spur","2010","552","479" +"120","7","44","Front-wheel drive","Volvo 2.5L 5 Cylinder 227 hp 236 ft-lbs Turbo","True","5","5 Speed Automatic","19","Gasoline","28","Automatic transmission","2011 Volvo C70 T5","Volvo","2011 Volvo C70","2011","227","236" +"119","230","44","Front-wheel drive","Volvo 2.5L 5 Cylinder 227 hp 236 ft-lbs Turbo","True","6","6 Speed Manual","20","Gasoline","28","Manual transmission","2010 Volvo C70 T5","Volvo","2010 Volvo C70","2010","227","236" +"119","230","44","Front-wheel drive","Volvo 2.5L 5 Cylinder 227 hp 236 ft-lbs Turbo","True","5","5 Speed Automatic","19","Gasoline","28","Automatic transmission","2010 Volvo C70 T5 AT","Volvo","2010 Volvo C70","2010","227","236" +"172","123","234","Front-wheel drive","Volvo 2.4L 5 Cylinder 168 hp 166 ft-lbs","True","5","5 Speed Manual","21","Gasoline","29","Manual transmission","2010 Volvo S40 2.4i","Volvo","2010 Volvo S40","2010","168","170" +"172","123","234","Front-wheel drive","Volvo 2.5L 5 Cylinder 227 hp 236 ft-lbs Turbo","True","5","5 Speed Automatic","21","Gasoline","30","Automatic transmission","2010 Volvo S40 R-Design","Volvo","2010 Volvo S40","2010","227","236" +"172","123","234","Front-wheel drive","Volvo 2.5L 5 Cylinder 227 hp 236 ft-lbs Turbo","True","5","5 Speed Automatic","21","Gasoline","30","Automatic transmission","2011 Volvo S40 T5","Volvo","2011 Volvo S40","2011","227","236" +"190","123","234","All-wheel drive","Volvo 2.5L 5 Cylinder 227 hp 236 ft-lbs Turbo","True","6","6 Speed Manual","20","Gasoline","27","Manual transmission","2010 Volvo S40 R-Design AWD","Volvo","2010 Volvo S40","2010","227","236" +"203","19","72","Front-wheel drive","Volvo 2.5L 5 Cylinder 250 hp 266 ft-lbs Turbo","True","6","6 Speed Automatic Select Shift","20","Gasoline","30","Automatic transmission","2012 Volvo S60 T5","Volvo","2012 Volvo S60","2012","250","266" +"203","19","72","All-wheel drive","Volvo 3.0 L 6 Cylinder 300 HP 325 ft-lbs Turbo","True","6","6 Speed Automatic Select Shift","18","Gasoline","26","Automatic transmission","2012 Volvo S60 T6 AWD","Volvo","2012 Volvo S60","2012","300","325" +"203","19","72","All-wheel drive","Volvo 3.0 L 6 Cylinder 325 HP 354 ft-lbs Turbo","True","6","6 Speed Automatic Select Shift","18","Gasoline","26","Automatic transmission","2012 Volvo S60 R-Design","Volvo","2012 Volvo S60","2012","325","354" +"203","14","72","All-wheel drive","Volvo 3.0 L 6 Cylinder 300 HP 325 ft-lbs Turbo","True","6","6 Speed Automatic","18","Gasoline","26","Automatic transmission","2011 Volvo S60 T6 AWD","Volvo","2011 Volvo S60","2011","300","325" +"213","243","69","Front-wheel drive","Volvo 3.2 L 6 cylinder 240 hp 236 ft-lbs","True","6","6 Speed Automatic Select Shift","19","Gasoline","27","Automatic transmission","2011 Volvo S80 3.2","Volvo","2011 Volvo S80","2011","240","236" +"213","243","69","All-wheel drive","Volvo 4.4L 8 Cylinder 311 hp 325 ft-lbs","True","6","6 Speed Automatic","15","Gasoline","22","Automatic transmission","2010 Volvo S80 V8","Volvo","2010 Volvo S80","2010","311","325" +"213","243","69","All-wheel drive","Volvo 3.0L 6 Cylinder 281 hp 295 ft-lbs Turbo","True","6","6 Speed Automatic Select Shift","16","Gasoline","24","Automatic transmission","2010 Volvo S80 T6 AWD","Volvo","2010 Volvo S80","2010","281","295" +"213","243","69","Front-wheel drive","Volvo 3.2L 6 Cylinder 235 hp 236 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","27","Automatic transmission","2010 Volvo S80 3.2","Volvo","2010 Volvo S80","2010","235","236" +"177","169","234","Front-wheel drive","Volvo 2.5L 5 Cylinder 227 hp 236 ft-lbs Turbo","True","5","5 Speed Automatic","21","Gasoline","30","Automatic transmission","2011 Volvo V50 T5","Volvo","2011 Volvo V50","2011","227","236" +"193","169","234","All-wheel drive","Volvo 2.5L 5 Cylinder 227 hp 236 ft-lbs Turbo","True","6","6 Speed Manual","20","Gasoline","26","Manual transmission","2010 Volvo V50 R-Design","Volvo","2010 Volvo V50","2010","227","236" +"177","169","234","Front-wheel drive","Volvo 2.4L 5 Cylinder 168 hp 166 ft-lbs","True","5","5 Speed Automatic Select Shift","20","Gasoline","31","Automatic transmission","2010 Volvo V50 2.4i","Volvo","2010 Volvo V50","2010","168","170" +"175","19","97","All-wheel drive","Volvo 3.0 L 6 Cylinder 300 HP 325 ft-lbs Turbo","True","6","6 Speed Automatic","17","Gasoline","22","Automatic transmission","2011 Volvo XC60 T6 AWD","Volvo","2011 Volvo XC60","2011","300","325" +"175","19","97","Front-wheel drive","Volvo 3.2 L 6 cylinder 240 hp 236 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","25","Automatic transmission","2011 Volvo XC60 3.2","Volvo","2011 Volvo XC60","2011","240","236" +"175","19","97","All-wheel drive","Volvo 3.0L 6 Cylinder 281 hp 295 ft-lbs Turbo","True","6","6 Speed Automatic Select Shift","16","Gasoline","21","Automatic transmission","2010 Volvo XC60 T6 AWD","Volvo","2010 Volvo XC60","2010","281","295" +"175","19","97","Front-wheel drive","Volvo 3.2L 6 Cylinder 235 hp 236 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","27","Automatic transmission","2010 Volvo XC60 3.2","Volvo","2010 Volvo XC60","2010","235","236" +"66","230","69","Front-wheel drive","Volvo 3.2 L 6 cylinder 240 hp 236 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","25","Automatic transmission","2011 Volvo XC70 3.2","Volvo","2011 Volvo XC70","2011","240","236" +"66","230","69","All-wheel drive","Volvo 3.0 L 6 Cylinder 300 HP 325 ft-lbs Turbo","True","6","6 Speed Automatic","17","Gasoline","22","Automatic transmission","2011 Volvo XC70 T6 AWD","Volvo","2011 Volvo XC70","2011","300","325" +"66","230","69","All-wheel drive","Volvo 3.0L 6 Cylinder 281 hp 295 ft-lbs Turbo","True","6","6 Speed Automatic","16","Gasoline","21","Automatic transmission","2010 Volvo XC70 T6 AWD","Volvo","2010 Volvo XC70","2010","281","295" +"66","230","69","All-wheel drive","Volvo 3.2L 6 Cylinder 235 hp 236 ft-lbs","True","6","6 Speed Automatic","16","Gasoline","22","Automatic transmission","2010 Volvo XC70 3.2","Volvo","2010 Volvo XC70","2010","235","236" +"24","216","133","Rear-wheel drive","Toyota 4.0L 6 Cylinder 270 hp 278 ft-lbs","True","5","5 Speed Automatic","17","Gasoline","23","Automatic transmission","2011 Toyota 4Runner SR5","Toyota","2011 Toyota 4Runner","2011","270","278" +"24","216","24","Four-wheel drive","Toyota 4.0L 6 Cylinder 270 hp 278 ft-lbs","True","5","5 Speed Automatic","17","Gasoline","22","Automatic transmission","2011 Toyota 4Runner SR5 4WD","Toyota","2011 Toyota 4Runner","2011","270","278" +"93","216","133","Four-wheel drive","Toyota 4.0L 6 Cylinder 270 hp 278 ft-lbs","True","5","5 Speed Automatic","17","Gasoline","22","Automatic transmission","2011 Toyota 4Runner Trail","Toyota","2011 Toyota 4Runner","2011","270","278" +"24","216","133","Rear-wheel drive","Toyota 4.0L 6 Cylinder 270 hp 278 ft-lbs","True","5","5 Speed Automatic","17","Gasoline","23","Automatic transmission","2011 Toyota 4Runner Limited","Toyota","2011 Toyota 4Runner","2011","270","278" +"24","216","133","Four-wheel drive","Toyota 4.0L 6 Cylinder 270 hp 278 ft-lbs","True","5","5 Speed Automatic","17","Gasoline","22","Automatic transmission","2011 Toyota 4Runner Limited 4WD","Toyota","2011 Toyota 4Runner","2011","270","278" +"247","200","105","Front-wheel drive","Volvo 3.2 L 6 cylinder 240 hp 236 ft-lbs","True","6","6 Speed Automatic","16","Gasoline","22","Automatic transmission","2011 Volvo XC90 3.2","Volvo","2011 Volvo XC90","2011","240","236" +"247","200","105","All-wheel drive","Volvo 4.4L 8 Cylinder 311 hp 325 ft-lbs","True","6","6 Speed Automatic","14","Gasoline","21","Automatic transmission","2011 Volvo XC90 V8","Volvo","2011 Volvo XC90","2011","311","325" +"247","200","105","Front-wheel drive","Volvo 3.2L 6 Cylinder 235 hp 236 ft-lbs","True","6","6 Speed Automatic","15","Gasoline","22","Automatic transmission","2010 Volvo XC90 3.2","Volvo","2010 Volvo XC90","2010","235","236" +"247","200","105","All-wheel drive","Volvo 4.4L 8 Cylinder 311 hp 325 ft-lbs","True","6","6 Speed Automatic","13","Gasoline","19","Automatic transmission","2010 Volvo XC90 V8","Volvo","2010 Volvo XC90","2010","311","325" +"10","215","69","Front-wheel drive","Volvo 3.2L 6 Cylinder 235 hp 236 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","27","Automatic transmission","2010 Volvo V70 3.2","Volvo","2010 Volvo V70","2010","235","236" +"24","216","133","Rear-wheel drive","Toyota 2.7L 4 Cylinder 157 hp 178 ft-lbs","True","4","4 Speed Automatic","18","Gasoline","23","Automatic transmission","2010 Toyota 4Runner SR5","Toyota","2010 Toyota 4Runner","2010","157","178" +"24","216","133","Rear-wheel drive","Toyota 4.0L 6 Cylinder 270 hp 278 ft-lbs","True","5","5 Speed Automatic","17","Gasoline","23","Automatic transmission","2010 Toyota 4Runner SR5 V6","Toyota","2010 Toyota 4Runner","2010","270","278" +"24","216","133","Four-wheel drive","Toyota 4.0L 6 Cylinder 270 hp 278 ft-lbs","True","5","5 Speed Automatic","17","Gasoline","22","Automatic transmission","2010 Toyota 4Runner SR5 V6 4WD","Toyota","2010 Toyota 4Runner","2010","270","278" +"93","216","133","Four-wheel drive","Toyota 4.0L 6 Cylinder 270 hp 278 ft-lbs","True","5","5 Speed Automatic","17","Gasoline","22","Automatic transmission","2010 Toyota 4Runner Trail","Toyota","2010 Toyota 4Runner","2010","270","278" +"24","216","133","Rear-wheel drive","Toyota 4.0L 6 Cylinder 270 hp 278 ft-lbs","True","5","5 Speed Automatic","17","Gasoline","23","Automatic transmission","2010 Toyota 4Runner Limited","Toyota","2010 Toyota 4Runner","2010","270","278" +"24","216","133","Four-wheel drive","Toyota 4.0L 6 Cylinder 270 hp 278 ft-lbs","True","5","5 Speed Automatic","17","Gasoline","22","Automatic transmission","2010 Toyota 4Runner Limited 4WD","Toyota","2010 Toyota 4Runner","2010","270","278" +"143","196","203","Front-wheel drive","Audi 2.0L 4 cylinder 200 hp 207 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","30","Manual transmission","2012 Audi A3 2.0 T","Audi","2012 Audi A3","2012","200","207" +"152","240","57","Front-wheel drive","Honda 3.5L 6 Cylinder 271hp 251 ft-lbs","True","6","6 Speed Manual","17","Gasoline","25","Manual transmission","2010 Honda Accord EX-L V-6 Coup","Honda","2010 Honda Accord Coupe","2010","271","251" +"152","240","57","Front-wheel drive","Honda 2.4L 4 cylinder 190 hp 162 ft-lbs","True","5","5 Speed Automatic","21","Gasoline","31","Automatic transmission","2010 Honda Accord EX Coup AT","Honda","2010 Honda Accord Coupe","2010","190","162" +"152","240","57","Front-wheel drive","Honda 2.4L 4 cylinder 190 hp 162 ft-lbs","True","5","5 Speed Manual","22","Gasoline","31","Manual transmission","2010 Honda Accord EX-L Coup","Honda","2010 Honda Accord Coupe","2010","190","162" +"152","240","57","Front-wheel drive","Honda 2.4L 4 cylinder 190 hp 162 ft-lbs","True","5","5 Speed Automatic","21","Gasoline","31","Automatic transmission","2010 Honda Accord EX-L Coup AT","Honda","2010 Honda Accord Coupe","2010","190","162" +"152","240","57","Front-wheel drive","Honda 3.5L 6 Cylinder 271hp 251 ft-lbs","True","5","5 Speed Automatic","19","Gasoline","28","Automatic transmission","2010 Honda Accord EX-L V-6 Coup AT","Honda","2010 Honda Accord Coupe","2010","271","251" +"152","240","57","Front-wheel drive","Honda 2.4L 4 cylinder 190 hp 162 ft-lbs","True","5","5 Speed Manual","22","Gasoline","31","Manual transmission","2010 Honda Accord EX Coup","Honda","2010 Honda Accord Coupe","2010","190","162" +"152","240","57","Front-wheel drive","Honda 2.4L 4 cylinder 190 hp 162 ft-lbs","True","5","5 Speed Automatic","21","Gasoline","31","Automatic transmission","2010 Honda Accord LX-S Coup AT","Honda","2010 Honda Accord Coupe","2010","190","162" +"152","240","57","Front-wheel drive","Honda 2.4L 4 cylinder 190 hp 162 ft-lbs","True","5","5 Speed Manual","22","Gasoline","31","Manual transmission","2010 Honda Accord LX-S Coup","Honda","2010 Honda Accord Coupe","2010","190","162" +"45","150","57","Rear-wheel drive","Nissan 3.7L 6 Cylinder 332 hp 270 ft-lbs","True","6","6 Speed Manual","18","Gasoline","25","Manual transmission","2011 Nissan 370Z Roadster","Nissan","2011 Nissan 370Z Roadster","2011","332","270" +"45","150","57","Rear-wheel drive","Nissan 3.7L 6 Cylinder 332 hp 270 ft-lbs","True","7","7 Speed Automatic Select Shift","18","Gasoline","25","Automatic transmission","2011 Nissan 370Z Roadster AT","Nissan","2011 Nissan 370Z Roadster","2011","332","270" +"45","150","57","Rear-wheel drive","Nissan 3.7L 6 Cylinder 332 hp 270 ft-lbs","True","6","6 Speed Manual","18","Gasoline","25","Manual transmission","2011 Nissan 370Z Touring Roadster","Nissan","2011 Nissan 370Z Roadster","2011","332","270" +"45","150","57","Rear-wheel drive","Nissan 3.7L 6 Cylinder 332 hp 270 ft-lbs","True","7","7 Speed Automatic Select Shift","18","Gasoline","25","Automatic transmission","2011 Nissan 370Z Touring Roadster AT","Nissan","2011 Nissan 370Z Roadster","2011","332","270" +"45","150","57","Rear-wheel drive","Nissan 3.7L 6 Cylinder 332 hp 270 ft-lbs","True","6","6 Speed Manual","18","Gasoline","25","Manual transmission","2010 Nissan 370Z Touring Roadster","Nissan","2010 Nissan 370Z Roadster","2010","332","270" +"45","150","57","Rear-wheel drive","Nissan 3.7L 6 Cylinder 332 hp 270 ft-lbs","True","6","6 Speed Manual","18","Gasoline","25","Manual transmission","2010 Nissan 370Z Roadster","Nissan","2010 Nissan 370Z Roadster","2010","332","270" +"45","150","57","Rear-wheel drive","Nissan 3.7L 6 Cylinder 332 hp 270 ft-lbs","True","7","7 Speed Automatic Select Shift","18","Gasoline","25","Automatic transmission","2010 Nissan 370Z Roadster AT","Nissan","2010 Nissan 370Z Roadster","2010","332","270" +"45","150","57","Rear-wheel drive","Nissan 3.7L 6 Cylinder 332 hp 270 ft-lbs","True","7","7 Speed Automatic Select Shift","18","Gasoline","25","Automatic transmission","2010 Nissan 370Z Touring Roadster AT","Nissan","2010 Nissan 370Z Roadster","2010","332","270" +"143","196","203","Front-wheel drive","Audi 2.0L 4 cylinder 200 hp 207 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","30","Manual transmission","2011 Audi A3 2.0 T","Audi","2011 Audi A3","2011","200","207" +"35","150","52","Rear-wheel drive","Nissan 3.7L 6 Cylinder 332 hp 270 ft-lbs","True","6","6 Speed Manual","18","Gasoline","26","Manual transmission","2011 Nissan 370Z Coupe","Nissan","2011 Nissan 370Z Coupe","2011","332","270" +"35","150","52","Rear-wheel drive","Nissan 3.7L 6 Cylinder 332 hp 270 ft-lbs","True","6","6 Speed Manual","18","Gasoline","26","Manual transmission","2011 Nissan 370Z Touring Coupe","Nissan","2011 Nissan 370Z Coupe","2011","332","270" +"35","150","52","Rear-wheel drive","Nissan 3.7L 6 Cylinder 332 hp 270 ft-lbs","True","7","7 Speed Automatic Select Shift","19","Gasoline","26","Automatic transmission","2011 Nissan 370Z Touring Coupe AT","Nissan","2011 Nissan 370Z Coupe","2011","332","270" +"35","150","52","Rear-wheel drive","Nissan 3.7L 6 Cylinder 332 hp 270 ft-lbs","True","6","6 Speed Manual","18","Gasoline","26","Manual transmission","2011 Nissan 370Z Touring Coupe","Nissan","2011 Nissan 370Z Coupe","2011","332","270" +"143","196","203","Front-wheel drive","Audi 2.0L 4 cylinder 200 hp 207 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","30","Manual transmission","2010 Audi A3 2.0 T","Audi","2010 Audi A3","2010","200","207" +"35","150","52","Rear-wheel drive","Nissan 3.7L 6 Cylinder 332 hp 270 ft-lbs","True","7","7 Speed Automatic Select Shift","19","Gasoline","26","Automatic transmission","2010 Nissan 370Z Touring Coupe AT","Nissan","2010 Nissan 370Z Coupe","2010","332","270" +"35","150","52","Rear-wheel drive","Nissan 3.7L 6 Cylinder 332 hp 270 ft-lbs","True","6","6 Speed Manual","18","Gasoline","26","Manual transmission","2010 Nissan 370Z Coupe","Nissan","2010 Nissan 370Z Coupe","2010","332","270" +"35","150","52","Rear-wheel drive","Nissan 3.7L 6 Cylinder 332 hp 270 ft-lbs","True","6","6 Speed Manual","18","Gasoline","26","Manual transmission","2010 Nissan 370Z Touring Coupe","Nissan","2010 Nissan 370Z Coupe","2010","332","270" +"35","150","52","Rear-wheel drive","Nissan 3.7L 6 Cylinder 332 hp 270 ft-lbs","True","7","7 Speed Automatic Select Shift","19","Gasoline","26","Automatic transmission","2010 Nissan 370Z Coupe AT","Nissan","2010 Nissan 370Z Coupe","2010","332","270" +"147","95","248","All-wheel drive","Audi 2.0L 4 cylinder 211 hp 258 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","31","Manual transmission","2012 Audi A4 Sedan 2.0 T Quattro","Audi","2012 Audi A4 Sedan","2012","211","258" +"147","95","248","All-wheel drive","Audi 2.0L 4 cylinder 211 hp 258 ft-lbs Turbo","True","8","8 Speed Automatic Select Shift","21","Gasoline","29","Automatic transmission","2012 Audi A4 Sedan 2.0 T Quattro AT","Audi","2012 Audi A4 Sedan","2012","211","258" +"147","95","214","All-wheel drive","Audi 2.0L 4 cylinder 211 hp 258 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","31","Manual transmission","2011 Audi A4 Sedan 2.0 T Quattro","Audi","2011 Audi A4 Sedan","2011","211","258" +"147","95","214","All-wheel drive","Audi 2.0L 4 cylinder 211 hp 258 ft-lbs Turbo","True","8","8 Speed Automatic Select Shift","21","Gasoline","29","Automatic transmission","2011 Audi A4 Sedan 2.0 T Quattro AT","Audi","2011 Audi A4 Sedan","2011","211","258" +"193","57","186","Front-wheel drive","Ford 1.6L 4 Cylinder 120 hp 112 ft-lbs","True","5","5 Speed Manual","29","Gasoline","38","Manual transmission","2012 Ford Fiesta S Sedan","Ford","2012 Ford Fiesta Sedan","2012","120","112" +"193","57","186","Front-wheel drive","Ford 1.6L 4 Cylinder 120 hp 112 ft-lbs","True","5","5 Speed Manual","29","Gasoline","38","Manual transmission","2012 Ford Fiesta SE Sedan","Ford","2012 Ford Fiesta Sedan","2012","120","112" +"193","57","186","Front-wheel drive","Ford 1.6L 4 Cylinder 120 hp 112 ft-lbs","True","5","5 Speed Manual","29","Gasoline","38","Manual transmission","2012 Ford Fiesta SEL Sedan","Ford","2012 Ford Fiesta Sedan","2012","120","112" +"193","57","160","Front-wheel drive","Ford 1.6L 4 Cylinder 120 hp 112 ft-lbs","True","5","5 Speed Manual","38","Gasoline","37","Manual transmission","2011 Ford Fiesta Sedan S","Ford","2011 Ford Fiesta Sedan","2011","120","112" +"193","57","160","Front-wheel drive","Ford 1.6L 4 Cylinder 120 hp 112 ft-lbs","True","5","5 Speed Manual","28","Gasoline","37","Manual transmission","2011 Ford Fiesta Sedan SE","Ford","2011 Ford Fiesta Sedan","2011","120","112" +"193","57","160","Front-wheel drive","Ford 1.6L 4 Cylinder 120 hp 112 ft-lbs","True","5","5 Speed Manual","28","Gasoline","37","Manual transmission","2011 Ford Fiesta Sedan SEL","Ford","2011 Ford Fiesta Sedan","2011","120","112" +"167","168","247","Front-wheel drive","Volvo 2.5L 5 Cylinder 227 hp 236 ft-lbs Turbo","True","5","5 Speed Automatic","21","Gasoline","30","Automatic transmission","2011 Volvo C30 R-Design AT","Volvo","2011 Volvo C30","2011","227","236" +"167","168","247","Front-wheel drive","Volvo 2.5L 5 Cylinder 227 hp 236 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","29","Manual transmission","2011 Volvo C30 R-Design","Volvo","2011 Volvo C30","2011","227","236" +"167","155","247","Front-wheel drive","Volvo 2.5L 5 Cylinder 227 hp 236 ft-lbs Turbo","True","5","5 Speed Automatic","21","Gasoline","30","Automatic transmission","2010 Volvo C30 R-Design AT","Volvo","2010 Volvo C30","2010","227","236" +"167","155","247","Front-wheel drive","Volvo 2.5L 5 Cylinder 227 hp 236 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","29","Manual transmission","2010 Volvo C30 R-Design","Volvo","2010 Volvo C30","2010","227","236" +"147","95","34","All-wheel drive","Audi 2.0L 4 cylinder 211 hp 258 ft-lbs Turbo","True","6","6 Speed Automatic Select Shift","21","Gasoline","27","Automatic transmission","2010 Audi A4 Sedan 2.0 T Quattro AT","Audi","2010 Audi A4 Sedan","2010","211","258" +"147","95","34","All-wheel drive","Audi 2.0L 4 cylinder 211 hp 258 ft-lbs Turbo","True","6","6 Speed Manual","22","Gasoline","30","Manual transmission","2010 Audi A4 Sedan 2.0 T Quattro","Audi","2010 Audi A4 Sedan","2010","211","258" +"172","123","234","Front-wheel drive","Volvo 2.4L 5 Cylinder 168 hp 166 ft-lbs","True","5","5 Speed Automatic","21","Gasoline","29","Automatic transmission","2010 Volvo S40 2.4i AT","Volvo","2010 Volvo S40","2010","168","170" +"190","123","234","All-wheel drive","Volvo 2.5L 5 Cylinder 227 hp 236 ft-lbs Turbo","True","5","5 Speed Automatic","20","Gasoline","27","Automatic transmission","2010 Volvo S40 R-Design AT AWD","Volvo","2010 Volvo S40","2010","227","236" +"156","95","248","All-wheel drive","Audi 2.0L 4 cylinder 211 hp 258 ft-lbs Turbo","True","8","8 Speed Automatic Select Shift","21","Gasoline","29","Automatic transmission","2012 Audi A4 Avant 2.0 T","Audi","2012 Audi A4 Avant","2012","211","258" +"156","95","214","All-wheel drive","Audi 2.0L 4 cylinder 211 hp 258 ft-lbs Turbo","True","8","8 Speed Automatic Select Shift","21","Gasoline","29","Automatic transmission","2011 Audi A4 Avant 2.0 T","Audi","2011 Audi A4 Avant","2011","211","258" +"155","95","34","All-wheel drive","Audi 2.0L 4 cylinder 211 hp 258 ft-lbs Turbo","True","6","6 Speed Automatic Select Shift","23","Gasoline","30","Automatic transmission","2010 Audi A4 Avant 2.0 T","Audi","2010 Audi A4 Avant","2010","211","258" +"152","240","57","Front-wheel drive","Honda 2.4L 4 cylinder 190 hp 162 ft-lbs","True","5","5 Speed Manual","23","Gasoline","32","Manual transmission","2011 Honda Accord EX Coup","Honda","2011 Honda Accord Coup","2011","190","162" +"152","240","57","Front-wheel drive","Honda 2.4L 4 cylinder 190 hp 162 ft-lbs","True","5","5 Speed Automatic","22","Gasoline","33","Automatic transmission","2011 Honda Accord LX-S Coup AT","Honda","2011 Honda Accord Coup","2011","190","162" +"152","240","57","Front-wheel drive","Honda 3.5L 6 Cylinder 271hp 251 ft-lbs","True","6","6 Speed Manual","17","Gasoline","26","Manual transmission","2011 Honda Accord EX-L V-6 Coup","Honda","2011 Honda Accord Coup","2011","271","251" +"152","240","57","Front-wheel drive","Honda 2.4L 4 cylinder 190 hp 162 ft-lbs","True","5","5 Speed Manual","23","Gasoline","32","Manual transmission","2011 Honda Accord LX-S Coup","Honda","2011 Honda Accord Coup","2011","190","162" +"152","240","57","Front-wheel drive","Honda 3.5L 6 Cylinder 271hp 251 ft-lbs","True","5","5 Speed Automatic","19","Gasoline","29","Automatic transmission","2011 Honda Accord EX-L V-6 Coup AT","Honda","2011 Honda Accord Coup","2011","271","251" +"152","240","57","Front-wheel drive","Honda 2.4L 4 cylinder 190 hp 162 ft-lbs","True","5","5 Speed Automatic","22","Gasoline","33","Automatic transmission","2011 Honda Accord EX Coup AT","Honda","2011 Honda Accord Coup","2011","190","162" +"152","240","57","Front-wheel drive","Honda 2.4L 4 cylinder 190 hp 162 ft-lbs","True","5","5 Speed Automatic","22","Gasoline","33","Automatic transmission","2011 Honda Accord EX-L Coup","Honda","2011 Honda Accord Coup","2011","190","162" +"193","226","186","Front-wheel drive","Ford 1.6L 4 Cylinder 120 hp 112 ft-lbs","True","5","5 Speed Manual","29","Gasoline","38","Manual transmission","2012 Ford Fiesta SE Hatchback","Ford","2012 Ford Fiesta Hatchback","2012","120","112" +"193","226","186","Front-wheel drive","Ford 1.6L 4 Cylinder 120 hp 112 ft-lbs","True","5","5 Speed Manual","29","Gasoline","38","Manual transmission","2012 Ford Fiesta SES Hatchback","Ford","2012 Ford Fiesta Hatchback","2012","120","112" +"193","226","160","Front-wheel drive","Ford 1.6L 4 Cylinder 120 hp 112 ft-lbs","True","5","5 Speed Manual","28","Gasoline","37","Manual transmission","2011 Ford Fiesta Hatchback SE","Ford","2011 Ford Fiesta Hatchback","2011","120","112" +"193","226","160","Front-wheel drive","Ford 1.6L 4 Cylinder 120 hp 112 ft-lbs","True","5","5 Speed Manual","28","Gasoline","37","Manual transmission","2011 Ford Fiesta Hatchback SES","Ford","2011 Ford Fiesta Hatchback","2011","120","112" +"58","66","54","Front-wheel drive","Honda 2.4L 4 cylinder 177 hp 161 ft-lbs","True","5","5 Speed Manual","22","Gasoline","31","Manual transmission","2010 Honda Accord LX Sedan","Honda","2010 Honda Accord Sedan","2010","177","161" +"195","66","54","Front-wheel drive","Honda 2.4L 4 cylinder 177 hp 161 ft-lbs","True","5","5 Speed Automatic","21","Gasoline","31","Automatic transmission","2010 Honda Accord LX Sedan AT","Honda","2010 Honda Accord Sedan","2010","177","161" +"195","66","54","Front-wheel drive","Honda 2.4L 4 cylinder 177 hp 161 ft-lbs","True","5","5 Speed Manual","22","Gasoline","31","Manual transmission","2010 Honda Accord LX-P Sedan","Honda","2010 Honda Accord Sedan","2010","177","161" +"195","66","54","Front-wheel drive","Honda 2.4L 4 cylinder 177 hp 161 ft-lbs","True","5","5 Speed Automatic","21","Gasoline","31","Automatic transmission","2010 Honda Accord LX-P Sedan AT","Honda","2010 Honda Accord Sedan","2010","177","161" +"195","66","54","Front-wheel drive","Honda 2.4L 4 cylinder 190 hp 162 ft-lbs","True","5","5 Speed Manual","22","Gasoline","31","Manual transmission","2010 Honda Accord EX Sedan","Honda","2010 Honda Accord Sedan","2010","190","162" +"195","66","54","Front-wheel drive","Honda 2.4L 4 cylinder 190 hp 162 ft-lbs","True","5","5 Speed Automatic","21","Gasoline","31","Automatic transmission","2010 Honda Accord EX Sedan AT","Honda","2010 Honda Accord Sedan","2010","190","162" +"195","66","54","Front-wheel drive","Honda 2.4L 4 cylinder 190 hp 162 ft-lbs","True","5","5 Speed Manual","22","Gasoline","31","Manual transmission","2010 Honda Accord EX-L Sedan","Honda","2010 Honda Accord Sedan","2010","190","162" +"195","66","54","Front-wheel drive","Honda 2.4L 4 cylinder 190 hp 162 ft-lbs","True","5","5 Speed Automatic","21","Gasoline","31","Automatic transmission","2010 Honda Accord EX-L Sedan AT","Honda","2010 Honda Accord Sedan","2010","190","162" +"195","71","54","Front-wheel drive","Honda 3.5L 6 Cylinder 271 hp 254 ft-lbs","True","5","5 Speed Automatic","19","Gasoline","29","Automatic transmission","2010 Honda Accord EX V-6 Sedan","Honda","2010 Honda Accord Sedan","2010","271","254" +"206","155","57","Front-wheel drive","Toyota 3.5L 6 Cylinder 268 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","29","Automatic transmission","2011 Toyota Avalon","Toyota","2011 Toyota Avalon","2011","268","248" +"206","155","57","Front-wheel drive","Toyota 3.5L 6 Cylinder 268 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","29","Automatic transmission","2011 Toyota Avalon Limited","Toyota","2011 Toyota Avalon","2011","268","248" +"35","150","57","Rear-wheel drive","Nissan 3.7L 6 Cylinder 332 hp 270 ft-lbs","True","7","7 Speed Automatic","18","Gasoline","26","Automatic transmission","2009 Nissan 370Z Coupe AT","Nissan","2009 Nissan 370Z Coupe","2009","332","270" +"35","150","57","Rear-wheel drive","Nissan 3.7L 6 Cylinder 332 hp 270 ft-lbs","True","7","7 Speed Automatic Select Shift","18","Gasoline","26","Automatic transmission","2009 Nissan 370Z Touring Coupe AT","Nissan","2009 Nissan 370Z Coupe","2009","332","270" +"35","150","57","Rear-wheel drive","Nissan 3.7L 6 Cylinder 332 hp 270 ft-lbs","True","6","6 Speed Manual","18","Gasoline","26","Manual transmission","2009 Nissan 370Z Touring Coupe","Nissan","2009 Nissan 370Z Coupe","2009","332","270" +"35","150","57","Rear-wheel drive","Nissan 3.7L 6 Cylinder 332 hp 270 ft-lbs","True","6","6 Speed Manual","18","Gasoline","26","Manual transmission","2009 Nissan 370Z Coupe","Nissan","2009 Nissan 370Z Coupe","2009","332","270" +"205","155","57","Front-wheel drive","Toyota 3.5L 6 Cylinder 268 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","19","Gasoline","28","Automatic transmission","2010 Toyota Avalon XL","Toyota","2010 Toyota Avalon","2010","268","248" +"206","155","57","Front-wheel drive","Toyota 3.5L 6 Cylinder 268 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","19","Gasoline","28","Automatic transmission","2010 Toyota Avalon XLS","Toyota","2010 Toyota Avalon","2010","268","248" +"206","155","57","Front-wheel drive","Toyota 3.5L 6 Cylinder 268 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","19","Gasoline","28","Automatic transmission","2010 Toyota Avalon Limited","Toyota","2010 Toyota Avalon","2010","268","248" +"191","198","29","Front-wheel drive","Toyota 2.5L 4 Cylinder 169 hp 167 ft-lbs","True","6","6 Speed Manual","22","Gasoline","33","Manual transmission","2011 Toyota Camry","Toyota","2011 Toyota Camry","2011","169","167" +"191","198","29","Front-wheel drive","Toyota 2.5L 4 Cylinder 169 hp 167 ft-lbs","True","6","6 Speed Automatic Select Shift","22","Gasoline","32","Automatic transmission","2011 Toyota Camry AT","Toyota","2011 Toyota Camry","2011","169","167" +"191","198","29","Front-wheel drive","Toyota 2.5L 4 Cylinder 169 hp 167 ft-lbs","True","6","6 Speed Manual","22","Gasoline","33","Manual transmission","2011 Toyota Camry LE","Toyota","2011 Toyota Camry","2011","169","167" +"191","198","29","Front-wheel drive","Toyota 2.5L 4 Cylinder 169 hp 167 ft-lbs","True","6","6 Speed Automatic Select Shift","22","Gasoline","32","Automatic transmission","2011 Toyota Camry LE AT","Toyota","2011 Toyota Camry","2011","169","167" +"191","198","29","Front-wheel drive","Toyota 3.5L 6 Cylinder 268 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","29","Automatic transmission","2011 Toyota Camry LE V6","Toyota","2011 Toyota Camry","2011","268","248" +"186","198","29","Front-wheel drive","Toyota 2.5L 4 Cylinder 179 hp 171 ft-lbs","True","6","6 Speed Manual","22","Gasoline","33","Manual transmission","2011 Toyota Camry SE","Toyota","2011 Toyota Camry","2011","179","171" +"186","198","29","Front-wheel drive","Toyota 2.5L 4 Cylinder 179 hp 171 ft-lbs","True","6","6 Speed Automatic Select Shift","22","Gasoline","32","Automatic transmission","2011 Toyota Camry SE AT","Toyota","2011 Toyota Camry","2011","179","171" +"186","198","29","Front-wheel drive","Toyota 3.5L 6 Cylinder 268 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","29","Automatic transmission","2011 Toyota Camry SE V6","Toyota","2011 Toyota Camry","2011","268","248" +"191","198","29","Front-wheel drive","Toyota 2.5L 4 Cylinder 169 hp 167 ft-lbs","True","6","6 Speed Automatic Select Shift","22","Gasoline","32","Automatic transmission","2011 Toyota Camry XLE","Toyota","2011 Toyota Camry","2011","169","167" +"191","198","29","Front-wheel drive","Toyota 3.5L 6 Cylinder 268 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","29","Automatic transmission","2011 Toyota Camry XLE V6","Toyota","2011 Toyota Camry","2011","268","248" +"185","181","31","Front-wheel drive","Ford 2.0L 4 Cylinder 160 hp 146 ft-lbs","True","5","5 Speed Manual","26","Gasoline","36","Manual transmission","2012 Ford Focus S Sedan","Ford","2012 Ford Focus Sedan","2012","160","146" +"185","181","31","Front-wheel drive","Ford 2.0L 4 Cylinder 160 hp 146 ft-lbs","True","5","5 Speed Manual","26","Gasoline","36","Manual transmission","2012 Ford Focus SE Sedan","Ford","2012 Ford Focus Sedan","2012","160","146" +"208","93","186","Front-wheel drive","Ford 2.0L 4 Cylinder 140 hp 136 ft-lbs","True","5","5 Speed Manual","25","Gasoline","35","Manual transmission","2011 Ford Focus Sedan S","Ford","2011 Ford Focus Sedan","2011","140","136" +"208","93","186","Front-wheel drive","Ford 2.0L 4 Cylinder 140 hp 136 ft-lbs","True","4","4 Speed Automatic","25","Gasoline","34","Automatic transmission","2011 Ford Focus Sedan S AT","Ford","2011 Ford Focus Sedan","2011","140","136" +"208","93","186","Front-wheel drive","Ford 2.0L 4 Cylinder 140 hp 136 ft-lbs","True","5","5 Speed Manual","25","Gasoline","35","Manual transmission","2011 Ford Focus Sedan SE","Ford","2011 Ford Focus Sedan","2011","140","136" +"208","93","186","Front-wheel drive","Ford 2.0L 4 Cylinder 140 hp 136 ft-lbs","True","4","4 Speed Automatic","25","Gasoline","34","Automatic transmission","2011 Ford Focus Sedan SE AT","Ford","2011 Ford Focus Sedan","2011","140","136" +"208","93","186","Front-wheel drive","Ford 2.0L 4 Cylinder 140 hp 136 ft-lbs","True","5","5 Speed Manual","25","Gasoline","35","Manual transmission","2011 Ford Focus Sedan SES","Ford","2011 Ford Focus Sedan","2011","140","136" +"208","93","186","Front-wheel drive","Ford 2.0L 4 Cylinder 140 hp 136 ft-lbs","True","4","4 Speed Automatic","25","Gasoline","34","Automatic transmission","2011 Ford Focus Sedan SES AT","Ford","2011 Ford Focus Sedan","2011","140","136" +"208","93","186","Front-wheel drive","Ford 2.0L 4 Cylinder 140 hp 136 ft-lbs","True","4","4 Speed Automatic","25","Gasoline","34","Automatic transmission","2011 Ford Focus Sedan SEL","Ford","2011 Ford Focus Sedan","2011","140","136" +"208","93","186","Front-wheel drive","Ford 2.0L 4 Cylinder 140 hp 136 ft-lbs","True","5","5 Speed Manual","24","Gasoline","35","Manual transmission","2010 Ford Focus Sedan S","Ford","2010 Ford Focus Sedan","2010","140","136" +"208","93","186","Front-wheel drive","Ford 2.0L 4 Cylinder 140 hp 136 ft-lbs","True","4","4 Speed Automatic","24","Gasoline","34","Automatic transmission","2010 Ford Focus Sedan S AT","Ford","2010 Ford Focus Sedan","2010","140","136" +"208","93","186","Front-wheel drive","Ford 2.0L 4 Cylinder 140 hp 136 ft-lbs","True","5","5 Speed Manual","24","Gasoline","35","Manual transmission","2010 Ford Focus Sedan SE","Ford","2010 Ford Focus Sedan","2010","140","136" +"208","93","186","Front-wheel drive","Ford 2.0L 4 Cylinder 140 hp 136 ft-lbs","True","4","4 Speed Automatic","24","Gasoline","34","Automatic transmission","2010 Ford Focus Sedan SE AT","Ford","2010 Ford Focus Sedan","2010","140","136" +"208","93","186","Front-wheel drive","Ford 2.0L 4 Cylinder 140 hp 136 ft-lbs","True","5","5 Speed Manual","24","Gasoline","35","Manual transmission","2010 Ford Focus Sedan SES","Ford","2010 Ford Focus Sedan","2010","140","136" +"208","93","186","Front-wheel drive","Ford 2.0L 4 Cylinder 140 hp 136 ft-lbs","True","4","4 Speed Automatic","24","Gasoline","34","Automatic transmission","2010 Ford Focus Sedan SES AT","Ford","2010 Ford Focus Sedan","2010","140","136" +"208","93","186","Front-wheel drive","Ford 2.0L 4 Cylinder 140 hp 136 ft-lbs","True","5","5 Speed Manual","24","Gasoline","35","Manual transmission","2010 Ford Focus Sedan SEL","Ford","2010 Ford Focus Sedan","2010","140","136" +"208","93","186","Front-wheel drive","Ford 2.0L 4 Cylinder 140 hp 136 ft-lbs","True","4","4 Speed Automatic","24","Gasoline","34","Automatic transmission","2010 Ford Focus Sedan SEL AT","Ford","2010 Ford Focus Sedan","2010","140","136" +"139","242","3","Front-wheel drive","Nissan 2.5L 4 cylinder 175 hp 180 ft-lbs","True","6","6 Speed Manual","23","Gasoline","31","Manual transmission","2011 Nissan Altima Coupe 2.5 S","Nissan","2011 Nissan Altima Coupe","2011","175","180" +"139","242","3","Front-wheel drive","Nissan 3.5L 6 cylinder 270hp 258 ft-lbs","True","6","6 Speed Manual","18","Gasoline","27","Manual transmission","2011 Nissan Altima Coupe 3.5 SR","Nissan","2011 Nissan Altima Coupe","2011","270","258" +"213","243","69","All-wheel drive","Volvo 3.0 L 6 Cylinder 300 HP 325 ft-lbs Turbo","True","6","6 Speed Automatic Select Shift","18","Gasoline","26","Automatic transmission","2012 Volvo S80 T6 AWD","Volvo","2012 Volvo S80","2012","300","325" +"213","243","69","Front-wheel drive","Volvo 3.2 L 6 cylinder 240 hp 236 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","29","Automatic transmission","2012 Volvo S80 3.2","Volvo","2012 Volvo S80","2012","240","236" +"175","19","97","All-wheel drive","Volvo 3.0 L 6 Cylinder 325 HP 354 ft-lbs Turbo","True","6","6 Speed Automatic Select Shift","17","Gasoline","23","Automatic transmission","2012 Volvo XC60 T6 AWD R-Design","Volvo","2012 Volvo XC60","2012","325","354" +"175","19","97","Front-wheel drive","Volvo 3.2 L 6 cylinder 240 hp 236 ft-lbs","True","6","6 Speed Automatic Select Shift","19","Gasoline","25","Automatic transmission","2012 Volvo XC60 3.2","Volvo","2012 Volvo XC60","2012","240","236" +"175","19","97","All-wheel drive","Volvo 3.0 L 6 Cylinder 300 HP 325 ft-lbs Turbo","True","6","6 Speed Automatic Select Shift","17","Gasoline","23","Automatic transmission","2012 Volvo XC60 T6 AWD","Volvo","2012 Volvo XC60","2012","300","325" +"66","230","69","All-wheel drive","Volvo 3.0 L 6 Cylinder 300 HP 325 ft-lbs Turbo","True","6","6 Speed Automatic Select Shift","17","Gasoline","23","Automatic transmission","2012 Volvo XC70 T6 AWD","Volvo","2012 Volvo XC70","2012","300","325" +"66","230","69","Front-wheel drive","Volvo 3.2 L 6 cylinder 240 hp 236 ft-lbs","True","6","6 Speed Automatic Select Shift","19","Gasoline","25","Automatic transmission","2012 Volvo XC70 3.2","Volvo","2012 Volvo XC70","2012","240","236" +"247","200","105","Front-wheel drive","Volvo 3.2 L 6 cylinder 240 hp 236 ft-lbs","True","6","6 Speed Automatic Select Shift","16","Gasoline","23","Automatic transmission","2012 Volvo XC90 3.2","Volvo","2012 Volvo XC90","2012","240","236" +"247","200","105","Front-wheel drive","Volvo 3.2 L 6 cylinder 240 hp 236 ft-lbs","True","6","6 Speed Automatic Select Shift","16","Gasoline","23","Automatic transmission","2012 Volvo XC90 3.2 R-Design","Volvo","2012 Volvo XC90","2012","240","236" +"139","242","3","Front-wheel drive","Nissan 2.5L 4 cylinder 175 hp 180 ft-lbs","True","6","6 Speed Manual","23","Gasoline","32","Manual transmission","2010 Nissan Altima Coupe 2.5 S","Nissan","2010 Nissan Altima Coupe","2010","175","180" +"139","242","3","Front-wheel drive","Nissan 3.5L 6 cylinder 270hp 258 ft-lbs","True","6","6 Speed Manual","18","Gasoline","27","Manual transmission","2010 Nissan Altima Coupe 3.5 SR","Nissan","2010 Nissan Altima Coupe","2010","270","258" +"191","197","29","Front-wheel drive","Toyota 2.5L 4 Cylinder 169 hp 167 ft-lbs","True","6","6 Speed Manual","22","Gasoline","33","Manual transmission","2010 Toyota Camry","Toyota","2010 Toyota Camry","2010","169","167" +"191","198","29","Front-wheel drive","Toyota 2.5L 4 Cylinder 169 hp 167 ft-lbs","True","6","6 Speed Automatic Select Shift","22","Gasoline","32","Automatic transmission","2010 Toyota Camry AT","Toyota","2010 Toyota Camry","2010","169","167" +"191","198","29","Front-wheel drive","Toyota 2.5L 4 Cylinder 169 hp 167 ft-lbs","True","6","6 Speed Manual","22","Gasoline","33","Manual transmission","2010 Toyota Camry LE","Toyota","2010 Toyota Camry","2010","169","167" +"191","198","29","Front-wheel drive","Toyota 2.5L 4 Cylinder 169 hp 167 ft-lbs","True","6","6 Speed Automatic Select Shift","22","Gasoline","32","Automatic transmission","2010 Toyota Camry LE AT","Toyota","2010 Toyota Camry","2010","169","167" +"191","198","29","Front-wheel drive","Toyota 3.5L 6 Cylinder 268 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","19","Gasoline","28","Automatic transmission","2010 Toyota Camry LE V6","Toyota","2010 Toyota Camry","2010","268","248" +"186","198","29","Front-wheel drive","Toyota 2.5L 4 Cylinder 179 hp 171 ft-lbs","True","6","6 Speed Manual","22","Gasoline","33","Manual transmission","2010 Toyota Camry SE","Toyota","2010 Toyota Camry","2010","179","171" +"186","198","29","Front-wheel drive","Toyota 2.5L 4 Cylinder 179 hp 171 ft-lbs","True","6","6 Speed Automatic Select Shift","22","Gasoline","32","Automatic transmission","2010 Toyota Camry SE AT","Toyota","2010 Toyota Camry","2010","179","171" +"186","198","29","Front-wheel drive","Toyota 3.5L 6 Cylinder 268 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","19","Gasoline","28","Automatic transmission","2010 Toyota Camry SE V6","Toyota","2010 Toyota Camry","2010","268","248" +"191","216","29","Front-wheel drive","Toyota 2.5L 4 Cylinder 169 hp 167 ft-lbs","True","6","6 Speed Automatic Select Shift","22","Gasoline","32","Automatic transmission","2010 Toyota Camry XLE","Toyota","2010 Toyota Camry","2010","169","167" +"191","198","29","Front-wheel drive","Toyota 3.5L 6 Cylinder 268 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","19","Gasoline","28","Automatic transmission","2010 Toyota Camry XLE V6","Toyota","2010 Toyota Camry","2010","268","248" +"247","200","105","Front-wheel drive","Volvo 3.2L 6 Cylinder 235 hp 236 ft-lbs","True","6","6 Speed Automatic","15","Gasoline","22","Automatic transmission","2010 Volvo XC90 R-Design","Volvo","2010 Volvo XC90","2010","235","236" +"247","200","105","Front-wheel drive","Volvo 3.2 L 6 cylinder 240 hp 236 ft-lbs","True","6","6 Speed Automatic","16","Gasoline","22","Automatic transmission","2011 Volvo XC90 R-Design","Volvo","2011 Volvo XC90","2011","240","236" +"175","19","97","All-wheel drive","Volvo 3.0L 6 Cylinder 281 hp 295 ft-lbs Turbo","True","6","6 Speed Automatic","16","Gasoline","21","Automatic transmission","2010 Volvo XC60 T6 R-Design","Volvo","2010 Volvo XC60","2010","281","295" +"175","19","97","All-wheel drive","Volvo 3.0 L 6 Cylinder 300 HP 325 ft-lbs Turbo","True","6","6 Speed Automatic","17","Gasoline","22","Automatic transmission","2011 Volvo XC60 T6 R-Design","Volvo","2011 Volvo XC60","2011","300","325" +"175","19","97","Front-wheel drive","Volvo 3.2 L 6 cylinder 240 hp 236 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","25","Automatic transmission","2011 Volvo XC60 3.2 R-Design","Volvo","2011 Volvo XC60","2011","240","236" +"193","169","234","All-wheel drive","Volvo 2.5L 5 Cylinder 227 hp 236 ft-lbs Turbo","True","5","5 Speed Automatic","20","Gasoline","26","Automatic transmission","2010 Volvo V50 R-Design AT","Volvo","2010 Volvo V50","2010","227","236" +"218","169","234","Front-wheel drive","Volvo 2.5L 5 Cylinder 227 hp 236 ft-lbs Turbo","True","5","5 Speed Automatic","21","Gasoline","30","Automatic transmission","2011 Volvo V50 R-Design","Volvo","2011 Volvo V50","2011","227","236" +"124","198","152","All-wheel drive","Bentley 6.0L 12 Cylinder 567 hp 516 ft-lbs FFV","True","6","6 Speed Automatic Select Shift","8","E85","14","Automatic transmission","2012 Bentley Continental GT","Bentley","2012 Bentley Continental GT","2012","567","516" +"109","195","123","All-wheel drive","Bentley 6.0L 12 cylinder 552 hp 479 ft-lbs Turbo","True","6","6 Speed Automatic","10","Gasoline","17","Automatic transmission","2010 Bentley Continental GT","Bentley","2010 Bentley Continental GT","2010","552","479" +"99","195","123","All-wheel drive","Bentley 6.0L 12 cylinder 600hp 553 ft-lbs Turbo","True","6","6 Speed Automatic","10","Gasoline","17","Automatic transmission","2010 Bentley Continental GT Speed","Bentley","2010 Bentley Continental GT","2010","600","553" +"208","93","188","Front-wheel drive","Ford 2.0L 4 Cylinder 140 hp 136 ft-lbs","True","5","5 Speed Manual","24","Gasoline","35","Manual transmission","2010 Ford Focus Coupe SE","Ford","2010 Ford Focus Coupe","2010","140","136" +"208","93","188","Front-wheel drive","Ford 2.0L 4 Cylinder 140 hp 136 ft-lbs","True","4","4 Speed Automatic","24","Gasoline","34","Automatic transmission","2010 Ford Focus Coupe SE AT","Ford","2010 Ford Focus Coupe","2010","140","136" +"208","93","188","Front-wheel drive","Ford 2.0L 4 Cylinder 140 hp 136 ft-lbs","True","5","5 Speed Manual","24","Gasoline","35","Manual transmission","2010 Ford Focus Coupe SES","Ford","2010 Ford Focus Coupe","2010","140","136" +"208","93","188","Front-wheel drive","Ford 2.0L 4 Cylinder 140 hp 136 ft-lbs","True","4","4 Speed Automatic","24","Gasoline","34","Automatic transmission","2010 Ford Focus Coupe SES AT","Ford","2010 Ford Focus Coupe","2010","140","136" +"109","195","135","All-wheel drive","Bentley 6.0L 12 Cylinder 600 hp 553 ft-lbs FFV Turbo","True","6","6 Speed Automatic","11","Gasoline","18","Automatic transmission","2011 Bentley Continental GTC Speed","Bentley","2011 Bentley Continental GTC","2011","600","553" +"109","195","125","All-wheel drive","Bentley 6.0L 12 cylinder 600hp 553 ft-lbs Turbo","True","6","6 Speed Automatic","10","Gasoline","17","Automatic transmission","2010 Bentley Continental GTC Speed","Bentley","2010 Bentley Continental GTC","2010","600","553" +"117","195","135","All-wheel drive","Bentley 6.0L 12 cylinder 552 hp 479 ft-lbs Turbo","True","6","6 Speed Automatic","10","Gasoline","17","Automatic transmission","2010 Bentley Continental GTC","Bentley","2010 Bentley Continental GTC","2010","552","479" +"210","34","107","Rear-wheel drive","Bentley 6.8L 8 cylinder 500hp 738 ft-lbs Turbo","True","6","6 Speed Automatic","9","Gasoline","15","Automatic transmission","2010 Bentley Azure T","Bentley","2010 Bentley Azure T","2010","500","738" +"186","220","227","Front-wheel drive","Toyota 1.8L 4 Cylinder 132 hp 128 ft-lbs.","True","5","5 Speed Manual","28","Gasoline","35","Manual transmission","2011 Toyota Corolla","Toyota","2011 Toyota Corolla","2011","132","128" +"186","220","227","Front-wheel drive","Toyota 1.8L 4 Cylinder 132 hp 128 ft-lbs.","True","4","4 Speed Automatic Select Shift","26","Gasoline","34","Automatic transmission","2011 Toyota Corolla AT","Toyota","2011 Toyota Corolla","2011","132","128" +"186","220","227","Front-wheel drive","Toyota 1.8L 4 Cylinder 132 hp 128 ft-lbs.","True","4","4 Speed Automatic Select Shift","26","Gasoline","34","Automatic transmission","2011 Toyota Corolla LE","Toyota","2011 Toyota Corolla","2011","132","128" +"186","202","227","Front-wheel drive","Toyota 1.8L 4 Cylinder 132 hp 128 ft-lbs.","True","5","5 Speed Manual","28","Gasoline","35","Manual transmission","2011 Toyota Corolla S","Toyota","2011 Toyota Corolla","2011","132","128" +"186","202","227","Front-wheel drive","Toyota 1.8L 4 Cylinder 132 hp 128 ft-lbs.","True","4","4 Speed Automatic Select Shift","26","Gasoline","34","Automatic transmission","2011 Toyota Corolla S AT","Toyota","2011 Toyota Corolla","2011","132","128" +"13","24","156","Rear-wheel drive","Rolls-Royce 6.6L 12 Cylinder 563 hp 575 ft-lbs","True","8","8 Speed Automatic Select Shift","13","Gasoline","20","Automatic transmission","2010 Rolls-Royce Ghost","Rolls-Royce","2010 Rolls-Royce Ghost","2010","563","575" +"101","14","227","All-wheel drive","Audi 2.0L 4 cylinder 211 hp 258 ft-lbs Turbo","True","8","8 Speed Automatic Select Shift","21","Gasoline","29","Automatic transmission","2011 Audi A5 Cabriolet 2.0 T Quattro","Audi","2011 Audi A5 Cabriolet","2011","211","258" +"103","17","228","All-wheel drive","Audi 2.0L 4 cylinder 211 hp 258 ft-lbs Turbo","True","6","6 Speed Automatic Select Shift","20","Gasoline","26","Automatic transmission","2010 Audi A5 Cabriolet 2.0 T Quattro","Audi","2010 Audi A5 Cabriolet","2010","211","258" +"102","202","196","Rear-wheel drive","Rolls-Royce 6.7L 12 Cylinder 453 hp 531 ft-lbs","True","6","6 Speed Automatic","11","Gasoline","18","Automatic transmission","2010 Rolls-Royce Phantom Sedan","Rolls-Royce","2010 Rolls-Royce Phantom Sedan","2010","453","531" +"104","202","196","Rear-wheel drive","Rolls-Royce 6.7L 12 Cylinder 453 hp 531 ft-lbs","True","6","6 Speed Automatic","11","Gasoline","18","Automatic transmission","2010 Rolls-Royce Phantom Sedan EWB","Rolls-Royce","2010 Rolls-Royce Phantom Sedan","2010","453","531" +"92","17","189","All-wheel drive","Audi 2.0L 4 cylinder 211 hp 258 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","31","Manual transmission","2012 Audi A5 Coupe 2.0 T","Audi","2012 Audi A5 Coupe","2012","211","258" +"92","17","189","All-wheel drive","Audi 2.0L 4 cylinder 211 hp 258 ft-lbs Turbo","True","8","8 Speed Automatic Select Shift","21","Gasoline","29","Automatic transmission","2012 Audi A5 Coupe 2.0 T AT","Audi","2012 Audi A5 Coupe","2012","211","258" +"61","234","194","Rear-wheel drive","Rolls-Royce 6.7L 12 Cylinder 453 hp 531 ft-lbs","True","6","6 Speed Automatic","11","Gasoline","18","Automatic transmission","2010 Rolls-Royce Phantom Coupe","Rolls-Royce","2010 Rolls-Royce Phantom Coupe","2010","453","531" +"92","17","189","All-wheel drive","Audi 2.0L 4 cylinder 211 hp 258 ft-lbs Turbo","True","8","8 Speed Automatic Select Shift","21","Gasoline","29","Automatic transmission","2011 Audi A5 Coupe 2.0 T AT","Audi","2011 Audi A5 Coupe","2011","211","258" +"92","17","189","All-wheel drive","Audi 2.0L 4 cylinder 211 hp 258 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","31","Manual transmission","2011 Audi A5 Coupe 2.0 T","Audi","2011 Audi A5 Coupe","2011","211","258" +"92","17","62","All-wheel drive","Audi 2.0L 4 cylinder 211 hp 258 ft-lbs Turbo","True","6","6 Speed Manual","22","Gasoline","30","Manual transmission","2010 Audi A5 Coupe 2.0 T","Audi","2010 Audi A5 Coupe","2010","211","258" +"92","17","62","All-wheel drive","Audi 3.2L 6 cylinder 265hp 243 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","27","Automatic transmission","2010 Audi A5 Coupe 3.2","Audi","2010 Audi A5 Coupe","2010","265","243" +"92","17","62","All-wheel drive","Audi 2.0L 4 cylinder 211 hp 258 ft-lbs Turbo","True","6","6 Speed Automatic Select Shift","21","Gasoline","27","Automatic transmission","2010 Audi A5 Coupe 2.0 T AT","Audi","2010 Audi A5 Coupe","2010","211","258" +"43","232","194","Rear-wheel drive","Rolls-Royce 6.7L 12 Cylinder 453 hp 531 ft-lbs","True","6","6 Speed Automatic","11","Gasoline","18","Automatic transmission","2010 Rolls-Royce Phantom Drophead Coupe","Rolls-Royce","2010 Rolls-Royce Phantom Drophead Coupe","2010","453","531" +"13","24","156","Rear-wheel drive","Rolls-Royce 6.6L 12 Cylinder 563 hp 575 ft-lbs","True","8","8 Speed Automatic Select Shift","13","Gasoline","20","Automatic transmission","2011 Rolls-Royce Ghost","Rolls-Royce","2011 Rolls-Royce Ghost","2011","563","575" +"195","71","54","Front-wheel drive","Honda 3.5L 6 Cylinder 271 hp 254 ft-lbs","True","5","5 Speed Automatic","19","Gasoline","29","Automatic transmission","2010 Honda Accord EX-L V-6 Sedan","Honda","2010 Honda Accord Sedan","2010","271","254" +"102","207","196","Rear-wheel drive","Rolls-Royce 6.7L 12 Cylinder 453 hp 531 ft-lbs","True","6","6 Speed Automatic","11","Gasoline","18","Automatic transmission","2011 Rolls-Royce Phantom Sedan","Rolls-Royce","2011 Rolls-Royce Phantom Sedan","2011","453","531" +"195","86","54","Front-wheel drive","Honda 2.4L 4 cylinder 177 hp 161 ft-lbs","True","5","5 Speed Manual","23","Gasoline","33","Manual transmission","2011 Honda Accord LX Sedan","Honda","2011 Honda Accord Sedan","2011","177","161" +"195","86","54","Front-wheel drive","Honda 2.4L 4 cylinder 177 hp 161 ft-lbs","True","5","5 Speed Automatic","23","Gasoline","34","Automatic transmission","2011 Honda Accord LX Sedan AT","Honda","2011 Honda Accord Sedan","2011","177","161" +"195","86","54","Front-wheel drive","Honda 2.4L 4 cylinder 177 hp 161 ft-lbs","True","5","5 Speed Automatic","23","Gasoline","34","Automatic transmission","2011 Honda Accord LX-P Sedan","Honda","2011 Honda Accord Sedan","2011","177","161" +"195","86","54","Front-wheel drive","Honda 2.4L 4 cylinder 177 hp 161 ft-lbs","True","5","5 Speed Automatic","23","Gasoline","34","Automatic transmission","2011 Honda Accord SE Sedan","Honda","2011 Honda Accord Sedan","2011","177","161" +"195","86","54","Front-wheel drive","Honda 2.4L 4 cylinder 190 hp 162 ft-lbs","True","5","5 Speed Manual","23","Gasoline","33","Manual transmission","2011 Honda Accord EX Sedan","Honda","2011 Honda Accord Sedan","2011","190","162" +"195","86","54","Front-wheel drive","Honda 2.4L 4 cylinder 190 hp 162 ft-lbs","True","5","5 Speed Automatic","23","Gasoline","34","Automatic transmission","2011 Honda Accord EX Sedan AT","Honda","2011 Honda Accord Sedan","2011","190","162" +"195","86","54","Front-wheel drive","Honda 3.5L 6 Cylinder 271 hp 254 ft-lbs","True","5","5 Speed Automatic","20","Gasoline","30","Automatic transmission","2011 Honda Accord EX V-6 Sedan","Honda","2011 Honda Accord Sedan","2011","271","254" +"195","86","54","Front-wheel drive","Honda 2.4L 4 cylinder 190 hp 162 ft-lbs","True","5","5 Speed Automatic","23","Gasoline","34","Automatic transmission","2011 Honda Accord EX-L Sedan","Honda","2011 Honda Accord Sedan","2011","190","162" +"195","86","54","Front-wheel drive","Honda 3.5L 6 Cylinder 271 hp 254 ft-lbs","True","5","5 Speed Automatic","20","Gasoline","30","Automatic transmission","2011 Honda Accord EX-L V-6 Sedan","Honda","2011 Honda Accord Sedan","2011","271","254" +"102","202","196","Rear-wheel drive","Rolls-Royce 6.7L 12 Cylinder 453 hp 531 ft-lbs","True","6","6 Speed Automatic","11","Gasoline","18","Automatic transmission","2011 Rolls-Royce Phantom Sedan EWB","Rolls-Royce","2011 Rolls-Royce Phantom Sedan","2011","453","531" +"61","234","194","Rear-wheel drive","Rolls-Royce 6.7L 12 Cylinder 453 hp 531 ft-lbs","True","6","6 Speed Automatic","11","Gasoline","18","Automatic transmission","2011 Rolls-Royce Phantom Coupe","Rolls-Royce","2011 Rolls-Royce Phantom Coupe","2011","453","531" +"43","232","194","Rear-wheel drive","Rolls-Royce 6.7L 12 Cylinder 453 hp 531 ft-lbs","True","6","6 Speed Automatic","11","Gasoline","18","Automatic transmission","2011 Rolls-Royce Phantom Drophead Coupe","Rolls-Royce","2011 Rolls-Royce Phantom Drophead Coupe","2011","453","531" +"172","19","242","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","5","5 Speed Manual","23","Gasoline","33","Manual transmission","2011 Volkswagen Jetta SEL PZEV","Volkswagen","2011 Volkswagen Jetta","2011","170","177" +"172","19","242","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","6","6 Speed Automatic","24","Gasoline","31","Automatic transmission","2011 Volkswagen Jetta SE PZEV AT","Volkswagen","2011 Volkswagen Jetta","2011","170","177" +"172","19","242","Front-wheel drive","Volkswagen 2.0L 4 Cylinder 115 hp 125 ft-lbs","True","6","6 Speed Automatic","23","Gasoline","29","Automatic transmission","2011 Volkswagen Jetta AT","Volkswagen","2011 Volkswagen Jetta","2011","115","125" +"172","19","242","Front-wheel drive","Volkswagen 2.0L 4 Cylinder 115 hp 125 ft-lbs","True","6","6 Speed Automatic","23","Gasoline","29","Automatic transmission","2011 Volkswagen Jetta S AT","Volkswagen","2011 Volkswagen Jetta","2011","115","125" +"172","19","242","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","6","6 Speed Automatic","24","Gasoline","31","Automatic transmission","2011 Volkswagen Jetta SE AT","Volkswagen","2011 Volkswagen Jetta","2011","170","177" +"172","19","242","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","6","6 Speed Automatic","24","Gasoline","31","Automatic transmission","2011 Volkswagen Jetta SEL PZEV AT","Volkswagen","2011 Volkswagen Jetta","2011","170","177" +"172","19","242","Front-wheel drive","Volkswagen 2.0L 4 Cylinder 115 hp 125 ft-lbs","True","5","5 Speed Manual","24","Gasoline","34","Manual transmission","2011 Volkswagen Jetta","Volkswagen","2011 Volkswagen Jetta","2011","115","125" +"172","19","242","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","6","6 Speed Automatic","24","Gasoline","31","Automatic transmission","2011 Volkswagen Jetta SEL AT","Volkswagen","2011 Volkswagen Jetta","2011","170","177" +"172","19","242","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","5","5 Speed Manual","23","Gasoline","33","Manual transmission","2011 Volkswagen Jetta SE","Volkswagen","2011 Volkswagen Jetta","2011","170","177" +"172","19","242","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","5","5 Speed Manual","23","Gasoline","33","Manual transmission","2011 Volkswagen Jetta SEL","Volkswagen","2011 Volkswagen Jetta","2011","170","177" +"172","19","242","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","5","5 Speed Manual","23","Gasoline","33","Manual transmission","2011 Volkswagen Jetta SE PZEV","Volkswagen","2011 Volkswagen Jetta","2011","170","177" +"172","19","242","Front-wheel drive","Volkswagen 2.0L 4 Cylinder 115 hp 125 ft-lbs","True","5","5 Speed Manual","24","Gasoline","34","Manual transmission","2011 Volkswagen Jetta S","Volkswagen","2011 Volkswagen Jetta","2011","115","125" +"186","187","224","Front-wheel drive","Toyota 1.8L 4 Cylinder 132 hp 128 ft-lbs.","True","5","5 Speed Manual","26","Gasoline","35","Manual transmission","2010 Toyota Corolla","Toyota","2010 Toyota Corolla","2010","132","128" +"186","187","224","Front-wheel drive","Toyota 1.8L 4 Cylinder 132 hp 128 ft-lbs.","True","4","4 Speed Automatic","26","Gasoline","34","Automatic transmission","2010 Toyota Corolla AT","Toyota","2010 Toyota Corolla","2010","132","128" +"186","187","224","Front-wheel drive","Toyota 1.8L 4 Cylinder 132 hp 128 ft-lbs.","True","5","5 Speed Manual","26","Gasoline","35","Manual transmission","2010 Toyota Corolla S","Toyota","2010 Toyota Corolla","2010","132","128" +"186","187","224","Front-wheel drive","Toyota 1.8L 4 Cylinder 132 hp 128 ft-lbs.","True","4","4 Speed Automatic","26","Gasoline","34","Automatic transmission","2010 Toyota Corolla S AT","Toyota","2010 Toyota Corolla","2010","132","128" +"186","187","224","Front-wheel drive","Toyota 1.8L 4 Cylinder 132 hp 128 ft-lbs.","True","4","4 Speed Automatic","26","Gasoline","34","Automatic transmission","2010 Toyota Corolla LE","Toyota","2010 Toyota Corolla","2010","132","128" +"186","187","224","Front-wheel drive","Toyota 1.8L 4 Cylinder 132 hp 128 ft-lbs.","True","4","4 Speed Automatic","26","Gasoline","34","Automatic transmission","2010 Toyota Corolla XLE","Toyota","2010 Toyota Corolla","2010","132","128" +"186","187","224","Front-wheel drive","Toyota 2.4L 4 Cylinder 158 hp 162 ft-lbs.","True","5","5 Speed Manual","22","Gasoline","30","Manual transmission","2010 Toyota Corolla XRS","Toyota","2010 Toyota Corolla","2010","158","162" +"186","187","224","Front-wheel drive","Toyota 2.4L 4 Cylinder 158 hp 162 ft-lbs.","True","5","5 Speed Automatic Select Shift","22","Gasoline","30","Automatic transmission","2010 Toyota Corolla XRS AT","Toyota","2010 Toyota Corolla","2010","158","162" +"19","63","113","Rear-wheel drive","Toyota 4.0L 6 Cylinder 260 hp 271 ft-lbs","True","5","5 Speed Automatic","17","Gasoline","22","Automatic transmission","2011 Toyota FJ Cruiser","Toyota","2011 Toyota FJ Cruiser","2011","260","271" +"37","63","113","Four-wheel drive","Toyota 4.0L 6 Cylinder 260 hp 271 ft-lbs","True","6","6 Speed Manual","15","Gasoline","20","Manual transmission","2011 Toyota FJ Cruiser 4WD","Toyota","2011 Toyota FJ Cruiser","2011","260","271" +"37","63","113","Four-wheel drive","Toyota 4.0L 6 Cylinder 260 hp 271 ft-lbs","True","5","5 Speed Automatic","17","Gasoline","21","Automatic transmission","2011 Toyota FJ Cruiser 4WD AT","Toyota","2011 Toyota FJ Cruiser","2011","260","271" +"188","61","82","All-wheel drive","Audi 3.0L 6 Cylinder 310 hp 325 ft-lbs","True","8","8 Speed Automatic Select Shift","19","Gasoline","28","Automatic transmission","2012 Audi A6 Sedan 3.0 T","Audi","2012 Audi A6 Sedan","2012","310","325" +"179","63","237","All-wheel drive","Audi 3.0L 6 Cylinder 300 hp 310 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","26","Automatic transmission","2011 Audi A6 Sedan 3.0 T","Audi","2011 Audi A6 Sedan","2011","300","310" +"177","202","244","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","6","6 Speed Automatic","23","Gasoline","30","Automatic transmission","2010 Volkswagen Jetta SE AT","Volkswagen","2010 Volkswagen Jetta","2010","170","177" +"177","202","244","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","6","6 Speed Automatic","23","Gasoline","30","Automatic transmission","2010 Volkswagen Jetta S AT","Volkswagen","2010 Volkswagen Jetta","2010","170","177" +"177","202","244","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","6","6 Speed Automatic","23","Gasoline","30","Automatic transmission","2010 Volkswagen Jetta SE PZEV AT","Volkswagen","2010 Volkswagen Jetta","2010","170","177" +"177","202","244","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","5","5 Speed Manual","22","Gasoline","30","Manual transmission","2010 Volkswagen Jetta Limited Edition","Volkswagen","2010 Volkswagen Jetta","2010","170","177" +"177","202","244","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","5","5 Speed Manual","22","Gasoline","30","Manual transmission","2010 Volkswagen Jetta S","Volkswagen","2010 Volkswagen Jetta","2010","170","177" +"177","202","244","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","6","6 Speed Automatic","23","Gasoline","30","Automatic transmission","2010 Volkswagen Jetta Limited Edition AT","Volkswagen","2010 Volkswagen Jetta","2010","170","177" +"177","202","244","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","6","6 Speed Automatic","23","Gasoline","30","Automatic transmission","2010 Volkswagen Jetta S PZEV AT","Volkswagen","2010 Volkswagen Jetta","2010","170","177" +"177","202","244","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","5","5 Speed Manual","22","Gasoline","30","Manual transmission","2010 Volkswagen Jetta S PZEV","Volkswagen","2010 Volkswagen Jetta","2010","170","177" +"177","202","244","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","6","6 Speed Automatic","23","Gasoline","30","Automatic transmission","2010 Volkswagen Jetta Limited Edition PZEV AT","Volkswagen","2010 Volkswagen Jetta","2010","170","177" +"177","202","244","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","5","5 Speed Manual","22","Gasoline","30","Manual transmission","2010 Volkswagen Jetta Sedan SE PZEV","Volkswagen","2010 Volkswagen Jetta","2010","170","177" +"177","202","244","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","5","5 Speed Manual","22","Gasoline","30","Manual transmission","2010 Volkswagen Jetta SE","Volkswagen","2010 Volkswagen Jetta","2010","170","177" +"177","202","244","Front-wheel drive","Volkswagen 2.0L 4 Cylinder 200 hp 207 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","31","Manual transmission","2010 Volkswagen Jetta Wolfsburg Edition","Volkswagen","2010 Volkswagen Jetta","2010","200","207" +"177","202","244","Front-wheel drive","Volkswagen 2.0L 4 Cylinder 200 hp 207 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","31","Manual transmission","2010 Volkswagen Jetta Wolfsburg Edition PZEV","Volkswagen","2010 Volkswagen Jetta","2010","200","207" +"177","202","244","Front-wheel drive","Volkswagen 2.0L 4 Cylinder 140 hp 236 ft-lbs Turbo Diesel","True","6","6 Speed Manual","30","Gasoline","41","Manual transmission","2010 Volkswagen Jetta TDI Clean Diesel","Volkswagen","2010 Volkswagen Jetta","2010","140","236" +"177","202","244","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","6","6 Speed Automatic","23","Gasoline","30","Automatic transmission","2010 Volkswagen Jetta SEL PZEV AT","Volkswagen","2010 Volkswagen Jetta","2010","170","177" +"177","202","244","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","6","6 Speed Automatic","23","Gasoline","30","Automatic transmission","2010 Volkswagen Jetta SEL AT","Volkswagen","2010 Volkswagen Jetta","2010","170","177" +"177","202","244","Front-wheel drive","Volkswagen 2.0L 4 Cylinder 140 hp 236 ft-lbs Turbo Diesel","True","6","6 Speed Manual","30","Gasoline","41","Manual transmission","2010 Volkswagen Jetta TDI Cup Edition","Volkswagen","2010 Volkswagen Jetta","2010","140","236" +"19","63","113","Rear-wheel drive","Toyota 4.0L 6 Cylinder 260 hp 271 ft-lbs","True","5","5 Speed Automatic","17","Gasoline","22","Automatic transmission","2010 Toyota FJ Cruiser","Toyota","2010 Toyota FJ Cruiser","2010","260","271" +"37","63","113","Four-wheel drive","Toyota 4.0L 6 Cylinder 260 hp 271 ft-lbs","True","6","6 Speed Manual","15","Gasoline","19","Manual transmission","2010 Toyota FJ Cruiser 4WD","Toyota","2010 Toyota FJ Cruiser","2010","260","271" +"37","63","113","Four-wheel drive","Toyota 4.0L 6 Cylinder 260 hp 271 ft-lbs","True","5","5 Speed Automatic","17","Gasoline","21","Automatic transmission","2010 Toyota FJ Cruiser 4WD AT","Toyota","2010 Toyota FJ Cruiser","2010","260","271" +"194","177","118","Front-wheel drive","Toyota 2.7L 4 Cylinder 187 hp 186 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","25","Automatic transmission","2011 Toyota Highlander","Toyota","2011 Toyota Highlander","2011","187","186" +"194","177","118","Front-wheel drive","Toyota 3.5L 6 Cylinder 270 hp 248 ft-lbs.","True","6","6 Speed Automatic Select Shift","20","Gasoline","25","Automatic transmission","2011 Toyota Highlander V6","Toyota","2011 Toyota Highlander","2011","270","248" +"194","177","118","Four-wheel drive","Toyota 3.5L 6 Cylinder 270 hp 248 ft-lbs.","True","5","5 Speed Automatic Select Shift","17","Gasoline","22","Automatic transmission","2011 Toyota Highlander V6 4WD","Toyota","2011 Toyota Highlander","2011","270","248" +"224","177","118","Front-wheel drive","Toyota 2.7L 4 Cylinder 187 hp 186 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","25","Automatic transmission","2011 Toyota Highlander SE","Toyota","2011 Toyota Highlander","2011","187","186" +"224","177","118","Front-wheel drive","Toyota 3.5L 6 Cylinder 270 hp 248 ft-lbs.","True","5","5 Speed Automatic Select Shift","18","Gasoline","24","Automatic transmission","2011 Toyota Highlander SE V6","Toyota","2011 Toyota Highlander","2011","270","248" +"224","177","118","Four-wheel drive","Toyota 3.5L 6 Cylinder 270 hp 248 ft-lbs.","True","5","5 Speed Automatic Select Shift","17","Gasoline","22","Automatic transmission","2011 Toyota Highlander SE V6 4WD","Toyota","2011 Toyota Highlander","2011","270","248" +"224","177","118","Front-wheel drive","Toyota 3.5L 6 Cylinder 270 hp 248 ft-lbs.","True","5","5 Speed Automatic Select Shift","18","Gasoline","24","Automatic transmission","2011 Toyota Highlander Limited","Toyota","2011 Toyota Highlander","2011","270","248" +"224","177","118","Four-wheel drive","Toyota 3.5L 6 Cylinder 270 hp 248 ft-lbs.","True","5","5 Speed Automatic Select Shift","17","Gasoline","22","Automatic transmission","2011 Toyota Highlander Limited 4WD","Toyota","2011 Toyota Highlander","2011","270","248" +"194","177","118","Front-wheel drive","Toyota 2.7L 4 Cylinder 187 hp 186 ft-lbs","True","6","6 Speed Automatic","20","Gasoline","27","Automatic transmission","2010 Toyota Highlander","Toyota","2010 Toyota Highlander","2010","187","186" +"194","177","118","Front-wheel drive","Toyota 3.5L 6 Cylinder 270 hp 248 ft-lbs.","True","5","5 Speed Automatic Select Shift","18","Gasoline","24","Automatic transmission","2010 Toyota Highlander V6","Toyota","2010 Toyota Highlander","2010","270","248" +"194","177","118","Four-wheel drive","Toyota 3.5L 6 Cylinder 270 hp 248 ft-lbs.","True","5","5 Speed Automatic Select Shift","17","Gasoline","23","Automatic transmission","2010 Toyota Highlander V6 4WD","Toyota","2010 Toyota Highlander","2010","270","248" +"224","177","118","Front-wheel drive","Toyota 3.5L 6 Cylinder 270 hp 248 ft-lbs.","True","5","5 Speed Automatic Select Shift","18","Gasoline","24","Automatic transmission","2010 Toyota Highlander Sport","Toyota","2010 Toyota Highlander","2010","270","248" +"224","177","118","Four-wheel drive","Toyota 3.5L 6 Cylinder 270 hp 248 ft-lbs.","True","5","5 Speed Automatic Select Shift","17","Gasoline","23","Automatic transmission","2010 Toyota Highlander Sport 4WD","Toyota","2010 Toyota Highlander","2010","270","248" +"224","177","118","Front-wheel drive","Toyota 3.5L 6 Cylinder 270 hp 248 ft-lbs.","True","5","5 Speed Automatic Select Shift","18","Gasoline","24","Automatic transmission","2010 Toyota Highlander SE","Toyota","2010 Toyota Highlander","2010","270","248" +"224","177","118","Four-wheel drive","Toyota 3.5L 6 Cylinder 270 hp 248 ft-lbs.","True","5","5 Speed Automatic Select Shift","17","Gasoline","23","Automatic transmission","2010 Toyota Highlander SE 4WD","Toyota","2010 Toyota Highlander","2010","270","248" +"224","177","118","Front-wheel drive","Toyota 3.5L 6 Cylinder 270 hp 248 ft-lbs.","True","5","5 Speed Automatic Select Shift","18","Gasoline","24","Automatic transmission","2010 Toyota Highlander Limited","Toyota","2010 Toyota Highlander","2010","270","248" +"224","177","118","Four-wheel drive","Toyota 3.5L 6 Cylinder 270 hp 248 ft-lbs.","True","5","5 Speed Automatic Select Shift","17","Gasoline","23","Automatic transmission","2010 Toyota Highlander Limited 4WD","Toyota","2010 Toyota Highlander","2010","270","248" +"132","134","105","Front-wheel drive","Honda 3.5L 6 Cylinder 271 hp 254 ft-lbs","True","5","5 Speed Automatic","18","Gasoline","27","Automatic transmission","2011 Honda Accord Crosstour EX Hatchback","Honda","2011 Honda Accord Crosstour Hatchback","2011","271","254" +"132","134","105","Front-wheel drive","Honda 3.5L 6 Cylinder 271 hp 254 ft-lbs","True","5","5 Speed Automatic","18","Gasoline","27","Automatic transmission","2011 Honda Accord Crosstour EX-L Hatchback","Honda","2011 Honda Accord Crosstour Hatchback","2011","271","254" +"132","134","105","Four-wheel drive","Honda 3.5L 6 Cylinder 271 hp 254 ft-lbs","True","5","5 Speed Automatic","18","Gasoline","26","Automatic transmission","2011 Honda Accord Crosstour EX-L Hatchback 4WD","Honda","2011 Honda Accord Crosstour Hatchback","2011","271","254" +"88","87","179","Four-wheel drive","Toyota 5.7L 8 Cylinder 381 hp 401 ft-lbs","True","6","6 Speed Automatic Select Shift","13","Gasoline","18","Automatic transmission","2011 Toyota Land Cruiser","Toyota","2011 Toyota Land Cruiser","2011","381","401" +"88","87","179","Four-wheel drive","Toyota 5.7L 8 Cylinder 381 hp 401 ft-lbs","True","6","6 Speed Automatic Select Shift","13","Gasoline","18","Automatic transmission","2010 Toyota Land Cruiser","Toyota","2010 Toyota Land Cruiser","2010","381","401" +"13","14","229","Front-wheel drive","Toyota 1.8L 4 Cylinder 132 hp 128 ft-lbs.","True","5","5 Speed Manual","26","Gasoline","32","Manual transmission","2011 Toyota Matrix","Toyota","2011 Toyota Matrix","2011","132","128" +"13","14","229","Front-wheel drive","Toyota 1.8L 4 Cylinder 132 hp 128 ft-lbs.","True","4","4 Speed Automatic","25","Gasoline","32","Automatic transmission","2011 Toyota Matrix AT","Toyota","2011 Toyota Matrix","2011","132","128" +"13","14","229","Front-wheel drive","Toyota 2.4L 4 Cylinder 158 hp 162 ft-lbs.","True","5","5 Speed Manual","21","Gasoline","28","Manual transmission","2011 Toyota Matrix S","Toyota","2011 Toyota Matrix","2011","158","162" +"13","14","229","Front-wheel drive","Toyota 2.4L 4 Cylinder 158 hp 162 ft-lbs.","True","5","5 Speed Automatic Select Shift","21","Gasoline","29","Automatic transmission","2011 Toyota Matrix S AT","Toyota","2011 Toyota Matrix","2011","158","162" +"24","14","229","All-wheel drive","Toyota 2.4L 4 Cylinder 158 hp 162 ft-lbs.","True","4","4 Speed Automatic","20","Gasoline","26","Automatic transmission","2011 Toyota Matrix S AT AWD","Toyota","2011 Toyota Matrix","2011","158","162" +"38","95","189","Rear-wheel drive","Maybach 6.0L 12 Cylinder 631 hp 738 ft-lbs Turbo","True","5","5 Speed Automatic Select Shift","10","Gasoline","16","Automatic transmission","2010 Maybach 57 Zeppelin","Maybach","2010 Maybach 57","2010","631","738" +"38","95","189","Rear-wheel drive","Maybach 5.5L 12 Cylinder 543 hp 664 ft-lbs Turbo","True","5","5 Speed Automatic Select Shift","10","Gasoline","16","Automatic transmission","2010 Maybach 57","Maybach","2010 Maybach 57","2010","543","664" +"1","95","189","Rear-wheel drive","Maybach 6.0L 12 Cylinder 604 hp 738 ft-lbs Turbo","True","5","5 Speed Automatic Select Shift","10","Gasoline","16","Automatic transmission","2010 Maybach 57 S","Maybach","2010 Maybach 57","2010","604","738" +"38","95","189","Rear-wheel drive","Maybach 6.0L 12 Cylinder 631 hp 738 ft-lbs Turbo","True","5","5 Speed Automatic Select Shift","10","Gasoline","16","Automatic transmission","2010 Maybach 57 Zeppelin","Maybach","2010 Maybach 57","2011","631","738" +"1","95","189","Rear-wheel drive","Maybach 6.0L 12 Cylinder 620 hp 738 ft-lbs Turbo","True","5","5 Speed Automatic Select Shift","10","Gasoline","16","Automatic transmission","2011 Maybach 57 S","Maybach","2011 Maybach 57","2011","620","738" +"38","20","189","Rear-wheel drive","Maybach 5.5L 12 Cylinder 543 hp 664 ft-lbs Turbo","True","5","5 Speed Automatic Select Shift","10","Gasoline","16","Automatic transmission","2010 Maybach 62","Maybach","2010 Maybach 62","2010","543","664" +"38","20","189","Rear-wheel drive","Maybach 6.0L 12 Cylinder 604 hp 738 ft-lbs Turbo","True","5","5 Speed Automatic Select Shift","10","Gasoline","16","Automatic transmission","2010 Maybach 62 S","Maybach","2010 Maybach 62","2010","604","738" +"38","20","189","Rear-wheel drive","Maybach 6.0L 12 Cylinder 631 hp 738 ft-lbs Turbo","True","5","5 Speed Automatic Select Shift","10","Gasoline","16","Automatic transmission","2010 Maybach 62 Zeppelin","Maybach","2010 Maybach 62","2010","631","738" +"38","20","189","Rear-wheel drive","Maybach 6.0L 12 Cylinder 620 hp 738 ft-lbs Turbo","True","5","5 Speed Automatic Select Shift","10","Gasoline","16","Automatic transmission","2011 Maybach 62 S","Maybach","2011 Maybach 62","2011","620","738" +"38","20","189","Rear-wheel drive","Maybach 5.5L 12 Cylinder 543 hp 664 ft-lbs Turbo","True","5","5 Speed Automatic Select Shift","10","Gasoline","16","Automatic transmission","2011 Maybach 62","Maybach","2011 Maybach 62","2011","543","664" +"38","20","189","Rear-wheel drive","Maybach 6.0L 12 Cylinder 604 hp 738 ft-lbs Turbo","True","5","5 Speed Automatic Select Shift","10","Gasoline","16","Automatic transmission","2009 Maybach Landaulet","Maybach","2009 Maybach Landaulet","2009","604","738" +"38","20","189","Rear-wheel drive","Maybach 6.0L 12 Cylinder 604 hp 738 ft-lbs Turbo","True","5","5 Speed Automatic Select Shift","10","Gasoline","16","Automatic transmission","2010 Maybach Landaulet","Maybach","2010 Maybach Landaulet","2010","604","738" +"38","20","189","Rear-wheel drive","Maybach 6.0L 12 Cylinder 620 hp 738 ft-lbs Turbo","True","5","5 Speed Automatic Select Shift","10","Gasoline","16","Automatic transmission","2011 Maybach Landaulet","Maybach","2011 Maybach Landaulet","2011","620","738" +"13","14","229","Front-wheel drive","Toyota 1.8L 4 Cylinder 132 hp 128 ft-lbs.","True","5","5 Speed Manual","26","Gasoline","32","Manual transmission","2010 Toyota Matrix","Toyota","2010 Toyota Matrix","2010","132","128" +"13","14","229","Front-wheel drive","Toyota 1.8L 4 Cylinder 132 hp 128 ft-lbs.","True","4","4 Speed Automatic","25","Gasoline","31","Automatic transmission","2010 Toyota Matrix AT","Toyota","2010 Toyota Matrix","2010","132","128" +"13","42","229","Front-wheel drive","Toyota 2.4L 4 Cylinder 158 hp 162 ft-lbs.","True","5","5 Speed Manual","21","Gasoline","28","Manual transmission","2010 Toyota Matrix S","Toyota","2010 Toyota Matrix","2010","158","162" +"13","42","229","Front-wheel drive","Toyota 2.4L 4 Cylinder 158 hp 162 ft-lbs.","True","5","5 Speed Automatic Select Shift","21","Gasoline","29","Automatic transmission","2010 Toyota Matrix S AT","Toyota","2010 Toyota Matrix","2010","158","162" +"24","42","229","All-wheel drive","Toyota 2.4L 4 Cylinder 158 hp 162 ft-lbs.","True","4","4 Speed Automatic","20","Gasoline","26","Automatic transmission","2010 Toyota Matrix S AT AWD","Toyota","2010 Toyota Matrix","2010","158","162" +"23","42","229","Front-wheel drive","Toyota 2.4L 4 Cylinder 158 hp 162 ft-lbs.","True","5","5 Speed Manual","21","Gasoline","28","Manual transmission","2010 Toyota Matrix XRS","Toyota","2010 Toyota Matrix","2010","158","162" +"23","42","229","Front-wheel drive","Toyota 2.4L 4 Cylinder 158 hp 162 ft-lbs.","True","5","5 Speed Automatic Select Shift","21","Gasoline","29","Automatic transmission","2010 Toyota Matrix XRS AT","Toyota","2010 Toyota Matrix","2010","158","162" +"13","14","229","Front-wheel drive","Toyota 1.8L 4 Cylinder 132 hp 128 ft-lbs.","True","4","4 Speed Automatic","25","Gasoline","31","Automatic transmission","2010 Toyota Matrix AT","Nissan","2010 Toyota Matrix","2010","132","128" +"189","155","222","Four-wheel drive","Nissan 5.6L 8 Cylinder 317 hp 385 ft-lbs FFV","True","5","5 Speed Automatic","12","Gasoline","18","Automatic transmission","2011 Nissan Armada SV 4x4 FFV","Nissan","2011 Nissan Armada","2011","317","385" +"189","155","222","Four-wheel drive","Nissan 5.6L 8 Cylinder 317 hp 385 ft-lbs FFV","True","5","5 Speed Automatic","12","Gasoline","18","Automatic transmission","2011 Nissan Armada Platinum 4x4","Nissan","2011 Nissan Armada","2011","317","385" +"189","155","222","Four-wheel drive","Nissan 5.6L 8 Cylinder 317 hp 385 ft-lbs FFV","True","5","5 Speed Automatic","12","Gasoline","18","Automatic transmission","2011 Nissan Armada SL 4x4 FFV","Nissan","2011 Nissan Armada","2011","317","385" +"168","155","222","Rear-wheel drive","Nissan 5.6L 8 Cylinder 317 hp 385 ft-lbs","True","5","5 Speed Automatic","13","Gasoline","19","Automatic transmission","2011 Nissan Armada Platinum","Nissan","2011 Nissan Armada","2011","317","385" +"168","155","222","Rear-wheel drive","Nissan 5.6L 8 Cylinder 317 hp 385 ft-lbs FFV","True","5","5 Speed Automatic","12","Gasoline","18","Automatic transmission","2011 Nissan Armada SV FFV","Nissan","2011 Nissan Armada","2011","317","385" +"168","155","222","Rear-wheel drive","Nissan 5.6L 8 Cylinder 317 hp 385 ft-lbs FFV","True","5","5 Speed Automatic","12","Gasoline","18","Automatic transmission","2011 Nissan Armada SL FFV","Nissan","2011 Nissan Armada","2011","317","385" +"223","204","244","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","5","5 Speed Manual","23","Gasoline","33","Manual transmission","2011 Volkswagen Jetta SportWagen S PZEV","Volkswagen","2011 Volkswagen Jetta SportWagen","2011","170","177" +"223","204","244","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","6","6 Speed Automatic","24","Gasoline","31","Automatic transmission","2011 Volkswagen Jetta SportWagen S PZEV AT","Volkswagen","2011 Volkswagen Jetta SportWagen","2011","170","177" +"223","204","244","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","5","5 Speed Manual","23","Gasoline","33","Manual transmission","2011 Volkswagen Jetta SportWagen S","Volkswagen","2011 Volkswagen Jetta SportWagen","2011","170","177" +"223","204","244","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","6","6 Speed Automatic","24","Gasoline","31","Automatic transmission","2011 Volkswagen Jetta SportWagen S AT","Volkswagen","2011 Volkswagen Jetta SportWagen","2011","170","177" +"223","204","244","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","6","6 Speed Automatic","24","Gasoline","31","Automatic transmission","2011 Volkswagen Jetta SportWagen SE","Volkswagen","2011 Volkswagen Jetta SportWagen","2011","170","177" +"223","204","244","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","6","6 Speed Automatic","24","Gasoline","31","Automatic transmission","2011 Volkswagen Jetta SportWagen SE PZEV","Volkswagen","2011 Volkswagen Jetta SportWagen","2011","170","177" +"223","204","244","Front-wheel drive","Volkswagen 2.0L 4 Cylinder 140 hp 236 ft-lbs Turbo Diesel","True","6","6 Speed Manual","30","Gasoline","42","Manual transmission","2011 Volkswagen Jetta SportWagen TDI Clean Diesel","Volkswagen","2011 Volkswagen Jetta SportWagen","2011","140","236" +"226","214","173","Front-wheel drive","Chevrolet 1.6L 4 Cylinder 108 hp 105 ft-lbs","True","5","5 Speed Manual","27","Gasoline","35","Manual transmission","2011 Chevrolet Aveo LS","Chevrolet","2011 Chevrolet Aveo","2011","108","105" +"226","214","173","Front-wheel drive","Chevrolet 1.6L 4 Cylinder 108 hp 105 ft-lbs","True","5","5 Speed Manual","27","Gasoline","35","Manual transmission","2011 Chevrolet Aveo 1LT","Chevrolet","2011 Chevrolet Aveo","2011","108","105" +"226","214","173","Front-wheel drive","Chevrolet 1.6L 4 Cylinder 108 hp 105 ft-lbs","True","4","4 Speed Automatic","25","Gasoline","34","Automatic transmission","2011 Chevrolet Aveo 1LT AT","Chevrolet","2011 Chevrolet Aveo","2011","108","105" +"226","214","173","Front-wheel drive","Chevrolet 1.6L 4 Cylinder 108 hp 105 ft-lbs","True","5","5 Speed Manual","27","Gasoline","35","Manual transmission","2011 Chevrolet Aveo 2LT","Chevrolet","2011 Chevrolet Aveo","2011","108","105" +"226","214","173","Front-wheel drive","Chevrolet 1.6L 4 Cylinder 108 hp 105 ft-lbs","True","4","4 Speed Automatic","25","Gasoline","34","Automatic transmission","2011 Chevrolet Aveo 2LT AT","Chevrolet","2011 Chevrolet Aveo","2011","108","105" +"137","215","62","Front-wheel drive","Volkswagen 2.0L 4 Cylinder 200 hp 207 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","31","Manual transmission","2010 Volkswagen CC Sport PZEV","Volkswagen","2010 Volkswagen CC","2010","200","207" +"137","190","62","Front-wheel drive","Volkswagen 2.0L 4 Cylinder 200 hp 207 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","31","Manual transmission","2010 Volkswagen CC Sport","Volkswagen","2010 Volkswagen CC","2010","200","207" +"137","190","62","Front-wheel drive","Volkswagen 3.6L 6 Cylinder 280 hp 265 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","27","Automatic transmission","2010 Volkswagen CC VR6 Sport","Volkswagen","2010 Volkswagen CC","2010","280","265" +"137","190","62","Front-wheel drive","Volkswagen 3.6L 6 Cylinder 280 hp 265 ft-lbs","True","6","6 Speed Automatic","17","Gasoline","25","Automatic transmission","2010 Volkswagen CC VR6 4Motion Executive","Volkswagen","2010 Volkswagen CC","2010","280","265" +"179","52","237","All-wheel drive","Audi 4.2L 8 cylinder 350 hp 325 ft-lbs","True","6","6 Speed Automatic Select Shift","16","Gasoline","24","Automatic transmission","2011 Audi A6 Sedan 4.2","Audi","2011 Audi A6 Sedan","2011","350","325" +"179","52","220","All-wheel drive","Audi 3.0L 6 Cylinder 300 hp 310 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","26","Automatic transmission","2010 Audi A6 Sedan 3.0 T","Audi","2010 Audi A6 Sedan","2010","300","310" +"226","79","142","Front-wheel drive","Chevrolet 1.6L 4 Cylinder 108 hp 105 ft-lbs","True","5","5 Speed Manual","27","Gasoline","35","Manual transmission","2011 Chevrolet Aveo5 LS","Chevrolet","2011 Chevrolet Aveo5","2011","108","105" +"226","79","142","Front-wheel drive","Chevrolet 1.6L 4 Cylinder 108 hp 105 ft-lbs","True","5","5 Speed Manual","27","Gasoline","35","Manual transmission","2011 Chevrolet Aveo5 1LT","Chevrolet","2011 Chevrolet Aveo5","2011","108","105" +"226","79","142","Front-wheel drive","Chevrolet 1.6L 4 Cylinder 108 hp 105 ft-lbs","True","4","4 Speed Automatic","25","Gasoline","34","Automatic transmission","2011 Chevrolet Aveo5 1LT AT","Chevrolet","2011 Chevrolet Aveo5","2011","108","105" +"226","79","142","Front-wheel drive","Chevrolet 1.6L 4 Cylinder 108 hp 105 ft-lbs","True","5","5 Speed Manual","27","Gasoline","35","Manual transmission","2011 Chevrolet Aveo5 2LT","Chevrolet","2011 Chevrolet Aveo5","2011","108","105" +"226","79","142","Front-wheel drive","Chevrolet 1.6L 4 Cylinder 108 hp 105 ft-lbs","True","4","4 Speed Automatic","25","Gasoline","34","Automatic transmission","2011 Chevrolet Aveo5 2LT AT","Chevrolet","2011 Chevrolet Aveo5","2011","108","105" +"179","52","220","All-wheel drive","Audi 4.2L 8 cylinder 350 hp 325 ft-lbs","True","6","6 Speed Automatic Select Shift","16","Gasoline","23","Automatic transmission","2010 Audi A6 Sedan 4.2","Audi","2010 Audi A6 Sedan","2010","350","325" +"198","69","220","All-wheel drive","Audi 3.0L 6 Cylinder 300 hp 310 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","26","Automatic transmission","2011 Audi A6 Avant","Audi","2011 Audi A6 Avant","2011","300","310" +"198","69","220","All-wheel drive","Audi 3.0L 6 Cylinder 300 hp 310 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","26","Automatic transmission","2010 Audi A6 Avant","Audi","2010 Audi A6 Avant","2010","300","310" +"140","105","91","All-wheel drive","Audi 3.0L 6 Cylinder 310 hp 325 ft-lbs","True","8","8 Speed Automatic Select Shift","18","Gasoline","28","Automatic transmission","2012 Audi A7","Audi","2012 Audi A7","2012","310","325" +"180","17","63","All-wheel drive","Audi 4.2L 8 Cylinder 372 hp 328 ft-lbs","True","8","8 Speed Automatic Select Shift","17","Gasoline","27","Automatic transmission","2011 Audi A8","Audi","2011 Audi A8","2011","372","328" +"191","147","63","All-wheel drive","Audi 4.2L 8 Cylinder 372 hp 328 ft-lbs","True","8","8 Speed Automatic Select Shift","17","Gasoline","27","Automatic transmission","2011 Audi A8 L","Audi","2011 Audi A8","2011","372","328" +"189","155","222","Four-wheel drive","Nissan 5.6L 8 Cylinder 317 hp 385 ft-lbs","True","5","5 Speed Automatic","12","Gasoline","18","Automatic transmission","2010 Nissan Armada SE 4x4","Nissan","2010 Nissan Armada","2010","317","385" +"189","155","222","Four-wheel drive","Nissan 5.6L 8 Cylinder 317 hp 385 ft-lbs","True","5","5 Speed Automatic","12","Gasoline","18","Automatic transmission","2010 Nissan Armada Titanium 4x4","Nissan","2010 Nissan Armada","2010","317","385" +"168","155","222","Rear-wheel drive","Nissan 5.6L 8 Cylinder 317 hp 385 ft-lbs","True","5","5 Speed Automatic","12","Gasoline","18","Automatic transmission","2010 Nissan Armada Platinum","Nissan","2010 Nissan Armada","2010","317","385" +"168","155","222","Rear-wheel drive","Nissan 5.6L 8 Cylinder 317 hp 385 ft-lbs","True","5","5 Speed Automatic","12","Gasoline","18","Automatic transmission","2010 Nissan Armada SE","Nissan","2010 Nissan Armada","2010","317","385" +"168","155","222","Rear-wheel drive","Nissan 5.6L 8 Cylinder 317 hp 385 ft-lbs","True","5","5 Speed Automatic","12","Gasoline","18","Automatic transmission","2010 Nissan Armada Titanium","Nissan","2010 Nissan Armada","2010","317","385" +"189","155","222","Four-wheel drive","Nissan 5.6L 8 Cylinder 317 hp 385 ft-lbs","True","5","5 Speed Automatic","12","Gasoline","18","Automatic transmission","2010 Nissan Armada Platinum 4x4","Nissan","2010 Nissan Armada","2010","317","385" +"164","198","236","All-wheel drive","Audi 4.2L 8 cylinder 350 hp 325 ft-lbs","True","6","6 Speed Automatic Select Shift","16","Gasoline","23","Automatic transmission","2010 Audi A8 L","Audi","2010 Audi A8","2010","350","325" +"164","198","236","All-wheel drive","Audi 4.2L 8 cylinder 350 hp 325 ft-lbs","True","6","6 Speed Automatic Select Shift","16","Gasoline","23","Automatic transmission","2010 Audi A8","Audi","2010 Audi A8","2010","350","325" +"115","140","158","Front-wheel drive","Nissan 1.8L 4 Cylinder 122 hp 127 ft-lbs","True","6","6 Speed Manual","25","Gasoline","30","Manual transmission","2011 Nissan Cube 1.8","Nissan","2011 Nissan Cube","2011","122","127" +"115","140","158","Front-wheel drive","Nissan 1.8L 4 Cylinder 122 hp 127 ft-lbs","True","6","6 Speed Manual","25","Gasoline","30","Manual transmission","2011 Nissan Cube 1.8 S","Nissan","2011 Nissan Cube","2011","122","127" +"115","140","158","Front-wheel drive","Nissan 1.8L 4 Cylinder 122 hp 127 ft-lbs","True","6","6 Speed Manual","25","Gasoline","30","Manual transmission","2010 Nissan Cube 1.8","Nissan","2010 Nissan Cube","2010","122","127" +"115","140","158","Front-wheel drive","Nissan 1.8L 4 Cylinder 122 hp 127 ft-lbs","True","6","6 Speed Manual","25","Gasoline","30","Manual transmission","2010 Nissan Cube 1.8 S","Nissan","2010 Nissan Cube","2010","122","127" +"117","21","41","All-wheel drive","Audi 2.0L 4 cylinder 211 hp 258 ft-lbs Turbo","True","8","8 Speed Automatic Select Shift","20","Gasoline","27","Automatic transmission","2012 Audi Q5 2.0 T","Audi","2012 Audi Q5","2012","211","258" +"117","21","41","All-wheel drive","Audi 3.2L 6 cylinder 270 hp 243 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","23","Automatic transmission","2012 Audi Q5 3.2","Audi","2012 Audi Q5","2012","270","243" +"117","21","41","All-wheel drive","Audi 2.0L 4 cylinder 211 hp 258 ft-lbs Turbo","True","8","8 Speed Automatic Select Shift","20","Gasoline","27","Automatic transmission","2011 Audi Q5 2.0 T","Audi","2011 Audi Q5","2011","211","258" +"117","21","41","All-wheel drive","Audi 3.2L 6 cylinder 270 hp 243 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","23","Automatic transmission","2011 Audi Q5 3.2","Audi","2011 Audi Q5","2011","270","243" +"135","134","105","Front-wheel drive","Honda 3.5L 6 Cylinder 271 hp 254 ft-lbs","True","5","5 Speed Automatic","18","Gasoline","27","Automatic transmission","2010 Honda Accord Crosstour EX Hatchback","Honda","2010 Honda Accord Crosstour Hatchback","2010","271","254" +"135","134","105","Front-wheel drive","Honda 3.5L 6 Cylinder 271 hp 254 ft-lbs","True","5","5 Speed Automatic","18","Gasoline","27","Automatic transmission","2010 Honda Accord Crosstour EX-L Hatchback","Honda","2010 Honda Accord Crosstour Hatchback","2010","271","254" +"135","134","105","Four-wheel drive","Honda 3.5L 6 Cylinder 271 hp 254 ft-lbs","True","5","5 Speed Automatic","17","Gasoline","25","Automatic transmission","2010 Honda Accord Crosstour EX-L Hatchback 4WD","Honda","2010 Honda Accord Crosstour Hatchback","2010","271","254" +"117","21","41","All-wheel drive","Audi 3.2L 6 cylinder 270 hp 243 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","23","Automatic transmission","2010 Audi Q5 3.2","Audi","2010 Audi Q5","2010","270","243" +"117","20","88","All-wheel drive","Audi 3.2L 6 cylinder 270 hp 243 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","23","Automatic transmission","2009 Audi Q5 3.2","Audi","2009 Audi Q5","2009","270","243" +"117","105","214","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Manual","26","Gasoline","34","Manual transmission","2011 Honda Civic DX Coup","Honda","2011 Honda Civic Coup","2011","140","128" +"117","105","214","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Automatic","25","Gasoline","36","Automatic transmission","2011 Honda Civic DX Coup AT","Honda","2011 Honda Civic Coup","2011","140","128" +"117","105","214","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Manual","26","Gasoline","34","Manual transmission","2011 Honda Civic LX Coup","Honda","2011 Honda Civic Coup","2011","140","128" +"117","105","214","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Automatic","25","Gasoline","36","Automatic transmission","2011 Honda Civic LX Coup AT","Honda","2011 Honda Civic Coup","2011","140","128" +"117","105","214","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Manual","26","Gasoline","34","Manual transmission","2011 Honda Civic EX Coup","Honda","2011 Honda Civic Coup","2011","140","128" +"117","105","214","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Automatic","25","Gasoline","36","Automatic transmission","2011 Honda Civic EX Coup AT","Honda","2011 Honda Civic Coup","2011","140","128" +"117","105","214","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Automatic","25","Gasoline","36","Automatic transmission","2011 Honda Civic EX-L Coup","Honda","2011 Honda Civic Coup","2011","140","128" +"117","105","214","Front-wheel drive","Honda 2.0L 4 cylinder 197hp 139ft-lbs","True","6","6 Speed Manual","21","Gasoline","29","Manual transmission","2011 Honda Civic Si Coup","Honda","2011 Honda Civic Coup","2011","197","139" +"201","225","129","All-wheel drive","Audi 3.0L 6 Cylinder 333 hp 325 ft-lbs S-charged","True","8","8 Speed Automatic Select Shift","16","Gasoline","22","Automatic transmission","2012 Audi Q7 3.0 T S Line","Audi","2012 Audi Q7","2012","333","325" +"201","225","129","All-wheel drive","Audi 3.0L 6 Cylinder 280 hp 295 ft-lbs S-charged","True","8","8 Speed Automatic Select Shift","16","Gasoline","22","Automatic transmission","2012 Audi Q7 3.0 T","Audi","2012 Audi Q7","2012","280","295" +"201","225","129","All-wheel drive","Audi 3.0L 6 Cylinder 225 hp 406 ft-lbs Turbo Diesel","True","8","8 Speed Automatic Select Shift","17","Diesel fuel","25","Automatic transmission","2012 Audi Q7 3.0 TDI","Audi","2012 Audi Q7","2012","225","406" +"141","249","107","Rear-wheel drive","Lamborghini 5.2L 10 Cylinder 550 hp 398 ft-lbs","True","6","6 Speed Manual","12","Gasoline","20","Manual transmission","2010 Lamborghini Gallardo Coupe LP 550-2 Valentino Balboni","Lamborghini","2010 Lamborghini Gallardo Coupe","2010","550","398" +"226","79","142","Front-wheel drive","Chevrolet 1.6L 4 Cylinder 108 hp 105 ft-lbs","True","5","5 Speed Manual","27","Gasoline","35","Manual transmission","2010 Chevrolet Aveo5 LS","Chevrolet","2010 Chevrolet Aveo5","2010","108","105" +"226","79","142","Front-wheel drive","Chevrolet 1.6L 4 Cylinder 108 hp 105 ft-lbs","True","5","5 Speed Manual","27","Gasoline","35","Manual transmission","2010 Chevrolet Aveo5 1LT","Chevrolet","2010 Chevrolet Aveo5","2010","108","105" +"226","79","142","Front-wheel drive","Chevrolet 1.6L 4 Cylinder 108 hp 105 ft-lbs","True","4","4 Speed Automatic","25","Gasoline","34","Automatic transmission","2010 Chevrolet Aveo5 1LT AT","Chevrolet","2010 Chevrolet Aveo5","2010","108","105" +"226","79","142","Front-wheel drive","Chevrolet 1.6L 4 Cylinder 108 hp 105 ft-lbs","True","5","5 Speed Manual","27","Gasoline","35","Manual transmission","2010 Chevrolet Aveo5 2LT","Chevrolet","2010 Chevrolet Aveo5","2010","108","105" +"226","79","142","Front-wheel drive","Chevrolet 1.6L 4 Cylinder 108 hp 105 ft-lbs","True","4","4 Speed Automatic","25","Gasoline","34","Automatic transmission","2010 Chevrolet Aveo5 2LT AT","Chevrolet","2010 Chevrolet Aveo5","2010","108","105" +"195","195","82","Rear-wheel drive","Lexus 4.6L 8 Cylinder 380 hp 367 ft-lbs","True","8","8 Speed Automatic Select Shift","16","Gasoline","24","Automatic transmission","2010 Lexus LS 460","Lexus","2010 Lexus LS","2010","380","367" +"195","196","83","All-wheel drive","Lexus 4.6L 8 Cylinder 357hp 344ft-lbs","True","8","8 Speed Automatic Select Shift","16","Gasoline","23","Automatic transmission","2010 Lexus LS 460 AWD","Lexus","2010 Lexus LS","2010","357","344" +"195","60","83","Rear-wheel drive","Lexus 4.6L 8 Cylinder 380 hp 367 ft-lbs","True","8","8 Speed Automatic Select Shift","16","Gasoline","24","Automatic transmission","2010 Lexus LS 460 L","Lexus","2010 Lexus LS","2010","380","367" +"195","60","83","All-wheel drive","Lexus 4.6L 8 Cylinder 357hp 344ft-lbs","True","8","8 Speed Automatic Select Shift","16","Gasoline","23","Automatic transmission","2010 Lexus LS 460 L AWD","Lexus","2010 Lexus LS","2010","357","344" +"141","249","107","Four-wheel drive","Lamborghini 5.2L 10 Cylinder 560 hp 398 ft-lbs","True","6","6 Speed Manual","12","Gasoline","20","Manual transmission","2011 Lamborghini Gallardo Coupe LP 560-4","Lamborghini","2011 Lamborghini Gallardo Coupe","2011","560","398" +"159","249","107","Four-wheel drive","Lamborghini 5.2L 10 Cylinder 560 hp 398 ft-lbs","True","6","6 Speed Manual","12","Gasoline","20","Manual transmission","2011 Lamborghini Gallardo Coupe LP 560-4 Spyder","Lamborghini","2011 Lamborghini Gallardo Coupe","2011","560","398" +"170","18","163","Front-wheel drive","Hyundai 1.6L 4 Cylinder 138 hp 123 ft-lbs","True","6","6 Speed Automatic Select Shift","30","Gasoline","40","Automatic transmission","2012 Hyundai Accent Hatchback SE AT","Hyundai","2012 Hyundai Accent Hatchback","2012","138","123" +"170","18","163","Front-wheel drive","Hyundai 1.6L 4 Cylinder 138 hp 123 ft-lbs","True","6","6 Speed Automatic Select Shift","30","Gasoline","40","Automatic transmission","2012 Hyundai Accent Hatchback GS AT","Hyundai","2012 Hyundai Accent Hatchback","2012","138","123" +"170","18","163","Front-wheel drive","Hyundai 1.6L 4 Cylinder 138 hp 123 ft-lbs","True","6","6 Speed Manual","30","Gasoline","40","Manual transmission","2012 Hyundai Accent Hatchback SE","Hyundai","2012 Hyundai Accent Hatchback","2012","138","123" +"170","18","163","Front-wheel drive","Hyundai 1.6L 4 Cylinder 138 hp 123 ft-lbs","True","6","6 Speed Manual","30","Gasoline","40","Manual transmission","2012 Hyundai Accent Hatchback GS","Hyundai","2012 Hyundai Accent Hatchback","2012","138","123" +"195","196","83","Rear-wheel drive","Lexus 4.6L 8 Cylinder 380 hp 367 ft-lbs","True","8","8 Speed Automatic Select Shift","16","Gasoline","24","Automatic transmission","2011 Lexus LS 460","Lexus","2011 Lexus LS","2011","380","367" +"195","196","83","All-wheel drive","Lexus 4.6L 8 Cylinder 357hp 344ft-lbs","True","8","8 Speed Automatic Select Shift","16","Gasoline","23","Automatic transmission","2011 Lexus LS 460 AWD","Lexus","2011 Lexus LS","2011","357","344" +"195","60","83","Rear-wheel drive","Lexus 4.6L 8 Cylinder 380 hp 367 ft-lbs","True","8","8 Speed Automatic Select Shift","16","Gasoline","24","Automatic transmission","2011 Lexus LS 460 L","Lexus","2011 Lexus LS","2011","380","367" +"195","60","83","All-wheel drive","Lexus 4.6L 8 Cylinder 357hp 344ft-lbs","True","8","8 Speed Automatic Select Shift","16","Gasoline","23","Automatic transmission","2011 Lexus LS 460 L AWD","Lexus","2011 Lexus LS","2011","357","344" +"190","206","158","Front-wheel drive","Hyundai 1.6L 4 cylinder 110hp 106 ft-lbs","True","4","4 Speed Automatic","27","Gasoline","36","Automatic transmission","2011 Hyundai Accent Hatchback GS AT","Hyundai","2011 Hyundai Accent Hatchback","2011","110","106" +"190","206","158","Front-wheel drive","Hyundai 1.6L 4 cylinder 110hp 106 ft-lbs","True","5","5 Speed Manual","28","Gasoline","34","Manual transmission","2011 Hyundai Accent Hatchback SE","Hyundai","2011 Hyundai Accent Hatchback","2011","110","106" +"190","206","158","Front-wheel drive","Hyundai 1.6L 4 cylinder 110hp 106 ft-lbs","True","5","5 Speed Manual","28","Gasoline","34","Manual transmission","2011 Hyundai Accent Hatchback GS","Hyundai","2011 Hyundai Accent Hatchback","2011","110","106" +"190","206","158","Front-wheel drive","Hyundai 1.6L 4 cylinder 110hp 106 ft-lbs","True","5","5 Speed Manual","28","Gasoline","34","Manual transmission","2011 Hyundai Accent Hatchback GL","Hyundai","2011 Hyundai Accent Hatchback","2011","110","106" +"190","206","158","Front-wheel drive","Hyundai 1.6L 4 cylinder 110hp 106 ft-lbs","True","4","4 Speed Automatic","27","Gasoline","36","Automatic transmission","2011 Hyundai Accent Hatchback SE AT","Hyundai","2011 Hyundai Accent Hatchback","2011","110","106" +"190","206","158","Front-wheel drive","Hyundai 1.6L 4 cylinder 110hp 106 ft-lbs","True","5","5 Speed Manual","28","Gasoline","34","Manual transmission","2010 Hyundai Accent Hatchback GS","Hyundai","2010 Hyundai Accent Hatchback","2010","110","106" +"190","206","158","Front-wheel drive","Hyundai 1.6L 4 cylinder 110hp 106 ft-lbs","True","4","4 Speed Automatic","27","Gasoline","36","Automatic transmission","2010 Hyundai Accent Hatchback SE AT","Hyundai","2010 Hyundai Accent Hatchback","2010","110","106" +"190","206","158","Front-wheel drive","Hyundai 1.6L 4 cylinder 110hp 106 ft-lbs","True","5","5 Speed Manual","28","Gasoline","34","Manual transmission","2010 Hyundai Accent Hatchback SE","Hyundai","2010 Hyundai Accent Hatchback","2010","110","106" +"190","206","158","Front-wheel drive","Hyundai 1.6L 4 cylinder 110hp 106 ft-lbs","True","4","4 Speed Automatic","27","Gasoline","36","Automatic transmission","2010 Hyundai Accent Hatchback GS AT","Hyundai","2010 Hyundai Accent Hatchback","2010","110","106" +"190","206","158","Front-wheel drive","Hyundai 1.6L 4 cylinder 110hp 106 ft-lbs","True","5","5 Speed Manual","27","Gasoline","36","Manual transmission","2010 Hyundai Accent Hatchback Blue","Hyundai","2010 Hyundai Accent Hatchback","2010","110","106" +"170","16","163","Front-wheel drive","Hyundai 1.6L 4 Cylinder 138 hp 123 ft-lbs","True","6","6 Speed Manual","30","Gasoline","40","Manual transmission","2012 Hyundai Accent Sedan GLS","Hyundai","2012 Hyundai Accent Sedan","2012","138","123" +"170","16","163","Front-wheel drive","Hyundai 1.6L 4 Cylinder 138 hp 123 ft-lbs","True","6","6 Speed Automatic Select Shift","30","Gasoline","40","Automatic transmission","2012 Hyundai Accent Sedan GLS AT","Hyundai","2012 Hyundai Accent Sedan","2012","138","123" +"190","183","158","Front-wheel drive","Hyundai 1.6L 4 cylinder 110hp 106 ft-lbs","True","4","4 Speed Automatic","27","Gasoline","36","Automatic transmission","2011 Hyundai Accent Sedan GLS AT","Hyundai","2011 Hyundai Accent Sedan","2011","110","106" +"190","183","158","Front-wheel drive","Hyundai 1.6L 4 cylinder 110hp 106 ft-lbs","True","5","5 Speed Manual","28","Gasoline","34","Manual transmission","2011 Hyundai Accent Sedan GLS","Hyundai","2011 Hyundai Accent Sedan","2011","110","106" +"190","183","158","Front-wheel drive","Hyundai 1.6L 4 cylinder 110hp 106 ft-lbs","True","5","5 Speed Manual","28","Gasoline","34","Manual transmission","2010 Hyundai Accent Sedan GLS","Hyundai","2010 Hyundai Accent Sedan","2010","110","106" +"190","183","158","Front-wheel drive","Hyundai 1.6L 4 cylinder 110hp 106 ft-lbs","True","4","4 Speed Automatic","27","Gasoline","36","Automatic transmission","2010 Hyundai Accent Sedan GLS AT","Hyundai","2010 Hyundai Accent Sedan","2010","110","106" +"210","45","57","Front-wheel drive","Hyundai 3.3L 6 Cylinder 260 hp 233 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","28","Automatic transmission","2011 Hyundai Azera GLS","Hyundai","2011 Hyundai Azera","2011","260","233" +"210","45","57","Front-wheel drive","Hyundai 3.8L 6 Cylinder 283 hp 263 ft-lbs","True","6","6 Speed Automatic Select Shift","19","Gasoline","27","Automatic transmission","2011 Hyundai Azera Limited","Hyundai","2011 Hyundai Azera","2011","283","263" +"210","30","57","Front-wheel drive","Hyundai 3.8L 6 cylinder 263hp 257 ft-lbs","True","5","5 Speed Automatic Select Shift","17","Gasoline","26","Automatic transmission","2010 Hyundai Azera Limited","Hyundai","2010 Hyundai Azera","2010","263","257" +"210","30","57","Front-wheel drive","Hyundai 3.3L 6 cylinder 234hp 226 ft-lbs","True","5","5 Speed Automatic Select Shift","18","Gasoline","26","Automatic transmission","2010 Hyundai Azera GLS","Hyundai","2010 Hyundai Azera","2010","234","226" +"201","225","129","All-wheel drive","Audi 3.0L 6 Cylinder 333 hp 325 ft-lbs S-charged","True","8","8 Speed Automatic Select Shift","16","Gasoline","22","Automatic transmission","2011 Audi Q7 3.0 T S Line","Audi","2011 Audi Q7","2011","333","325" +"201","225","129","All-wheel drive","Audi 3.0L 6 Cylinder 272 hp 295 ft-lbs S-charged","True","8","8 Speed Automatic Select Shift","16","Gasoline","22","Automatic transmission","2011 Audi Q7 3.0 T","Audi","2011 Audi Q7","2011","272","295" +"201","225","129","All-wheel drive","Audi 3.0L 6 Cylinder 225 hp 406 ft-lbs Turbo Diesel","True","8","8 Speed Automatic Select Shift","17","Diesel fuel","25","Automatic transmission","2011 Audi Q7 3.0 TDI","Audi","2011 Audi Q7","2011","225","406" +"201","223","191","All-wheel drive","Audi 3.6L 6 cylinder 280hp 266 ft-lbs","True","6","6 Speed Automatic Select Shift","14","Gasoline","19","Automatic transmission","2010 Audi Q7 3.6","Audi","2010 Audi Q7","2010","280","266" +"201","223","191","All-wheel drive","Audi 3.0L 6 Cylinder 225 hp 406 ft-lbs Turbo Diesel","True","6","6 Speed Automatic Select Shift","17","Diesel fuel","25","Automatic transmission","2010 Audi Q7 3.0 TDI","Audi","2010 Audi Q7","2010","225","406" +"201","223","191","All-wheel drive","Audi 4.2L 8 cylinder 350 hp 325 ft-lbs","True","6","6 Speed Automatic Select Shift","13","Gasoline","18","Automatic transmission","2010 Audi Q7 4.2","Audi","2010 Audi Q7","2010","350","325" +"148","12","24","Front-wheel drive","Toyota 2.5L 4 Cylinder 179 hp 172 ft-lbs.","True","4","4 Speed Automatic","22","Gasoline","28","Automatic transmission","2011 Toyota RAV4","Toyota","2011 Toyota RAV4","2011","179","172" +"148","12","24","Four-wheel drive","Toyota 2.5L 4 Cylinder 179 hp 172 ft-lbs.","True","4","4 Speed Automatic","21","Gasoline","27","Automatic transmission","2011 Toyota RAV4 4WD","Toyota","2011 Toyota RAV4","2011","179","172" +"148","12","24","Front-wheel drive","Toyota 3.5L 6 Cylinder 269 hp 246 ft-lbs.","True","5","5 Speed Automatic","19","Gasoline","27","Automatic transmission","2011 Toyota RAV4 V6","Toyota","2011 Toyota RAV4","2011","269","246" +"148","12","24","Four-wheel drive","Toyota 3.5L 6 Cylinder 269 hp 246 ft-lbs.","True","5","5 Speed Automatic","19","Gasoline","26","Automatic transmission","2011 Toyota RAV4 V6 4WD","Toyota","2011 Toyota RAV4","2011","269","246" +"148","12","62","Front-wheel drive","Toyota 2.5L 4 Cylinder 179 hp 172 ft-lbs.","True","4","4 Speed Automatic","22","Gasoline","28","Automatic transmission","2011 Toyota RAV4 Sport","Toyota","2011 Toyota RAV4","2011","179","172" +"148","12","62","Four-wheel drive","Toyota 2.5L 4 Cylinder 179 hp 172 ft-lbs.","True","4","4 Speed Automatic","21","Gasoline","27","Automatic transmission","2011 Toyota RAV4 Sport 4WD","Toyota","2011 Toyota RAV4","2011","179","172" +"148","12","62","Front-wheel drive","Toyota 3.5L 6 Cylinder 269 hp 246 ft-lbs.","True","5","5 Speed Automatic","19","Gasoline","27","Automatic transmission","2011 Toyota RAV4 Sport V6","Toyota","2011 Toyota RAV4","2011","269","246" +"148","12","62","Four-wheel drive","Toyota 3.5L 6 Cylinder 269 hp 246 ft-lbs.","True","5","5 Speed Automatic","19","Gasoline","26","Automatic transmission","2011 Toyota RAV4 Sport V6 4WD","Toyota","2011 Toyota RAV4","2011","269","246" +"208","12","62","Front-wheel drive","Toyota 2.5L 4 Cylinder 179 hp 172 ft-lbs.","True","4","4 Speed Automatic","22","Gasoline","28","Automatic transmission","2011 Toyota RAV4 Limited","Toyota","2011 Toyota RAV4","2011","179","172" +"208","12","62","Four-wheel drive","Toyota 2.5L 4 Cylinder 179 hp 172 ft-lbs.","True","4","4 Speed Automatic","21","Gasoline","27","Automatic transmission","2011 Toyota RAV4 Limited 4WD","Toyota","2011 Toyota RAV4","2011","179","172" +"208","12","62","Front-wheel drive","Toyota 3.5L 6 Cylinder 269 hp 246 ft-lbs.","True","5","5 Speed Automatic","19","Gasoline","27","Automatic transmission","2011 Toyota RAV4 Limited V6","Toyota","2011 Toyota RAV4","2011","269","246" +"208","12","62","Four-wheel drive","Toyota 3.5L 6 Cylinder 269 hp 246 ft-lbs.","True","5","5 Speed Automatic","19","Gasoline","26","Automatic transmission","2011 Toyota RAV4 Limited V6 4WD","Toyota","2011 Toyota RAV4","2011","269","246" +"115","140","158","Front-wheel drive","Nissan 1.8L 4 Cylinder 122 hp 127 ft-lbs","True","6","6 Speed Manual","24","Gasoline","29","Manual transmission","2009 Nissan Cube 1.8 S","Nissan","2009 Nissan Cube","2009","122","127" +"115","140","158","Front-wheel drive","Nissan 1.8L 4 Cylinder 122 hp 127 ft-lbs","True","6","6 Speed Manual","24","Gasoline","29","Manual transmission","2009 Nissan Cube 1.8","Nissan","2009 Nissan Cube","2009","122","127" +"172","123","234","Front-wheel drive","Volvo 2.5L 5 Cylinder 227 hp 236 ft-lbs Turbo","True","5","5 Speed Automatic","21","Gasoline","30","Automatic transmission","2011 Volvo S40 R-Design","Volvo","2011 Volvo S40","2011","227","236" +"109","228","125","Rear-wheel drive","Chevrolet 3.6L 6 Cylinder 323 hp 278 ft-lbs","True","6","6 Speed Manual","17","Gasoline","28","Manual transmission","2012 Chevrolet Camaro Convertible 1LT","Chevrolet","2012 Chevrolet Camaro Convertible","2012","323","278" +"109","228","125","Rear-wheel drive","Chevrolet 3.6L 6 Cylinder 323 hp 278 ft-lbs","True","6","6 Speed Automatic","19","Gasoline","30","Automatic transmission","2012 Chevrolet Camaro Convertible 1LT AT","Chevrolet","2012 Chevrolet Camaro Convertible","2012","323","278" +"109","228","125","Rear-wheel drive","Chevrolet 3.6L 6 Cylinder 323 hp 278 ft-lbs","True","6","6 Speed Manual","17","Gasoline","28","Manual transmission","2012 Chevrolet Camaro Convertible 2LT","Chevrolet","2012 Chevrolet Camaro Convertible","2012","323","278" +"109","228","125","Rear-wheel drive","Chevrolet 3.6L 6 Cylinder 323 hp 278 ft-lbs","True","6","6 Speed Automatic","19","Gasoline","30","Automatic transmission","2012 Chevrolet Camaro Convertible 2LT AT","Chevrolet","2012 Chevrolet Camaro Convertible","2012","323","278" +"109","228","125","Rear-wheel drive","Chevrolet 6.2L 8 Cylinder 426 hp 420 ft-lbs","True","6","6 Speed Manual","16","Gasoline","24","Manual transmission","2012 Chevrolet Camaro Convertible 1SS","Chevrolet","2012 Chevrolet Camaro Convertible","2012","426","420" +"109","228","125","Rear-wheel drive","Chevrolet 6.2L 8 Cylinder 426 hp 420 ft-lbs","True","6","6 Speed Automatic","15","Gasoline","24","Automatic transmission","2012 Chevrolet Camaro Convertible 1SS AT","Chevrolet","2012 Chevrolet Camaro Convertible","2012","426","420" +"109","228","125","Rear-wheel drive","Chevrolet 6.2L 8 Cylinder 426 hp 420 ft-lbs","True","6","6 Speed Manual","16","Gasoline","24","Manual transmission","2012 Chevrolet Camaro Convertible 2SS","Chevrolet","2012 Chevrolet Camaro Convertible","2012","426","420" +"109","228","125","Rear-wheel drive","Chevrolet 6.2L 8 Cylinder 426 hp 420 ft-lbs","True","6","6 Speed Automatic","15","Gasoline","24","Automatic transmission","2012 Chevrolet Camaro Convertible 2SS AT","Chevrolet","2012 Chevrolet Camaro Convertible","2012","426","420" +"33","28","229","Front-wheel drive","Nissan 1.6L 4 Cylinder 188 hp 177 ft-lbs Turbo","True","6","6 Speed Manual","24","Gasoline","31","Manual transmission","2011 Nissan Juke SL","Nissan","2011 Nissan Juke","2011","188","177" +"33","28","229","Front-wheel drive","Nissan 1.6L 4 Cylinder 188 hp 177 ft-lbs Turbo","True","6","6 Speed Manual","24","Gasoline","31","Manual transmission","2011 Nissan Juke SV","Nissan","2011 Nissan Juke","2011","188","177" +"109","228","125","Rear-wheel drive","Chevrolet 3.6L 6 Cylinder 312 hp 278 ft-lbs","True","6","6 Speed Manual","17","Gasoline","28","Manual transmission","2011 Chevrolet Camaro Convertible 1LT","Chevrolet","2011 Chevrolet Camaro Convertible","2011","312","278" +"109","228","125","Rear-wheel drive","Chevrolet 3.6L 6 Cylinder 312 hp 278 ft-lbs","True","6","6 Speed Automatic","19","Gasoline","30","Automatic transmission","2011 Chevrolet Camaro Convertible 1LT AT","Chevrolet","2011 Chevrolet Camaro Convertible","2011","312","278" +"109","228","125","Rear-wheel drive","Chevrolet 3.6L 6 Cylinder 312 hp 278 ft-lbs","True","6","6 Speed Manual","17","Gasoline","28","Manual transmission","2011 Chevrolet Camaro Convertible 2LT","Chevrolet","2011 Chevrolet Camaro Convertible","2011","312","278" +"109","228","125","Rear-wheel drive","Chevrolet 3.6L 6 Cylinder 312 hp 278 ft-lbs","True","6","6 Speed Automatic","19","Gasoline","30","Automatic transmission","2011 Chevrolet Camaro Convertible 2LT AT","Chevrolet","2011 Chevrolet Camaro Convertible","2011","312","278" +"109","228","125","Rear-wheel drive","Chevrolet 6.2L 8 Cylinder 426 hp 420 ft-lbs","True","6","6 Speed Manual","16","Gasoline","24","Manual transmission","2011 Chevrolet Camaro Convertible 1SS","Chevrolet","2011 Chevrolet Camaro Convertible","2011","426","420" +"109","228","125","Rear-wheel drive","Chevrolet 6.2L 8 Cylinder 426 hp 420 ft-lbs","True","6","6 Speed Automatic","15","Gasoline","24","Automatic transmission","2011 Chevrolet Camaro Convertible 1SS AT","Chevrolet","2011 Chevrolet Camaro Convertible","2011","426","420" +"109","228","125","Rear-wheel drive","Chevrolet 6.2L 8 Cylinder 426 hp 420 ft-lbs","True","6","6 Speed Manual","16","Gasoline","24","Manual transmission","2011 Chevrolet Camaro Convertible 2SS","Chevrolet","2011 Chevrolet Camaro Convertible","2011","426","420" +"109","228","125","Rear-wheel drive","Chevrolet 6.2L 8 Cylinder 426 hp 420 ft-lbs","True","6","6 Speed Automatic","16","Gasoline","25","Automatic transmission","2011 Chevrolet Camaro Convertible 2SS AT","Chevrolet","2011 Chevrolet Camaro Convertible","2011","426","420" +"150","22","234","Rear-wheel drive","Mercedes-Benz 3.0L 6 Cylinders 228 hp 221 ft-lbs FFV","True","6","6 Speed Manual","18","Gasoline","26","Manual transmission","2010 Mercedes-Benz C300 Sport FFV","Mercedes","2010 Mercedes-Benz C-Class","2010","228","221" +"150","22","234","Rear-wheel drive","Mercedes-Benz 3.0L 6 Cylinders 228 hp 221 ft-lbs FFV","True","7","7 Speed Automatic Select Shift","18","Gasoline","26","Automatic transmission","2010 Mercedes-Benz C300 Sport AT FFV","Mercedes","2010 Mercedes-Benz C-Class","2010","228","221" +"150","22","234","Rear-wheel drive","Mercedes-Benz 3.5L 6 Cylinders 268 hp 258 ft-lbs","True","7","7 Speed Automatic Select Shift","17","Gasoline","25","Automatic transmission","2010 Mercedes-Benz C350 Sport","Mercedes","2010 Mercedes-Benz C-Class","2010","268","258" +"132","9","211","Rear-wheel drive","BMW 3.0L 6 cylinder 230hp 200 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","27","Automatic transmission","2010 BMW 128i Convertible AT","BMW Motorrad","2010 BMW 1 Series Convertible","2010","230","200" +"132","9","211","Rear-wheel drive","BMW 3.0L 6 cylinder 300 hp 300 ft-lbs Turbo","True","6","6 Speed Manual","17","Gasoline","26","Manual transmission","2010 BMW 135i Convertible","BMW","2010 BMW 1 Series Convertible","2010","300","300" +"132","9","211","Rear-wheel drive","BMW 3.0L 6 cylinder 300 hp 300 ft-lbs Turbo","True","6","6 Speed Automatic Select Shift","17","Gasoline","26","Automatic transmission","2010 BMW 135i Convertible AT","BMW","2010 BMW 1 Series Convertible","2010","300","300" +"132","9","211","Rear-wheel drive","BMW 3.0L 6 cylinder 230hp 200 ft-lbs","True","6","6 Speed Manual","18","Gasoline","28","Manual transmission","2010 BMW 128i Convertible","BMW Motorrad","2010 BMW 1 Series Convertible","2010","230","200" +"96","228","125","Rear-wheel drive","Chevrolet 3.6L 6 Cylinder 323 hp 278 ft-lbs","True","6","6 Speed Manual","17","Gasoline","28","Manual transmission","2012 Chevrolet Camaro Coupe 1LT","Chevrolet","2012 Chevrolet Camaro Coupe","2012","323","278" +"96","228","125","Rear-wheel drive","Chevrolet 3.6L 6 Cylinder 323 hp 278 ft-lbs","True","6","6 Speed Automatic","19","Gasoline","30","Automatic transmission","2012 Chevrolet Camaro Coupe 1LT AT","Chevrolet","2012 Chevrolet Camaro Coupe","2012","323","278" +"96","228","125","Rear-wheel drive","Chevrolet 3.6L 6 Cylinder 323 hp 278 ft-lbs","True","6","6 Speed Manual","17","Gasoline","28","Manual transmission","2012 Chevrolet Camaro Coupe 2LT","Chevrolet","2012 Chevrolet Camaro Coupe","2012","323","278" +"96","228","125","Rear-wheel drive","Chevrolet 3.6L 6 Cylinder 323 hp 278 ft-lbs","True","6","6 Speed Automatic","19","Gasoline","30","Automatic transmission","2012 Chevrolet Camaro Coupe 2LT AT","Chevrolet","2012 Chevrolet Camaro Coupe","2012","323","278" +"96","228","125","Rear-wheel drive","Chevrolet 6.2L 8 Cylinder 426 hp 420 ft-lbs","True","6","6 Speed Manual","16","Gasoline","24","Manual transmission","2012 Chevrolet Camaro Coupe 1SS","Chevrolet","2012 Chevrolet Camaro Coupe","2012","426","420" +"96","228","125","Rear-wheel drive","Chevrolet 6.2L 8 Cylinder 426 hp 420 ft-lbs","True","6","6 Speed Automatic","15","Gasoline","24","Automatic transmission","2012 Chevrolet Camaro Coupe 1SS AT","Chevrolet","2012 Chevrolet Camaro Coupe","2012","426","420" +"96","228","125","Rear-wheel drive","Chevrolet 6.2L 8 Cylinder 426 hp 420 ft-lbs","True","6","6 Speed Manual","16","Gasoline","24","Manual transmission","2012 Chevrolet Camaro Coupe 2SS","Chevrolet","2012 Chevrolet Camaro Coupe","2012","426","420" +"96","228","125","Rear-wheel drive","Chevrolet 6.2L 8 Cylinder 426 hp 420 ft-lbs","True","6","6 Speed Automatic","15","Gasoline","24","Automatic transmission","2012 Chevrolet Camaro Coupe 2SS AT","Chevrolet","2012 Chevrolet Camaro Coupe","2012","426","420" +"96","228","125","Rear-wheel drive","Chevrolet 3.6L 6 Cylinder 323 hp 278 ft-lbs","True","6","6 Speed Manual","17","Gasoline","28","Manual transmission","2012 Chevrolet Camaro Coupe 1LS","Chevrolet","2012 Chevrolet Camaro Coupe","2012","323","278" +"96","228","125","Rear-wheel drive","Chevrolet 3.6L 6 Cylinder 323 hp 278 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","29","Automatic transmission","2012 Chevrolet Camaro Coupe 2LS","Chevrolet","2012 Chevrolet Camaro Coupe","2012","323","278" +"150","22","234","All-wheel drive","Mercedes-Benz 3.0L 6 Cylinders 228 hp 221 ft-lbs FFV","True","7","7 Speed Automatic Select Shift","13","E85","19","Automatic transmission","2010 Mercedes-Benz C300 Sport 4MATIC","Mercedes","2010 Mercedes-Benz C-Class","2010","228","221" +"165","22","234","Rear-wheel drive","Mercedes-Benz 3.0L 6 Cylinders 228 hp 221 ft-lbs FFV","True","7","7 Speed Automatic Select Shift","18","Gasoline","26","Automatic transmission","2010 Mercedes-Benz C300 Luxury","Mercedes","2010 Mercedes-Benz C-Class","2010","228","221" +"155","176","239","Front-wheel drive","Hyundai 1.8L 4 Cylinder 145 hp 130 ft-lbs","True","6","6 Speed Automatic Select Shift","29","Gasoline","40","Automatic transmission","2012 Hyundai Elantra Sedan Limited PZEV","Hyundai","2012 Hyundai Elantra Sedan","2012","145","130" +"155","176","239","Front-wheel drive","Hyundai 1.8L 4 Cylinder 148 hp 131 ft-lbs","True","6","6 Speed Automatic Select Shift","29","Gasoline","40","Automatic transmission","2012 Hyundai Elantra Sedan GLS AT","Hyundai","2012 Hyundai Elantra Sedan","2012","148","131" +"155","176","239","Front-wheel drive","Hyundai 1.8L 4 Cylinder 148 hp 131 ft-lbs","True","6","6 Speed Manual","29","Gasoline","40","Manual transmission","2012 Hyundai Elantra Sedan GLS","Hyundai","2012 Hyundai Elantra Sedan","2012","148","131" +"155","176","239","Front-wheel drive","Hyundai 1.8L 4 Cylinder 145 hp 130 ft-lbs","True","6","6 Speed Automatic Select Shift","29","Gasoline","40","Automatic transmission","2012 Hyundai Elantra Sedan GLS PZEV","Hyundai","2012 Hyundai Elantra Sedan","2012","145","130" +"155","176","239","Front-wheel drive","Hyundai 1.8L 4 Cylinder 148 hp 131 ft-lbs","True","6","6 Speed Automatic Select Shift","29","Gasoline","40","Automatic transmission","2012 Hyundai Elantra Sedan Limited","Hyundai","2012 Hyundai Elantra Sedan","2012","148","131" +"155","176","239","Front-wheel drive","Hyundai 1.8L 4 Cylinder 148 hp 131 ft-lbs","True","6","6 Speed Automatic Select Shift","29","Gasoline","40","Automatic transmission","2011 Hyundai Elantra Sedan GLS AT","Hyundai","2011 Hyundai Elantra Sedan","2011","148","131" +"155","176","239","Front-wheel drive","Hyundai 1.8L 4 Cylinder 148 hp 131 ft-lbs","True","6","6 Speed Automatic Select Shift","29","Gasoline","40","Automatic transmission","2011 Hyundai Elantra Sedan Limited","Hyundai","2011 Hyundai Elantra Sedan","2011","148","131" +"155","176","239","Front-wheel drive","Hyundai 1.8L 4 Cylinder 145 hp 130 ft-lbs","True","6","6 Speed Automatic Select Shift","29","Gasoline","40","Automatic transmission","2011 Hyundai Elantra Sedan GLS PZEV","Hyundai","2011 Hyundai Elantra Sedan","2011","145","130" +"155","176","239","Front-wheel drive","Hyundai 1.8L 4 Cylinder 148 hp 131 ft-lbs","True","6","6 Speed Manual","29","Gasoline","40","Manual transmission","2011 Hyundai Elantra Sedan GLS","Hyundai","2011 Hyundai Elantra Sedan","2011","148","131" +"155","176","239","Front-wheel drive","Hyundai 1.8L 4 Cylinder 145 hp 130 ft-lbs","True","6","6 Speed Automatic Select Shift","29","Gasoline","40","Automatic transmission","2011 Hyundai Elantra Sedan Limited PZEV","Hyundai","2011 Hyundai Elantra Sedan","2011","145","130" +"200","153","239","Front-wheel drive","Hyundai 2.0L 4 cylinder 138 hp 136 ft-lbs","True","4","4 Speed Automatic","26","Gasoline","34","Automatic transmission","2010 Hyundai Elantra Sedan SE","Hyundai","2010 Hyundai Elantra Sedan","2010","138","136" +"200","153","239","Front-wheel drive","Hyundai 2.0L 4 cylinder 132hp 133 torque","True","4","4 Speed Automatic","26","Gasoline","34","Automatic transmission","2010 Hyundai Elantra Sedan GLS PZEV","Hyundai","2010 Hyundai Elantra Sedan","2010","132","133" +"200","153","239","Front-wheel drive","Hyundai 2.0L 4 cylinder 138 hp 136 ft-lbs","True","5","5 Speed Manual","25","Gasoline","34","Manual transmission","2010 Hyundai Elantra Sedan Blue","Hyundai","2010 Hyundai Elantra Sedan","2010","138","136" +"200","153","239","Front-wheel drive","Hyundai 2.0L 4 cylinder 132hp 133 torque","True","4","4 Speed Automatic","26","Gasoline","34","Automatic transmission","2010 Hyundai Elantra Sedan SE PZEV","Hyundai","2010 Hyundai Elantra Sedan","2010","132","133" +"200","153","239","Front-wheel drive","Hyundai 2.0L 4 cylinder 138 hp 136 ft-lbs","True","4","4 Speed Automatic","26","Gasoline","34","Automatic transmission","2010 Hyundai Elantra Sedan GLS","Hyundai","2010 Hyundai Elantra Sedan","2010","138","136" +"162","233","41","Front-wheel drive","Ford 2.5L 4 Cylinder 175 hp 172 ft-lbs","True","6","6 Speed Manual","22","Gasoline","32","Manual transmission","2012 Ford Fusion S","Ford","2012 Ford Fusion","2012","175","172" +"162","233","41","Front-wheel drive","Ford 2.5L 4 Cylinder 175 hp 172 ft-lbs","True","6","6 Speed Automatic","23","Gasoline","33","Automatic transmission","2012 Ford Fusion S AT","Ford","2012 Ford Fusion","2012","175","172" +"162","233","41","Front-wheel drive","Ford 2.5L 4 Cylinder 175 hp 172 ft-lbs","True","6","6 Speed Automatic","23","Gasoline","33","Automatic transmission","2012 Ford Fusion SE","Ford","2012 Ford Fusion","2012","175","172" +"162","233","41","Front-wheel drive","Ford 3.0L 6 Cylinder 240 hp 223 ft-lbs FFV","True","6","6 Speed Automatic Select Shift","20","Gasoline","28","Automatic transmission","2012 Ford Fusion V6 SE","Ford","2012 Ford Fusion","2012","240","223" +"162","233","41","Front-wheel drive","Ford 2.5L 4 Cylinder 175 hp 172 ft-lbs","True","6","6 Speed Automatic","23","Gasoline","33","Automatic transmission","2012 Ford Fusion SEL","Ford","2012 Ford Fusion","2012","175","172" +"162","233","41","Front-wheel drive","Ford 3.0L 6 Cylinder 240 hp 223 ft-lbs FFV","True","6","6 Speed Automatic Select Shift","20","Gasoline","28","Automatic transmission","2012 Ford Fusion V6 SEL","Ford","2012 Ford Fusion","2012","240","223" +"162","233","41","All-wheel drive","Ford 3.0L 6 Cylinder 240 hp 223 ft-lbs FFV","True","6","6 Speed Automatic Select Shift","13","E85","19","Automatic transmission","2012 Ford Fusion V6 SEL AWD","Ford","2012 Ford Fusion","2012","240","223" +"162","233","41","Front-wheel drive","Ford 3.5L 6 Cylinder 263 hp 249 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","27","Automatic transmission","2012 Ford Fusion Sport","Ford","2012 Ford Fusion","2012","263","249" +"162","233","41","All-wheel drive","Ford 3.5L 6 Cylinder 263 hp 249 ft-lbs","True","6","6 Speed Automatic Select Shift","17","Gasoline","25","Automatic transmission","2012 Ford Fusion Sport AWD","Ford","2012 Ford Fusion","2012","263","249" +"137","190","62","Front-wheel drive","Volkswagen 2.0L 4 Cylinder 200 hp 207 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","31","Manual transmission","2011 Volkswagen CC Sport","Volkswagen","2011 Volkswagen CC","2011","200","207" +"137","190","62","Front-wheel drive","Volkswagen 2.0L 4 Cylinder 200 hp 207 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","31","Manual transmission","2011 Volkswagen CC R-Line","Volkswagen","2011 Volkswagen CC","2011","200","207" +"137","190","62","All-wheel drive","Volkswagen 3.6L 6 Cylinder 280 hp 265 ft-lbs","True","6","6 Speed Automatic","22","Gasoline","31","Automatic transmission","2011 Volkswagen CC VR6 4Motion Executive","Volkswagen","2011 Volkswagen CC","2011","280","265" +"165","233","41","Front-wheel drive","Ford 2.5L 4 Cylinder 175 hp 172 ft-lbs","True","6","6 Speed Manual","22","Gasoline","29","Manual transmission","2011 Ford Fusion S","Ford","2011 Ford Fusion","2011","175","172" +"165","233","41","Front-wheel drive","Ford 2.5L 4 Cylinder 175 hp 172 ft-lbs","True","6","6 Speed Automatic","23","Gasoline","33","Automatic transmission","2011 Ford Fusion S AT","Ford","2011 Ford Fusion","2011","175","172" +"165","233","41","Front-wheel drive","Ford 2.5L 4 Cylinder 175 hp 172 ft-lbs","True","6","6 Speed Manual","22","Gasoline","29","Manual transmission","2011 Ford Fusion SE","Ford","2011 Ford Fusion","2011","175","172" +"165","233","41","Front-wheel drive","Ford 2.5L 4 Cylinder 175 hp 172 ft-lbs","True","6","6 Speed Automatic","23","Gasoline","33","Automatic transmission","2011 Ford Fusion SEL","Ford","2011 Ford Fusion","2011","175","172" +"165","233","41","Front-wheel drive","Ford 3.0L 6 Cylinder 240 hp 228 ft-lbs FFV","True","6","6 Speed Automatic","14","E85","21","Automatic transmission","2011 Ford Fusion V6 SEL","Ford","2011 Ford Fusion","2011","240","228" +"165","233","41","All-wheel drive","Ford 3.0L 6 Cylinder 240 hp 228 ft-lbs FFV","True","6","6 Speed Automatic","13","E85","19","Automatic transmission","2011 Ford Fusion V6 SEL AWD","Ford","2011 Ford Fusion","2011","240","228" +"165","233","41","Front-wheel drive","Ford 3.5L 6 Cylinder 263 hp 249 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","27","Automatic transmission","2011 Ford Fusion Sport","Ford","2011 Ford Fusion","2011","263","249" +"165","233","41","All-wheel drive","Ford 3.5L 6 Cylinder 263 hp 249 ft-lbs","True","6","6 Speed Automatic","17","Gasoline","24","Automatic transmission","2011 Ford Fusion Sport AWD","Ford","2011 Ford Fusion","2011","263","249" +"165","233","41","Front-wheel drive","Ford 3.0L 6 Cylinder 240 hp 228 ft-lbs FFV","True","6","6 Speed Automatic","14","E85","21","Automatic transmission","2011 Ford Fusion V6 SE","Ford","2011 Ford Fusion","2011","240","228" +"165","233","41","Front-wheel drive","Ford 2.5L 4 Cylinder 175 hp 172 ft-lbs","True","6","6 Speed Automatic","23","Gasoline","33","Automatic transmission","2011 Ford Fusion SE AT","Ford","2011 Ford Fusion","2011","175","172" +"165","233","41","Front-wheel drive","Ford 2.5L 4 Cylinder 175 hp 172 ft-lbs","True","6","6 Speed Manual","22","Gasoline","31","Manual transmission","2010 Ford Fusion S","Ford","2010 Ford Fusion","2010","175","172" +"165","233","41","Front-wheel drive","Ford 2.5L 4 Cylinder 175 hp 172 ft-lbs","True","6","6 Speed Automatic","23","Gasoline","34","Automatic transmission","2010 Ford Fusion S AT","Ford","2010 Ford Fusion","2010","175","172" +"165","233","41","Front-wheel drive","Ford 2.5L 4 Cylinder 175 hp 172 ft-lbs","True","6","6 Speed Manual","22","Gasoline","29","Manual transmission","2010 Ford Fusion SE","Ford","2010 Ford Fusion","2010","175","172" +"165","233","41","Front-wheel drive","Ford 3.0L 6 Cylinder 240 hp 228 ft-lbs FFV","True","6","6 Speed Automatic Select Shift","19","Gasoline","27","Automatic transmission","2010 Ford Fusion V6 SE","Ford","2010 Ford Fusion","2010","240","228" +"165","233","41","Front-wheel drive","Ford 2.5L 4 Cylinder 175 hp 172 ft-lbs","True","6","6 Speed Automatic","22","Gasoline","31","Automatic transmission","2010 Ford Fusion SEL","Ford","2010 Ford Fusion","2010","175","172" +"165","233","41","Front-wheel drive","Ford 3.0L 6 Cylinder 240 hp 228 ft-lbs FFV","True","6","6 Speed Automatic Select Shift","13","E85","20","Automatic transmission","2010 Ford Fusion V6 SEL","Ford","2010 Ford Fusion","2010","240","228" +"165","233","41","All-wheel drive","Ford 3.0L 6 Cylinder 240 hp 228 ft-lbs FFV","True","6","6 Speed Automatic Select Shift","13","E85","18","Automatic transmission","2010 Ford Fusion V6 SEL AWD","Ford","2010 Ford Fusion","2010","240","228" +"165","233","41","Front-wheel drive","Ford 3.5L 6 Cylinder 263 hp 249 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","27","Automatic transmission","2010 Ford Fusion Sport","Ford","2010 Ford Fusion","2010","263","249" +"165","233","41","All-wheel drive","Ford 3.5L 6 Cylinder 263 hp 249 ft-lbs","True","6","6 Speed Automatic Select Shift","17","Gasoline","24","Automatic transmission","2010 Ford Fusion Sport AWD","Ford","2010 Ford Fusion","2010","263","249" +"165","233","41","Front-wheel drive","Ford 2.5L 4 Cylinder 175 hp 172 ft-lbs","True","6","6 Speed Automatic","22","Gasoline","31","Automatic transmission","2010 Ford Fusion SE AT","Ford","2010 Ford Fusion","2010","175","172" +"180","176","239","Front-wheel drive","Kia 2.0L 4 Cylinder 156 hp 144 ft-lbs","True","6","6 Speed Manual","25","Gasoline","34","Manual transmission","2011 Kia Forte LX","Kia","2011 Kia Forte","2011","156","144" +"180","176","239","Front-wheel drive","Kia 2.0L 4 Cylinder 156 hp 144 ft-lbs","True","6","6 Speed Automatic Select Shift","26","Gasoline","36","Automatic transmission","2011 Kia Forte LX AT","Kia","2011 Kia Forte","2011","156","144" +"180","176","239","Front-wheel drive","Kia 2.0L 4 Cylinder 156 hp 144 ft-lbs","True","6","6 Speed Automatic Select Shift","26","Gasoline","36","Automatic transmission","2011 Kia Forte EX","Kia","2011 Kia Forte","2011","156","144" +"180","176","239","Front-wheel drive","Kia 2.4L 4 Cylinder 173 hp 168 ft-lbs","True","6","6 Speed Automatic Select Shift","23","Gasoline","32","Automatic transmission","2011 Kia Forte SX","Kia","2011 Kia Forte","2011","173","168" +"201","221","191","All-wheel drive","Audi 3.0L 6 Cylinder 225 hp 406 ft-lbs Turbo Diesel","True","6","6 Speed Automatic Select Shift","17","Diesel fuel","25","Automatic transmission","2009 Audi Q7 3.0 TDI","Audi","2009 Audi Q7","2009","225","406" +"180","244","239","Front-wheel drive","Kia 2.0L 4 Cylinder 156 hp 144 ft-lbs","True","6","6 Speed Manual","25","Gasoline","34","Manual transmission","2011 Kia Forte 5-Door EX","Kia","2011 Kia Forte 5-Door","2011","156","144" +"180","244","239","Front-wheel drive","Kia 2.0L 4 Cylinder 156 hp 144 ft-lbs","True","6","6 Speed Automatic Select Shift","26","Gasoline","36","Automatic transmission","2011 Kia Forte 5-Door EX AT","Kia","2011 Kia Forte 5-Door","2011","156","144" +"180","244","239","Front-wheel drive","Kia 2.4L 4 Cylinder 173 hp 168 ft-lbs","True","6","6 Speed Manual","22","Gasoline","32","Manual transmission","2011 Kia Forte 5-Door SX","Kia","2011 Kia Forte 5-Door","2011","173","168" +"180","244","239","Front-wheel drive","Kia 2.4L 4 Cylinder 173 hp 168 ft-lbs","True","6","6 Speed Automatic Select Shift","23","Gasoline","32","Automatic transmission","2011 Kia Forte 5-Door SX AT","Kia","2011 Kia Forte 5-Door","2011","173","168" +"119","128","229","Front-wheel drive","Kia 2.0L 4 Cylinder 156 hp 144 ft-lbs","True","6","6 Speed Manual","24","Gasoline","33","Manual transmission","2011 Kia Forte Koup EX","Kia","2011 Kia Forte Koup","2011","156","144" +"119","128","229","Front-wheel drive","Kia 2.0L 4 Cylinder 156 hp 144 ft-lbs","True","6","6 Speed Automatic Select Shift","25","Gasoline","34","Automatic transmission","2011 Kia Forte Koup EX AT","Kia","2011 Kia Forte Koup","2011","156","144" +"119","128","229","Front-wheel drive","Kia 2.4L 4 Cylinder 173 hp 168 ft-lbs","True","6","6 Speed Manual","22","Gasoline","32","Manual transmission","2011 Kia Forte Koup SX","Kia","2011 Kia Forte Koup","2011","173","168" +"119","128","229","Front-wheel drive","Kia 2.4L 4 Cylinder 173 hp 168 ft-lbs","True","6","6 Speed Automatic Select Shift","23","Gasoline","31","Automatic transmission","2011 Kia Forte Koup SX AT","Kia","2011 Kia Forte Koup","2011","173","168" +"228","82","138","All-wheel drive","Audi 4.2L 8 cylinder 420hp 317 ft-lbs","True","6","6 Speed Manual","11","Gasoline","20","Manual transmission","2011 Audi R8 Coupe 4.2","Audi","2011 Audi R8 Coupe","2011","420","317" +"228","82","138","All-wheel drive","Audi 5.2L 10 Cylinder 525 hp 391 ft-lbs","True","6","6 Speed Manual","12","Gasoline","19","Manual transmission","2011 Audi R8 Coupe 5.2","Audi","2011 Audi R8 Coupe","2011","525","391" +"180","176","239","Front-wheel drive","Kia 2.0L 4 Cylinder 156 hp 144 ft-lbs","True","5","5 Speed Manual","25","Gasoline","34","Manual transmission","2010 Kia Forte LX","Kia","2010 Kia Forte","2010","156","144" +"180","176","239","Front-wheel drive","Kia 2.0L 4 Cylinder 156 hp 144 ft-lbs","True","4","4 Speed Automatic Select Shift","25","Gasoline","34","Automatic transmission","2010 Kia Forte LX AT","Kia","2010 Kia Forte","2010","156","144" +"180","176","239","Front-wheel drive","Kia 2.0L 4 Cylinder 156 hp 144 ft-lbs","True","5","5 Speed Manual","25","Gasoline","34","Manual transmission","2010 Kia Forte EX","Kia","2010 Kia Forte","2010","156","144" +"180","176","239","Front-wheel drive","Kia 2.0L 4 Cylinder 156 hp 144 ft-lbs","True","4","4 Speed Automatic Select Shift","25","Gasoline","34","Automatic transmission","2010 Kia Forte EX 4sp. AT","Kia","2010 Kia Forte","2010","156","144" +"180","176","239","Front-wheel drive","Kia 2.0L 4 Cylinder 156 hp 144 ft-lbs","True","5","5 Speed Automatic","27","Gasoline","36","Automatic transmission","2010 Kia Forte EX 5sp. AT","Kia","2010 Kia Forte","2010","156","144" +"180","176","239","Front-wheel drive","Kia 2.4L 4 Cylinder 173 hp 168 ft-lbs","True","6","6 Speed Manual","22","Gasoline","32","Manual transmission","2010 Kia Forte SX","Kia","2010 Kia Forte","2010","173","168" +"180","176","239","Front-wheel drive","Kia 2.4L 4 Cylinder 173 hp 168 ft-lbs","True","5","5 Speed Automatic","23","Gasoline","31","Automatic transmission","2010 Kia Forte SX AT","Kia","2010 Kia Forte","2010","173","168" +"228","79","237","All-wheel drive","Audi 4.2L 8 cylinder 430 hp 316 ft-lbs","True","6","6 Speed Manual","11","Gasoline","20","Manual transmission","2012 Audi R8 Coupe 4.2","Audi","2012 Audi R8 Coupe","2012","430","316" +"228","83","237","All-wheel drive","Audi 5.2L 10 Cylinder 525 hp 391 ft-lbs","True","6","6 Speed Manual","12","Gasoline","19","Manual transmission","2012 Audi R8 Coupe 5.2","Audi","2012 Audi R8 Coupe","2012","525","391" +"238","133","229","Front-wheel drive","Hyundai 2.0L 4 cylinder 138 hp 136 ft-lbs","True","4","4 Speed Automatic","23","Gasoline","30","Automatic transmission","2012 Hyundai Elantra Touring GLS AT","Hyundai","2012 Hyundai Elantra Touring","2012","138","136" +"238","133","229","Front-wheel drive","Hyundai 2.0L 4 cylinder 138 hp 136 ft-lbs","True","5","5 Speed Manual","23","Gasoline","31","Manual transmission","2012 Hyundai Elantra Touring GLS","Hyundai","2012 Hyundai Elantra Touring","2012","138","136" +"238","133","229","Front-wheel drive","Hyundai 2.0L 4 cylinder 138 hp 136 ft-lbs","True","5","5 Speed Manual","23","Gasoline","31","Manual transmission","2012 Hyundai Elantra Touring SE","Hyundai","2012 Hyundai Elantra Touring","2012","138","136" +"238","133","229","Front-wheel drive","Hyundai 2.0L 4 cylinder 138 hp 136 ft-lbs","True","4","4 Speed Automatic","23","Gasoline","30","Automatic transmission","2012 Hyundai Elantra Touring SE AT","Hyundai","2012 Hyundai Elantra Touring","2012","138","136" +"238","123","229","Front-wheel drive","Hyundai 2.0L 4 cylinder 138 hp 136 ft-lbs","True","5","5 Speed Manual","23","Gasoline","31","Manual transmission","2011 Hyundai Elantra Touring GLS","Hyundai","2011 Hyundai Elantra Touring","2011","138","136" +"238","123","229","Front-wheel drive","Hyundai 2.0L 4 cylinder 138 hp 136 ft-lbs","True","4","4 Speed Automatic","23","Gasoline","30","Automatic transmission","2011 Hyundai Elantra Touring SE AT","Hyundai","2011 Hyundai Elantra Touring","2011","138","136" +"238","123","229","Front-wheel drive","Hyundai 2.0L 4 cylinder 138 hp 136 ft-lbs","True","4","4 Speed Automatic","23","Gasoline","30","Automatic transmission","2011 Hyundai Elantra Touring GLS AT","Hyundai","2011 Hyundai Elantra Touring","2011","138","136" +"238","123","229","Front-wheel drive","Hyundai 2.0L 4 cylinder 138 hp 136 ft-lbs","True","5","5 Speed Manual","23","Gasoline","31","Manual transmission","2011 Hyundai Elantra Touring SE","Hyundai","2011 Hyundai Elantra Touring","2011","138","136" +"238","123","229","Front-wheel drive","Hyundai 2.0L 4 cylinder 138 hp 136 ft-lbs","True","5","5 Speed Manual","23","Gasoline","31","Manual transmission","2010 Hyundai Elantra Touring GLS","Hyundai","2010 Hyundai Elantra Touring","2010","138","136" +"238","123","229","Front-wheel drive","Hyundai 2.0L 4 cylinder 138 hp 136 ft-lbs","True","4","4 Speed Automatic","23","Gasoline","30","Automatic transmission","2010 Hyundai Elantra Touring GLS AT","Hyundai","2010 Hyundai Elantra Touring","2010","138","136" +"238","123","229","Front-wheel drive","Hyundai 2.0L 4 cylinder 138 hp 136 ft-lbs","True","5","5 Speed Manual","23","Gasoline","31","Manual transmission","2010 Hyundai Elantra Touring SE","Hyundai","2010 Hyundai Elantra Touring","2010","138","136" +"238","123","229","Front-wheel drive","Hyundai 2.0L 4 cylinder 138 hp 136 ft-lbs","True","4","4 Speed Automatic","23","Gasoline","30","Automatic transmission","2010 Hyundai Elantra Touring SE AT","Hyundai","2010 Hyundai Elantra Touring","2010","138","136" +"238","123","229","Front-wheel drive","Hyundai 2.0L 4 cylinder 138 hp 136 ft-lbs","True","5","5 Speed Manual","23","Gasoline","31","Manual transmission","2009 Hyundai Elantra Touring","Hyundai","2009 Hyundai Elantra Touring","2009","138","136" +"238","123","229","Front-wheel drive","Hyundai 2.0L 4 cylinder 138 hp 136 ft-lbs","True","4","4 Speed Automatic","23","Gasoline","30","Automatic transmission","2009 Hyundai Elantra Touring AT","Hyundai","2009 Hyundai Elantra Touring","2009","138","136" +"210","38","97","Rear-wheel drive","Hyundai 4.6L 8 Cylinder 385 hp 333 ft-lbs","True","6","6 Speed Automatic Select Shift","16","Gasoline","24","Automatic transmission","2011 Hyundai Equus Ultimate","Hyundai","2011 Hyundai Equus","2011","385","333" +"210","38","97","Rear-wheel drive","Hyundai 4.6L 8 Cylinder 385 hp 333 ft-lbs","True","6","6 Speed Automatic Select Shift","16","Gasoline","24","Automatic transmission","2011 Hyundai Equus Signature","Hyundai","2011 Hyundai Equus","2011","385","333" +"200","122","97","Rear-wheel drive","Hyundai 4.6L 8 Cylinder 385 hp 333 ft-lbs","True","8","8 Speed Automatic Select Shift","17","Gasoline","26","Automatic transmission","2012 Hyundai Genesis Sedan 4.6","Hyundai","2012 Hyundai Genesis Sedan","2012","385","333" +"195","122","97","Rear-wheel drive","Hyundai 3.8L 6 Cylinder 333 hp 291 ft-lbs","True","8","8 Speed Automatic Select Shift","19","Gasoline","29","Automatic transmission","2012 Hyundai Genesis Sedan 3.8","Hyundai","2012 Hyundai Genesis Sedan","2012","333","291" +"200","122","97","Rear-wheel drive","Hyundai 5.0L 8 Cylinder 429 hp 376 ft-lbs","True","8","8 Speed Automatic Select Shift","17","Gasoline","26","Automatic transmission","2012 Hyundai Genesis Sedan 5.0 R-Spec","Hyundai","2012 Hyundai Genesis Sedan","2012","429","376" +"119","128","229","Front-wheel drive","Kia 2.0L 4 Cylinder 156 hp 144 ft-lbs","True","5","5 Speed Manual","25","Gasoline","34","Manual transmission","2010 Kia Forte Koup EX","Kia","2010 Kia Forte Koup","2010","156","144" +"119","128","229","Front-wheel drive","Kia 2.0L 4 Cylinder 156 hp 144 ft-lbs","True","4","4 Speed Automatic Select Shift","25","Gasoline","34","Automatic transmission","2010 Kia Forte Koup EX AT","Kia","2010 Kia Forte Koup","2010","156","144" +"119","128","229","Front-wheel drive","Kia 2.4L 4 Cylinder 173 hp 168 ft-lbs","True","6","6 Speed Manual","22","Gasoline","32","Manual transmission","2010 Kia Forte Koup SX","Kia","2010 Kia Forte Koup","2010","173","168" +"119","128","229","Front-wheel drive","Kia 2.4L 4 Cylinder 173 hp 168 ft-lbs","True","5","5 Speed Automatic Select Shift","23","Gasoline","31","Automatic transmission","2010 Kia Forte Koup SX AT","Kia","2010 Kia Forte Koup","2010","173","168" +"175","235","39","Front-wheel drive","Kia 2.4L 4 Cylinder 200 hp 186 ft-lbs","True","6","6 Speed Manual","24","Gasoline","35","Manual transmission","2011 Kia Optima LX MT","Kia","2011 Kia Optima","2011","200","186" +"175","235","39","Front-wheel drive","Kia 2.4L 4 Cylinder 200 hp 186 ft-lbs","True","6","6 Speed Automatic Select Shift","24","Gasoline","34","Automatic transmission","2011 Kia Optima LX AT","Kia","2011 Kia Optima","2011","200","186" +"175","235","39","Front-wheel drive","Kia 2.4L 4 Cylinder 200 hp 186 ft-lbs","True","6","6 Speed Automatic Select Shift","24","Gasoline","34","Automatic transmission","2011 Kia Optima EX","Kia","2011 Kia Optima","2011","200","186" +"175","235","39","Front-wheel drive","Kia 2.0L 4 Cylinder 274 hp 269 ft-lbs Turbo","True","6","6 Speed Automatic Select Shift","22","Gasoline","34","Automatic transmission","2011 Kia Optima EX Turbo","Kia","2011 Kia Optima","2011","274","269" +"175","235","39","Front-wheel drive","Kia 2.0L 4 Cylinder 274 hp 269 ft-lbs Turbo","True","6","6 Speed Automatic Select Shift","22","Gasoline","34","Automatic transmission","2011 Kia Optima SX","Kia","2011 Kia Optima","2011","274","269" +"117","105","214","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Manual","26","Gasoline","34","Manual transmission","2010 Honda Civic DX Coup","Honda","2010 Honda Civic Coup","2010","140","128" +"117","105","214","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Automatic","25","Gasoline","36","Automatic transmission","2010 Honda Civic DX Coup AT","Honda","2010 Honda Civic Coup","2010","140","128" +"117","105","214","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Manual","26","Gasoline","34","Manual transmission","2010 Honda Civic LX Coup","Honda","2010 Honda Civic Coup","2010","140","128" +"117","105","214","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Automatic","25","Gasoline","36","Automatic transmission","2010 Honda Civic LX Coup AT","Honda","2010 Honda Civic Coup","2010","140","128" +"117","105","214","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Manual","26","Gasoline","34","Manual transmission","2010 Honda Civic EX Coup","Honda","2010 Honda Civic Coup","2010","140","128" +"117","105","214","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Automatic","25","Gasoline","36","Automatic transmission","2010 Honda Civic EX Coup AT","Honda","2010 Honda Civic Coup","2010","140","128" +"117","105","214","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Manual","26","Gasoline","34","Manual transmission","2010 Honda Civic EX-L Coup","Honda","2010 Honda Civic Coup","2010","140","128" +"117","105","214","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Automatic","25","Gasoline","36","Automatic transmission","2010 Honda Civic EX-L Coup AT","Honda","2010 Honda Civic Coup","2010","140","128" +"117","105","214","Front-wheel drive","Honda 2.0L 4 Cyinder 197 hp 139 ft-lbs","True","6","6 Speed Manual","21","Gasoline","29","Manual transmission","2010 Honda Civic Si Coup","Honda","2010 Honda Civic Coup","2010","197","139" +"170","235","39","Front-wheel drive","Kia 2.4L 4 Cylinder 166 hp 154 ft-lbs Hybrid","True","6","6 Speed Automatic Select Shift","36","Gasoline","40","Automatic transmission","2011 Kia Optima Hybrid","Kia","2011 Kia Optima Hybrid","2011","166","154" +"200","192","13","Front-wheel drive","Kia 2.4L 4 Cylinder 175 hp 169 ft-lbs","True","5","5 Speed Manual","22","Gasoline","32","Manual transmission","2010 Kia Optima LX","Kia","2010 Kia Optima","2010","175","169" +"200","192","13","Front-wheel drive","Kia 2.4L 4 Cylinder 175 hp 169 ft-lbs","True","5","5 Speed Automatic Select Shift","22","Gasoline","32","Automatic transmission","2010 Kia Optima LX AT","Kia","2010 Kia Optima","2010","175","169" +"200","192","13","Front-wheel drive","Kia 2.4L 4 Cylinder 175 hp 169 ft-lbs","True","5","5 Speed Automatic Select Shift","22","Gasoline","32","Automatic transmission","2010 Kia Optima EX","Kia","2010 Kia Optima","2010","175","169" +"200","192","13","Front-wheel drive","Kia 2.7L 6 Cylinder 194 hp 184 ft-lbs","True","5","5 Speed Automatic Select Shift","20","Gasoline","28","Automatic transmission","2010 Kia Optima EX V6","Kia","2010 Kia Optima","2010","194","184" +"200","192","13","Front-wheel drive","Kia 2.4L 4 Cylinder 175 hp 169 ft-lbs","True","5","5 Speed Automatic Select Shift","22","Gasoline","32","Automatic transmission","2010 Kia Optima SX","Kia","2010 Kia Optima","2010","175","169" +"200","192","13","Front-wheel drive","Kia 2.7L 6 Cylinder 194 hp 184 ft-lbs","True","5","5 Speed Automatic Select Shift","20","Gasoline","28","Automatic transmission","2010 Kia Optima SX V6","Kia","2010 Kia Optima","2010","194","184" +"190","143","158","Front-wheel drive","Kia 1.6L 4 Cylinder 110 hp 107 ft-lbs","True","5","5 Speed Manual","28","Gasoline","34","Manual transmission","2011 Kia Rio","Kia","2011 Kia Rio","2011","110","107" +"190","143","158","Front-wheel drive","Kia 1.6L 4 Cylinder 110 hp 107 ft-lbs","True","4","4 Speed Automatic","27","Gasoline","36","Automatic transmission","2011 Kia Rio LX","Kia","2011 Kia Rio","2011","110","107" +"190","143","158","Front-wheel drive","Kia 1.6L 4 Cylinder 110 hp 107 ft-lbs","True","4","4 Speed Automatic","27","Gasoline","36","Automatic transmission","2011 Kia Rio SX","Kia","2011 Kia Rio","2011","110","107" +"195","111","97","Rear-wheel drive","Hyundai 3.8L 6 cylinder 290hp 264 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","27","Automatic transmission","2011 Hyundai Genesis Sedan 3.8","Hyundai","2011 Hyundai Genesis Sedan","2011","290","264" +"200","111","97","Rear-wheel drive","Hyundai 4.6L 8 Cylinder 385 hp 333 ft-lbs","True","6","6 Speed Automatic Select Shift","17","Gasoline","25","Automatic transmission","2011 Hyundai Genesis Sedan 4.6","Hyundai","2011 Hyundai Genesis Sedan","2011","385","333" +"200","111","97","Rear-wheel drive","Hyundai 4.6L 8 cylinder 368hp 324 ft-lbs","True","6","6 Speed Automatic Select Shift","17","Gasoline","25","Automatic transmission","2010 Hyundai Genesis Sedan 4.6","Hyundai","2010 Hyundai Genesis Sedan","2010","368","324" +"195","111","97","Rear-wheel drive","Hyundai 3.8L 6 cylinder 290hp 264 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","27","Automatic transmission","2010 Hyundai Genesis Sedan 3.8","Hyundai","2010 Hyundai Genesis Sedan","2010","290","264" +"104","22","72","Rear-wheel drive","Hyundai 2.0L 4 Cylinder 210 hp 223 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","30","Manual transmission","2012 Hyundai Genesis Coupe 2.0T","Hyundai","2012 Hyundai Genesis Coupe","2012","210","223" +"104","22","72","Rear-wheel drive","Hyundai 3.8L 6 Cylinder 306 hp 266 ft-lbs","True","6","6 Speed Manual","17","Gasoline","26","Manual transmission","2012 Hyundai Genesis Coupe 3.8 Track","Hyundai","2012 Hyundai Genesis Coupe","2012","306","266" +"104","22","72","Rear-wheel drive","Hyundai 3.8L 6 Cylinder 306 hp 266 ft-lbs","True","6","6 Speed Automatic Select Shift","17","Gasoline","27","Automatic transmission","2012 Hyundai Genesis Coupe 3.8 Grand Touring","Hyundai","2012 Hyundai Genesis Coupe","2012","306","266" +"104","22","72","Rear-wheel drive","Hyundai 2.0L 4 Cylinder 210 hp 223 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","30","Manual transmission","2012 Hyundai Genesis Coupe 2.0T R-Spec","Hyundai","2012 Hyundai Genesis Coupe","2012","210","223" +"104","22","72","Rear-wheel drive","Hyundai 2.0L 4 Cylinder 210 hp 223 ft-lbs Turbo","True","5","5 Speed Automatic Select Shift","20","Gasoline","30","Automatic transmission","2012 Hyundai Genesis Coupe 2.0T AT","Hyundai","2012 Hyundai Genesis Coupe","2012","210","223" +"104","22","72","Rear-wheel drive","Hyundai 3.8L 6 Cylinder 306 hp 266 ft-lbs","True","6","6 Speed Manual","17","Gasoline","26","Manual transmission","2012 Hyundai Genesis Coupe 3.8 R-Spec","Hyundai","2012 Hyundai Genesis Coupe","2012","306","266" +"104","22","72","Rear-wheel drive","Hyundai 3.8L 6 Cylinder 306 hp 266 ft-lbs","True","6","6 Speed Automatic Select Shift","17","Gasoline","27","Automatic transmission","2012 Hyundai Genesis Coupe 3.8 Track AT","Hyundai","2012 Hyundai Genesis Coupe","2012","306","266" +"104","22","72","Rear-wheel drive","Hyundai 2.0L 4 Cylinder 210 hp 223 ft-lbs Turbo","True","5","5 Speed Automatic Select Shift","20","Gasoline","30","Automatic transmission","2012 Hyundai Genesis Coupe 2.0T Premium","Hyundai","2012 Hyundai Genesis Coupe","2012","210","223" +"104","22","72","Rear-wheel drive","Hyundai 2.0L 4 Cylinder 210 hp 223 ft-lbs Turbo","True","5","5 Speed Automatic Select Shift","20","Gasoline","30","Automatic transmission","2011 Hyundai Genesis Coupe 2.0T AT","Hyundai","2011 Hyundai Genesis Coupe","2011","210","223" +"104","22","72","Rear-wheel drive","Hyundai 2.0L 4 Cylinder 210 hp 223 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","30","Manual transmission","2011 Hyundai Genesis Coupe 2.0T","Hyundai","2011 Hyundai Genesis Coupe","2011","210","223" +"104","22","72","Rear-wheel drive","Hyundai 2.0L 4 Cylinder 210 hp 223 ft-lbs Turbo","True","5","5 Speed Automatic Select Shift","20","Gasoline","30","Automatic transmission","2011 Hyundai Genesis Coupe 2.0T Premium","Hyundai","2011 Hyundai Genesis Coupe","2011","210","223" +"104","22","72","Rear-wheel drive","Hyundai 3.8L 6 Cylinder 306 hp 266 ft-lbs","True","6","6 Speed Automatic Select Shift","17","Gasoline","27","Automatic transmission","2011 Hyundai Genesis Coupe 3.8 Grand Touring","Hyundai","2011 Hyundai Genesis Coupe","2011","306","266" +"104","22","72","Rear-wheel drive","Hyundai 3.8L 6 Cylinder 306 hp 266 ft-lbs","True","6","6 Speed Manual","17","Gasoline","26","Manual transmission","2011 Hyundai Genesis Coupe 3.8 R-Spec","Hyundai","2011 Hyundai Genesis Coupe","2011","306","266" +"104","22","72","Rear-wheel drive","Hyundai 2.0L 4 Cylinder 210 hp 223 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","30","Manual transmission","2011 Hyundai Genesis Coupe 2.0T R-Spec","Hyundai","2011 Hyundai Genesis Coupe","2011","210","223" +"104","22","72","Rear-wheel drive","Hyundai 3.8L 6 Cylinder 306 hp 266 ft-lbs","True","6","6 Speed Manual","17","Gasoline","26","Manual transmission","2011 Hyundai Genesis Coupe 3.8 Track","Hyundai","2011 Hyundai Genesis Coupe","2011","306","266" +"104","22","72","Rear-wheel drive","Hyundai 3.8L 6 Cylinder 306 hp 266 ft-lbs","True","6","6 Speed Automatic Select Shift","17","Gasoline","27","Automatic transmission","2011 Hyundai Genesis Coupe 3.8 Track AT","Hyundai","2011 Hyundai Genesis Coupe","2011","306","266" +"104","22","72","Rear-wheel drive","Hyundai 2.0L 4 Cylinder 210 hp 223 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","30","Manual transmission","2010 Hyundai Genesis Coupe 2.0T Premium","Hyundai","2010 Hyundai Genesis Coupe","2010","210","223" +"104","22","72","Rear-wheel drive","Hyundai 3.8L 6 Cylinder 306 hp 266 ft-lbs","True","6","6 Speed Automatic Select Shift","17","Gasoline","27","Automatic transmission","2010 Hyundai Genesis Coupe 3.8 AT","Hyundai","2010 Hyundai Genesis Coupe","2010","306","266" +"104","22","72","Rear-wheel drive","Hyundai 3.8L 6 Cylinder 306 hp 266 ft-lbs","True","6","6 Speed Automatic Select Shift","17","Gasoline","27","Automatic transmission","2010 Hyundai Genesis Coupe 3.8 Track AT","Hyundai","2010 Hyundai Genesis Coupe","2010","306","266" +"104","22","72","Rear-wheel drive","Hyundai 2.0L 4 Cylinder 210 hp 223 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","30","Manual transmission","2010 Hyundai Genesis Coupe 2.0T R-Spec","Hyundai","2010 Hyundai Genesis Coupe","2010","210","223" +"104","22","72","Rear-wheel drive","Hyundai 2.0L 4 Cylinder 210 hp 223 ft-lbs Turbo","True","5","5 Speed Automatic Select Shift","20","Gasoline","30","Automatic transmission","2010 Hyundai Genesis Coupe 2.0T Premium AT","Hyundai","2010 Hyundai Genesis Coupe","2010","210","223" +"104","22","72","Rear-wheel drive","Hyundai 2.0L 4 Cylinder 210 hp 223 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","30","Manual transmission","2010 Hyundai Genesis Coupe 2.0T Track","Hyundai","2010 Hyundai Genesis Coupe","2010","210","223" +"104","22","72","Rear-wheel drive","Hyundai 3.8L 6 Cylinder 306 hp 266 ft-lbs","True","6","6 Speed Manual","17","Gasoline","26","Manual transmission","2010 Hyundai Genesis Coupe 3.8","Hyundai","2010 Hyundai Genesis Coupe","2010","306","266" +"104","22","72","Rear-wheel drive","Hyundai 3.8L 6 Cylinder 306 hp 266 ft-lbs","True","6","6 Speed Automatic Select Shift","17","Gasoline","27","Automatic transmission","2010 Hyundai Genesis Coupe 3.8 Grand Touring AT","Hyundai","2010 Hyundai Genesis Coupe","2010","306","266" +"104","22","72","Rear-wheel drive","Hyundai 3.8L 6 Cylinder 306 hp 266 ft-lbs","True","6","6 Speed Manual","17","Gasoline","26","Manual transmission","2010 Hyundai Genesis Coupe 3.8 Track","Hyundai","2010 Hyundai Genesis Coupe","2010","306","266" +"104","22","72","Rear-wheel drive","Hyundai 2.0L 4 Cylinder 210 hp 223 ft-lbs Turbo","True","5","5 Speed Automatic Select Shift","20","Gasoline","30","Automatic transmission","2010 Hyundai Genesis Coupe 2.0T AT","Hyundai","2010 Hyundai Genesis Coupe","2010","210","223" +"104","22","72","Rear-wheel drive","Hyundai 3.8L 6 Cylinder 306 hp 266 ft-lbs","True","6","6 Speed Manual","17","Gasoline","26","Manual transmission","2010 Hyundai Genesis Coupe 3.8 Grand Touring","Hyundai","2010 Hyundai Genesis Coupe","2010","306","266" +"104","22","72","Rear-wheel drive","Hyundai 2.0L 4 Cylinder 210 hp 223 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","30","Manual transmission","2010 Hyundai Genesis Coupe 2.0T","Hyundai","2010 Hyundai Genesis Coupe","2010","210","223" +"157","118","3","Rear-wheel drive","Mercedes-AMG 6.3L 8 Cylinder 451 hp 443 ft-lbs","True","7","7 Speed Automatic Select Shift","12","Gasoline","19","Automatic transmission","2010 Mercedes-Benz C63 AMG Sport","AMG","2010 Mercedes-Benz C-Class","2010","451","443" +"188","115","242","Front-wheel drive","Volkswagen 2.0L 4 Cylinder 200 hp 207 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","31","Manual transmission","2010 Volkswagen GTI 2-Door","Volkswagen","2010 Volkswagen GTI 2-Door","2010","200","207" +"188","115","242","Front-wheel drive","Volkswagen 2.0L 4 Cylinder 200 hp 207 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","31","Manual transmission","2011 Volkswagen GTI 2-Door","Volkswagen","2011 Volkswagen GTI 2-Door","2011","200","207" +"137","169","85","Rear-wheel drive","Ford 3.7L 6 Cylinder 305 hp 280 ft-lbs","True","6","6 Speed Manual","19","Gasoline","29","Manual transmission","2012 Ford Mustang V6","Ford","2012 Ford Mustang Coup","2012","305","280" +"137","169","85","Rear-wheel drive","Ford 3.7L 6 Cylinder 305 hp 280 ft-lbs","True","6","6 Speed Automatic","19","Gasoline","31","Automatic transmission","2012 Ford Mustang V6 AT","Ford","2012 Ford Mustang Coup","2012","305","280" +"137","169","85","Rear-wheel drive","Ford 3.7L 6 Cylinder 305 hp 280 ft-lbs","True","6","6 Speed Manual","19","Gasoline","29","Manual transmission","2012 Ford Mustang V6 Premium","Ford","2012 Ford Mustang Coup","2012","305","280" +"137","169","85","Rear-wheel drive","Ford 3.7L 6 Cylinder 305 hp 280 ft-lbs","True","6","6 Speed Automatic","19","Gasoline","31","Automatic transmission","2012 Ford Mustang V6 Premium AT","Ford","2012 Ford Mustang Coup","2012","305","280" +"137","169","85","Rear-wheel drive","Ford 5.0L 8 Cylinder 412 hp 390 ft-lbs","True","6","6 Speed Manual","17","Gasoline","26","Manual transmission","2012 Ford Mustang GT","Ford","2012 Ford Mustang Coup","2012","412","390" +"137","169","85","Rear-wheel drive","Ford 5.0L 8 Cylinder 412 hp 390 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","25","Automatic transmission","2012 Ford Mustang GT AT","Ford","2012 Ford Mustang Coup","2012","412","390" +"137","169","85","Rear-wheel drive","Ford 5.0L 8 Cylinder 412 hp 390 ft-lbs","True","6","6 Speed Manual","17","Gasoline","26","Manual transmission","2012 Ford Mustang GT Premium","Ford","2012 Ford Mustang Coup","2012","412","390" +"137","169","85","Rear-wheel drive","Ford 5.0L 8 Cylinder 412 hp 390 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","25","Automatic transmission","2012 Ford Mustang GT Premium AT","Ford","2012 Ford Mustang Coup","2012","412","390" +"119","169","85","Rear-wheel drive","Ford 5.0L 8 Cylinder 444 hp 380 ft-lbs","True","6","6 Speed Manual","17","Gasoline","26","Manual transmission","2012 Ford Mustang Boss 302","Ford","2012 Ford Mustang Coup","2012","444","380" +"165","22","234","All-wheel drive","Mercedes-Benz 3.0L 6 Cylinders 228 hp 221 ft-lbs FFV","True","7","7 Speed Automatic Select Shift","18","Gasoline","25","Automatic transmission","2010 Mercedes-Benz C300 Luxury 4MATIC","Mercedes","2010 Mercedes-Benz C-Class","2010","228","221" +"137","169","85","Rear-wheel drive","Ford 3.7L 6 Cylinder 305 hp 280 ft-lbs","True","6","6 Speed Manual","19","Gasoline","30","Manual transmission","2012 Ford Mustang V6 Convertible","Ford","2012 Ford Mustang Convertible","2012","305","280" +"137","169","85","Rear-wheel drive","Ford 3.7L 6 Cylinder 305 hp 280 ft-lbs","True","6","6 Speed Automatic","19","Gasoline","30","Automatic transmission","2012 Ford Mustang V6 Convertible AT","Ford","2012 Ford Mustang Convertible","2012","305","280" +"137","169","85","Rear-wheel drive","Ford 3.7L 6 Cylinder 305 hp 280 ft-lbs","True","6","6 Speed Manual","19","Gasoline","30","Manual transmission","2012 Ford Mustang V6 Premium Convertible","Ford","2012 Ford Mustang Convertible","2012","305","280" +"137","169","85","Rear-wheel drive","Ford 3.7L 6 Cylinder 305 hp 280 ft-lbs","True","6","6 Speed Automatic","19","Gasoline","30","Automatic transmission","2012 Ford Mustang V6 Premium Convertible AT","Ford","2012 Ford Mustang Convertible","2012","305","280" +"137","169","85","Rear-wheel drive","Ford 5.0L 8 Cylinder 412 hp 390 ft-lbs","True","6","6 Speed Manual","19","Gasoline","30","Manual transmission","2012 Ford Mustang GT Convertible","Ford","2012 Ford Mustang Convertible","2012","412","390" +"137","169","85","Rear-wheel drive","Ford 5.0L 8 Cylinder 412 hp 390 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","25","Automatic transmission","2012 Ford Mustang GT Convertible AT","Ford","2012 Ford Mustang Convertible","2012","412","390" +"137","169","85","Rear-wheel drive","Ford 5.0L 8 Cylinder 412 hp 390 ft-lbs","True","6","6 Speed Manual","19","Gasoline","30","Manual transmission","2012 Ford Mustang GT Premium Convertible","Ford","2012 Ford Mustang Convertible","2012","412","390" +"137","169","85","Rear-wheel drive","Ford 5.0L 8 Cylinder 412 hp 390 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","25","Automatic transmission","2012 Ford Mustang GT Premium Convertible AT","Ford","2012 Ford Mustang Convertible","2012","412","390" +"144","169","85","Rear-wheel drive","Ford 3.7L 6 Cylinder 305 hp 280 ft-lbs","True","6","6 Speed Manual","19","Gasoline","29","Manual transmission","2011 Ford Mustang V6 Convertible","Ford","2011 Ford Mustang Convertible","2011","305","280" +"144","169","85","Rear-wheel drive","Ford 3.7L 6 Cylinder 305 hp 280 ft-lbs","True","6","6 Speed Automatic","19","Gasoline","30","Automatic transmission","2011 Ford Mustang V6 Convertible AT","Ford","2011 Ford Mustang Convertible","2011","305","280" +"144","169","85","Rear-wheel drive","Ford 3.7L 6 Cylinder 305 hp 280 ft-lbs","True","6","6 Speed Manual","19","Gasoline","29","Manual transmission","2011 Ford Mustang V6 Premium Convertible","Ford","2011 Ford Mustang Convertible","2011","305","280" +"144","169","85","Rear-wheel drive","Ford 3.7L 6 Cylinder 305 hp 280 ft-lbs","True","6","6 Speed Automatic","19","Gasoline","30","Automatic transmission","2011 Ford Mustang V6 Premium Convertible AT","Ford","2011 Ford Mustang Convertible","2011","305","280" +"137","169","85","Rear-wheel drive","Ford 5.0L 8 Cylinder 412 hp 390 ft-lbs","True","6","6 Speed Manual","17","Gasoline","26","Manual transmission","2011 Ford Mustang GT Convertible","Ford","2011 Ford Mustang Convertible","2011","412","390" +"137","169","85","Rear-wheel drive","Ford 5.0L 8 Cylinder 412 hp 390 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","25","Automatic transmission","2011 Ford Mustang GT Convertible AT","Ford","2011 Ford Mustang Convertible","2011","412","390" +"137","169","85","Rear-wheel drive","Ford 5.0L 8 Cylinder 412 hp 390 ft-lbs","True","6","6 Speed Manual","17","Gasoline","26","Manual transmission","2011 Ford Mustang GT Premium Convertible","Ford","2011 Ford Mustang Convertible","2011","412","390" +"137","169","85","Rear-wheel drive","Ford 5.0L 8 Cylinder 412 hp 390 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","25","Automatic transmission","2011 Ford Mustang GT Premium Convertible AT","Ford","2011 Ford Mustang Convertible","2011","412","390" +"144","169","85","Rear-wheel drive","Ford 3.7L 6 Cylinder 305 hp 280 ft-lbs","True","6","6 Speed Manual","19","Gasoline","29","Manual transmission","2011 Ford Mustang V6","Ford","2011 Ford Mustang Coup","2011","305","280" +"144","169","85","Rear-wheel drive","Ford 3.7L 6 Cylinder 305 hp 280 ft-lbs","True","6","6 Speed Automatic","19","Gasoline","31","Automatic transmission","2011 Ford Mustang V6 AT","Ford","2011 Ford Mustang Coup","2011","305","280" +"144","169","85","Rear-wheel drive","Ford 3.7L 6 Cylinder 305 hp 280 ft-lbs","True","6","6 Speed Manual","19","Gasoline","29","Manual transmission","2011 Ford Mustang V6 Premium","Ford","2011 Ford Mustang Coup","2011","305","280" +"144","169","85","Rear-wheel drive","Ford 3.7L 6 Cylinder 305 hp 280 ft-lbs","True","6","6 Speed Automatic","19","Gasoline","31","Automatic transmission","2011 Ford Mustang V6 Premium AT","Ford","2011 Ford Mustang Coup","2011","305","280" +"137","169","85","Rear-wheel drive","Ford 5.0L 8 Cylinder 412 hp 390 ft-lbs","True","6","6 Speed Manual","17","Gasoline","26","Manual transmission","2011 Ford Mustang GT","Ford","2011 Ford Mustang Coup","2011","412","390" +"137","169","85","Rear-wheel drive","Ford 5.0L 8 Cylinder 412 hp 390 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","25","Automatic transmission","2011 Ford Mustang GT AT","Ford","2011 Ford Mustang Coup","2011","412","390" +"137","169","85","Rear-wheel drive","Ford 5.0L 8 Cylinder 412 hp 390 ft-lbs","True","6","6 Speed Manual","17","Gasoline","26","Manual transmission","2011 Ford Mustang GT Premium","Ford","2011 Ford Mustang Coup","2011","412","390" +"137","169","85","Rear-wheel drive","Ford 5.0L 8 Cylinder 412 hp 390 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","25","Automatic transmission","2011 Ford Mustang GT Premium AT","Ford","2011 Ford Mustang Coup","2011","412","390" +"150","22","234","Rear-wheel drive","Mercedes-Benz 3.0L 6 Cylinders 228 hp 221 ft-lbs FFV","True","6","6 Speed Manual","18","Gasoline","26","Manual transmission","2011 Mercedes-Benz C300 Sport FFV","Mercedes","2011 Mercedes-Benz C-Class","2011","228","221" +"157","118","3","Rear-wheel drive","Mercedes-AMG 6.3L 8 Cylinder 451 hp 443 ft-lbs","True","7","7 Speed Automatic Select Shift","13","Gasoline","19","Automatic transmission","2011 Mercedes-Benz C63 AMG Sport","AMG","2011 Mercedes-Benz C-Class","2011","451","443" +"165","22","234","All-wheel drive","Mercedes-Benz 3.0L 6 Cylinder 228 hp 221 ft-lbs","True","7","7 Speed Automatic Select Shift","18","Gasoline","25","Automatic transmission","2011 Mercedes-Benz C300 Luxury 4MATIC","Mercedes","2011 Mercedes-Benz C-Class","2011","228","221" +"165","22","234","Rear-wheel drive","Mercedes-Benz 3.0L 6 Cylinders 228 hp 221 ft-lbs FFV","True","7","7 Speed Automatic Select Shift","18","Gasoline","26","Automatic transmission","2011 Mercedes-Benz C300 Luxury","Mercedes","2011 Mercedes-Benz C-Class","2011","228","221" +"150","22","234","Rear-wheel drive","Mercedes-Benz 3.5L 6 Cylinders 268 hp 258 ft-lbs","True","7","7 Speed Automatic Select Shift","17","Gasoline","25","Automatic transmission","2011 Mercedes-Benz C350 Sport","Mercedes","2011 Mercedes-Benz C-Class","2011","268","258" +"150","22","234","Rear-wheel drive","Mercedes-Benz 3.0L 6 Cylinders 228 hp 221 ft-lbs FFV","True","7","7 Speed Automatic Select Shift","13","E85","19","Automatic transmission","2011 Mercedes-Benz C300 Sport AT FFV","Mercedes","2011 Mercedes-Benz C-Class","2011","228","221" +"190","175","158","Front-wheel drive","Kia 1.6L 4 Cylinder 110 hp 107 ft-lbs","True","4","4 Speed Automatic","27","Gasoline","36","Automatic transmission","2011 Kia Rio5 LX","Kia","2011 Kia Rio5","2011","110","107" +"190","175","158","Front-wheel drive","Kia 1.6L 4 Cylinder 110 hp 107 ft-lbs","True","4","4 Speed Automatic","27","Gasoline","36","Automatic transmission","2011 Kia Rio5 SX","Kia","2011 Kia Rio5","2011","110","107" +"190","185","158","Front-wheel drive","Kia 1.6L 4 Cylinder 110 hp 107 ft-lbs","True","5","5 Speed Manual","28","Gasoline","34","Manual transmission","2010 Kia Rio5 LX","Kia","2010 Kia Rio5","2010","110","107" +"190","185","158","Front-wheel drive","Kia 1.6L 4 Cylinder 110 hp 107 ft-lbs","True","4","4 Speed Automatic","27","Gasoline","36","Automatic transmission","2010 Kia Rio5 LX AT","Kia","2010 Kia Rio5","2010","110","107" +"190","185","158","Front-wheel drive","Kia 1.6L 4 Cylinder 110 hp 107 ft-lbs","True","5","5 Speed Manual","28","Gasoline","34","Manual transmission","2010 Kia Rio5 SX","Kia","2010 Kia Rio5","2010","110","107" +"190","185","158","Front-wheel drive","Kia 1.6L 4 Cylinder 110 hp 107 ft-lbs","True","4","4 Speed Automatic","27","Gasoline","36","Automatic transmission","2010 Kia Rio5 SX AT","Kia","2010 Kia Rio5","2010","110","107" +"188","115","242","Front-wheel drive","Volkswagen 2.0L 4 Cylinder 200 hp 207 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","31","Manual transmission","2011 Volkswagen GTI 4-Door","Volkswagen","2011 Volkswagen GTI 4-Door","2011","200","207" +"190","153","158","Front-wheel drive","Kia 1.6L 4 Cylinder 110 hp 107 ft-lbs","True","5","5 Speed Manual","28","Gasoline","34","Manual transmission","2010 Kia Rio","Kia","2010 Kia Rio","2010","110","107" +"190","153","158","Front-wheel drive","Kia 1.6L 4 Cylinder 110 hp 107 ft-lbs","True","5","5 Speed Manual","28","Gasoline","34","Manual transmission","2010 Kia Rio LX","Kia","2010 Kia Rio","2010","110","107" +"190","153","158","Front-wheel drive","Kia 1.6L 4 Cylinder 110 hp 107 ft-lbs","True","4","4 Speed Automatic","27","Gasoline","36","Automatic transmission","2010 Kia Rio LX AT","Kia","2010 Kia Rio","2010","110","107" +"190","153","158","Front-wheel drive","Kia 1.6L 4 Cylinder 110 hp 107 ft-lbs","True","5","5 Speed Manual","28","Gasoline","34","Manual transmission","2010 Kia Rio SX","Kia","2010 Kia Rio","2010","110","107" +"190","153","158","Front-wheel drive","Kia 1.6L 4 Cylinder 110 hp 107 ft-lbs","True","4","4 Speed Automatic","27","Gasoline","36","Automatic transmission","2010 Kia Rio SX AT","Kia","2010 Kia Rio","2010","110","107" +"74","8","249","Front-wheel drive","Kia 1.6L 4 Cylinder 122 hp 115 ft-lbs","True","5","5 Speed Manual","26","Gasoline","31","Manual transmission","2011 Kia Soul","Kia","2011 Kia Soul","2011","122","115" +"74","8","249","Front-wheel drive","Kia 2.0L 4 Cylinder 142 hp 137 ft-lbs","True","5","5 Speed Manual","24","Gasoline","30","Manual transmission","2011 Kia Soul +","Kia","2011 Kia Soul","2011","142","137" +"74","8","249","Front-wheel drive","Kia 2.0L 4 Cylinder 142 hp 137 ft-lbs","True","4","4 Speed Automatic","24","Gasoline","30","Automatic transmission","2011 Kia Soul + AT","Kia","2011 Kia Soul","2011","142","137" +"74","8","249","Front-wheel drive","Kia 2.0L 4 Cylinder 142 hp 137 ft-lbs","True","4","4 Speed Automatic","24","Gasoline","30","Automatic transmission","2011 Kia Soul !","Kia","2011 Kia Soul","2011","142","137" +"74","8","249","Front-wheel drive","Kia 2.0L 4 Cylinder 142 hp 137 ft-lbs","True","4","4 Speed Automatic","24","Gasoline","30","Automatic transmission","2011 Kia Soul Sport","Kia","2011 Kia Soul","2011","142","137" +"96","228","125","Rear-wheel drive","Chevrolet 3.6L 6 Cylinder 312 hp 278 ft-lbs","True","6","6 Speed Manual","17","Gasoline","28","Manual transmission","2011 Chevrolet Camaro Coupe 1LS","Chevrolet","2011 Chevrolet Camaro Coupe","2011","312","278" +"96","228","125","Rear-wheel drive","Chevrolet 3.6L 6 Cylinder 312 hp 278 ft-lbs","True","6","6 Speed Automatic","19","Gasoline","30","Automatic transmission","2011 Chevrolet Camaro Coupe 1LS AT","Chevrolet","2011 Chevrolet Camaro Coupe","2011","312","278" +"96","228","125","Rear-wheel drive","Chevrolet 3.6L 6 Cylinder 312 hp 278 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","29","Automatic transmission","2011 Chevrolet Camaro Coupe 2LS","Chevrolet","2011 Chevrolet Camaro Coupe","2011","312","278" +"96","228","125","Rear-wheel drive","Chevrolet 3.6L 6 Cylinder 312 hp 278 ft-lbs","True","6","6 Speed Manual","17","Gasoline","28","Manual transmission","2011 Chevrolet Camaro Coupe 1LT","Chevrolet","2011 Chevrolet Camaro Coupe","2011","312","278" +"96","228","125","Rear-wheel drive","Chevrolet 3.6L 6 Cylinder 312 hp 278 ft-lbs","True","6","6 Speed Automatic","19","Gasoline","30","Automatic transmission","2011 Chevrolet Camaro Coupe 1LT AT","Chevrolet","2011 Chevrolet Camaro Coupe","2011","312","278" +"96","228","125","Rear-wheel drive","Chevrolet 3.6L 6 Cylinder 312 hp 278 ft-lbs","True","6","6 Speed Manual","17","Gasoline","28","Manual transmission","2011 Chevrolet Camaro Coupe 2LT","Chevrolet","2011 Chevrolet Camaro Coupe","2011","312","278" +"96","228","125","Rear-wheel drive","Chevrolet 3.6L 6 Cylinder 312 hp 278 ft-lbs","True","6","6 Speed Automatic","19","Gasoline","30","Automatic transmission","2011 Chevrolet Camaro Coupe 2LT AT","Chevrolet","2011 Chevrolet Camaro Coupe","2011","312","278" +"96","228","125","Rear-wheel drive","Chevrolet 6.2L 8 Cylinder 426 hp 420 ft-lbs","True","6","6 Speed Manual","16","Gasoline","24","Manual transmission","2011 Chevrolet Camaro Coupe 1SS","Chevrolet","2011 Chevrolet Camaro Coupe","2011","426","420" +"96","228","125","Rear-wheel drive","Chevrolet 6.2L 8 Cylinder 426 hp 420 ft-lbs","True","6","6 Speed Automatic","16","Gasoline","25","Automatic transmission","2011 Chevrolet Camaro Coupe 1SS AT","Chevrolet","2011 Chevrolet Camaro Coupe","2011","426","420" +"96","228","125","Rear-wheel drive","Chevrolet 6.2L 8 Cylinder 426 hp 420 ft-lbs","True","6","6 Speed Manual","16","Gasoline","24","Manual transmission","2011 Chevrolet Camaro Coupe 2SS","Chevrolet","2011 Chevrolet Camaro Coupe","2011","426","420" +"96","228","125","Rear-wheel drive","Chevrolet 6.2L 8 Cylinder 426 hp 420 ft-lbs","True","6","6 Speed Automatic","16","Gasoline","25","Automatic transmission","2011 Chevrolet Camaro Coupe 2SS AT","Chevrolet","2011 Chevrolet Camaro Coupe","2011","426","420" +"132","169","85","Rear-wheel drive","Ford 4.0L 6 cylinder 210 hp 240 ft-lbs","True","5","5 Speed Manual","18","Gasoline","26","Manual transmission","2010 Ford Mustang V6","Ford","2010 Ford Mustang Coup","2010","210","240" +"132","169","85","Rear-wheel drive","Ford 4.0L 6 cylinder 210 hp 240 ft-lbs","True","5","5 Speed Automatic","16","Gasoline","24","Automatic transmission","2010 Ford Mustang V6 AT","Ford","2010 Ford Mustang Coup","2010","210","240" +"132","169","85","Rear-wheel drive","Ford 4.0L 6 cylinder 210 hp 240 ft-lbs","True","5","5 Speed Manual","18","Gasoline","26","Manual transmission","2010 Ford Mustang V6 Premium","Ford","2010 Ford Mustang Coup","2010","210","240" +"132","169","85","Rear-wheel drive","Ford 4.0L 6 cylinder 210 hp 240 ft-lbs","True","5","5 Speed Automatic","16","Gasoline","24","Automatic transmission","2010 Ford Mustang V6 Premium AT","Ford","2010 Ford Mustang Coup","2010","210","240" +"132","169","85","Rear-wheel drive","Ford 4.6L 8 Cylinder 315 hp 325 ft-lbs","True","5","5 Speed Manual","16","Gasoline","24","Manual transmission","2010 Ford Mustang GT","Ford","2010 Ford Mustang Coup","2010","315","325" +"132","169","85","Rear-wheel drive","Ford 4.6L 8 Cylinder 315 hp 325 ft-lbs","True","5","5 Speed Automatic","17","Gasoline","23","Automatic transmission","2010 Ford Mustang GT AT","Ford","2010 Ford Mustang Coup","2010","315","325" +"132","169","85","Rear-wheel drive","Ford 4.6L 8 Cylinder 315 hp 325 ft-lbs","True","5","5 Speed Manual","16","Gasoline","24","Manual transmission","2010 Ford Mustang GT Premium","Ford","2010 Ford Mustang Coup","2010","315","325" +"132","169","85","Rear-wheel drive","Ford 4.6L 8 Cylinder 315 hp 325 ft-lbs","True","5","5 Speed Automatic","17","Gasoline","23","Automatic transmission","2010 Ford Mustang GT Premium","Ford","2010 Ford Mustang Coup","2010","315","325" +"74","8","249","Front-wheel drive","Kia 1.6L 4 Cylinder 122 hp 115 ft-lbs","True","5","5 Speed Manual","26","Gasoline","31","Manual transmission","2010 Kia Soul","Kia","2010 Kia Soul","2010","122","115" +"74","8","249","Front-wheel drive","Kia 2.0L 4 Cylinder 142 hp 137 ft-lbs","True","5","5 Speed Manual","24","Gasoline","30","Manual transmission","2010 Kia Soul +","Kia","2010 Kia Soul","2010","142","137" +"74","8","249","Front-wheel drive","Kia 2.0L 4 Cylinder 142 hp 137 ft-lbs","True","4","4 Speed Automatic","24","Gasoline","30","Automatic transmission","2010 Kia Soul + AT","Kia","2010 Kia Soul","2010","142","137" +"74","8","249","Front-wheel drive","Kia 2.0L 4 Cylinder 142 hp 137 ft-lbs","True","5","5 Speed Manual","24","Gasoline","30","Manual transmission","2010 Kia Soul !","Kia","2010 Kia Soul","2010","142","137" +"74","8","249","Front-wheel drive","Kia 2.0L 4 Cylinder 142 hp 137 ft-lbs","True","4","4 Speed Automatic","24","Gasoline","30","Automatic transmission","2010 Kia Soul ! AT","Kia","2010 Kia Soul","2010","142","137" +"74","8","249","Front-wheel drive","Kia 2.0L 4 Cylinder 142 hp 137 ft-lbs","True","5","5 Speed Manual","24","Gasoline","30","Manual transmission","2010 Kia Soul Sport","Kia","2010 Kia Soul","2010","142","137" +"74","8","249","Front-wheel drive","Kia 2.0L 4 Cylinder 142 hp 137 ft-lbs","True","4","4 Speed Automatic","24","Gasoline","30","Automatic transmission","2010 Kia Soul Sport AT","Kia","2010 Kia Soul","2010","142","137" +"144","169","85","Rear-wheel drive","Ford 4.0L 6 cylinder 210 hp 240 ft-lbs","True","5","5 Speed Manual","18","Gasoline","26","Manual transmission","2010 Ford Mustang V6 Convertible","Ford","2010 Ford Mustang Convertible","2010","210","240" +"144","169","85","Rear-wheel drive","Ford 4.0L 6 cylinder 210 hp 240 ft-lbs","True","5","5 Speed Automatic","16","Gasoline","24","Automatic transmission","2010 Ford Mustang V6 Convertible AT","Ford","2010 Ford Mustang Convertible","2010","210","240" +"144","169","85","Rear-wheel drive","Ford 4.0L 6 cylinder 210 hp 240 ft-lbs","True","5","5 Speed Manual","18","Gasoline","26","Manual transmission","2010 Ford Mustang V6 Premium Convertible","Ford","2010 Ford Mustang Convertible","2010","210","240" +"144","169","85","Rear-wheel drive","Ford 4.0L 6 cylinder 210 hp 240 ft-lbs","True","5","5 Speed Automatic","16","Gasoline","24","Automatic transmission","2010 Ford Mustang V6 Premium Convertible AT","Ford","2010 Ford Mustang Convertible","2010","210","240" +"144","169","85","Rear-wheel drive","Ford 4.6L 8 Cylinder 315 hp 325 ft-lbs","True","5","5 Speed Manual","16","Gasoline","24","Manual transmission","2010 Ford Mustang GT Convertible","Ford","2010 Ford Mustang Convertible","2010","315","325" +"144","169","85","Rear-wheel drive","Ford 4.6L 8 Cylinder 315 hp 325 ft-lbs","True","5","5 Speed Automatic","17","Gasoline","23","Automatic transmission","2010 Ford Mustang GT Convertible AT","Ford","2010 Ford Mustang Convertible","2010","315","325" +"144","169","85","Rear-wheel drive","Ford 4.6L 8 Cylinder 315 hp 325 ft-lbs","True","5","5 Speed Manual","16","Gasoline","24","Manual transmission","2010 Ford Mustang GT Premium Convertible","Ford","2010 Ford Mustang Convertible","2010","315","325" +"144","169","85","Rear-wheel drive","Ford 4.6L 8 Cylinder 315 hp 325 ft-lbs","True","5","5 Speed Automatic","17","Gasoline","23","Automatic transmission","2010 Ford Mustang GT Premium Convertible AT","Ford","2010 Ford Mustang Convertible","2010","315","325" +"228","83","138","All-wheel drive","Audi 5.2L 10 Cylinder 525 hp 391 ft-lbs","True","6","6 Speed Manual","12","Gasoline","20","Manual transmission","2010 Audi R8 Coupe 5.2","Audi","2010 Audi R8 Coupe","2010","525","391" +"228","79","112","All-wheel drive","Audi 4.2L 8 cylinder 420hp 317 ft-lbs","True","6","6 Speed Manual","12","Gasoline","19","Manual transmission","2010 Audi R8 Coupe 4.2","Audi","2010 Audi R8 Coupe","2010","420","317" +"224","10","191","Front-wheel drive","Kia 3.5L 6 Cylinder 271 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","25","Automatic transmission","2012 Kia Sedona LX","Kia","2012 Kia Sedona","2012","271","248" +"239","10","191","Front-wheel drive","Kia 3.5L 6 Cylinder 271 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","25","Automatic transmission","2012 Kia Sedona EX","Kia","2012 Kia Sedona","2012","271","248" +"127","172","85","Rear-wheel drive","Ford 5.4L 8 Cylinder 550 hp 510 ft-lbs S-charged","True","6","6 Speed Manual","15","Gasoline","23","Manual transmission","2012 Ford Mustang Shelby GT500 Convertible","Ford","2012 Ford Mustang Shelby GT500 Convertible","2012","550","510" +"119","172","85","Rear-wheel drive","Ford 5.4L 8 Cylinder 550 hp 510 ft-lbs S-charged","True","6","6 Speed Manual","15","Gasoline","23","Manual transmission","2012 Ford Mustang Shelby GT500 Coupe","Ford","2012 Ford Mustang Shelby GT500 Coupe","2012","550","510" +"139","172","85","Rear-wheel drive","Ford 5.4L 8 Cylinder 550 hp 510 ft-lbs S-charged","True","6","6 Speed Manual","15","Gasoline","23","Manual transmission","2011 Ford Mustang Shelby GT500 Convertible","Ford","2011 Ford Mustang Shelby GT500 Convertible","2011","550","510" +"104","172","85","Rear-wheel drive","Ford 5.4L 8 Cylinder 550 hp 510 ft-lbs S-charged","True","6","6 Speed Manual","15","Gasoline","23","Manual transmission","2011 Ford Shelby GT500 Coupe","Ford","2011 Ford Shelby GT500 Coupe","2011","550","510" +"104","172","85","Rear-wheel drive","Ford 5.4L 8 Cylinder 550 hp 510 ft-lbs S-charged","True","6","6 Speed Manual","15","Gasoline","23","Manual transmission","2010 Ford Mustang Shelby GT500 Coupe","Ford","2010 Ford Mustang Shelby GT500 Coupe","2010","550","510" +"139","172","85","Rear-wheel drive","Ford 5.4L 8 Cylinder 550 hp 510 ft-lbs S-charged","True","6","6 Speed Manual","14","Gasoline","22","Manual transmission","2010 Ford Mustang Shelby GT500 Convertible","Ford","2010 Ford Mustang Shelby GT500 Convertible","2010","550","510" +"24","10","191","Front-wheel drive","Kia 3.5L 6 Cylinder 271 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","25","Automatic transmission","2011 Kia Sedona LX","Kia","2011 Kia Sedona","2011","271","248" +"36","10","191","Front-wheel drive","Kia 3.5L 6 Cylinder 271 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","25","Automatic transmission","2011 Kia Sedona EX","Kia","2011 Kia Sedona","2011","271","248" +"224","202","191","Front-wheel drive","Kia 3.8L 6 Cylinder 244 hp 253 ft-lbs","True","5","5 Speed Automatic Select Shift","17","Gasoline","23","Automatic transmission","2010 Kia Sedona","Kia","2010 Kia Sedona","2010","244","253" +"224","10","191","Front-wheel drive","Kia 3.8L 6 Cylinder 244 hp 253 ft-lbs","True","5","5 Speed Automatic Select Shift","17","Gasoline","23","Automatic transmission","2010 Kia Sedona LX","Kia","2010 Kia Sedona","2010","244","253" +"224","10","191","Front-wheel drive","Kia 3.8L 6 Cylinder 244 hp 253 ft-lbs","True","5","5 Speed Automatic Select Shift","17","Gasoline","23","Automatic transmission","2010 Kia Sedona EX","Kia","2010 Kia Sedona","2010","244","253" +"220","79","113","All-wheel drive","Audi 4.2L 8 cylinder 420hp 317 ft-lbs","True","6","6 Speed Manual","11","Gasoline","20","Manual transmission","2011 Audi R8 Spyder 4.2","Audi","2011 Audi R8 Spyder","2011","420","317" +"188","115","242","Front-wheel drive","Volkswagen 2.0L 4 Cylinder 200 hp 207 ft-lbs Turbo","True","6","6 Speed Manual","21","Gasoline","31","Manual transmission","2010 Volkswagen GTI 4-Door","Volkswagen","2010 Volkswagen GTI 4-Door","2010","200","207" +"220","83","113","All-wheel drive","Audi 5.2L 10 Cylinder 525 hp 391 ft-lbs","True","6","6 Speed Manual","12","Gasoline","19","Manual transmission","2011 Audi R8 Spyder 5.2","Audi","2011 Audi R8 Spyder","2011","525","391" +"173","63","92","Front-wheel drive","Kia 2.4L 4 Cylinder 175 hp 169 ft-lbs","True","6","6 Speed Manual","20","Gasoline","27","Manual transmission","2012 Kia Sorento","Kia","2012 Kia Sorento","2012","175","169" +"173","63","92","Front-wheel drive","Kia 2.4L 4 Cylinder 175 hp 169 ft-lbs","True","6","6 Speed Automatic Select Shift","21","Gasoline","29","Automatic transmission","2012 Kia Sorento LX","Kia","2012 Kia Sorento","2012","175","169" +"173","63","92","All-wheel drive","Kia 2.4L 4 Cylinder 175 hp 169 ft-lbs","True","6","6 Speed Automatic Select Shift","21","Gasoline","27","Automatic transmission","2012 Kia Sorento LX AWD","Kia","2012 Kia Sorento","2012","175","169" +"173","63","92","Front-wheel drive","Kia 3.5L 6 Cylinder 276 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","26","Automatic transmission","2012 Kia Sorento LX V6","Kia","2012 Kia Sorento","2012","276","248" +"173","63","92","All-wheel drive","Kia 3.5L 6 Cylinder 276 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","24","Automatic transmission","2012 Kia Sorento LX V6 AWD","Kia","2012 Kia Sorento","2012","276","248" +"173","63","92","Front-wheel drive","Kia 2.4L 4 Cylinder 191 hp 181 ft-lbs","True","6","6 Speed Automatic Select Shift","22","Gasoline","32","Automatic transmission","2012 Kia Sorento EX","Kia","2012 Kia Sorento","2012","191","181" +"173","63","92","All-wheel drive","Kia 2.4L 4 Cylinder 191 hp 181 ft-lbs","True","6","6 Speed Automatic Select Shift","21","Gasoline","28","Automatic transmission","2012 Kia Sorento EX AWD","Kia","2012 Kia Sorento","2012","191","181" +"173","63","92","Front-wheel drive","Kia 3.5L 6 Cylinder 276 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","26","Automatic transmission","2012 Kia Sorento EX V6","Kia","2012 Kia Sorento","2012","276","248" +"173","63","92","All-wheel drive","Kia 3.5L 6 Cylinder 276 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","24","Automatic transmission","2012 Kia Sorento EX V6 AWD","Kia","2012 Kia Sorento","2012","276","248" +"163","63","92","Front-wheel drive","Kia 3.5L 6 Cylinder 276 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","26","Automatic transmission","2012 Kia Sorento SX","Kia","2012 Kia Sorento","2012","276","248" +"163","63","92","All-wheel drive","Kia 3.5L 6 Cylinder 276 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","24","Automatic transmission","2012 Kia Sorento SX AWD","Kia","2012 Kia Sorento","2012","276","248" +"126","109","248","All-wheel drive","Audi 3.0L 6 Cylinder 333 hp 325 ft-lbs S-charged","True","6","6 Speed Manual","18","Gasoline","27","Manual transmission","2012 Audi S4 Sedan 3.0","Audi","2012 Audi S4 Sedan","2012","333","325" +"96","228","125","Rear-wheel drive","Chevrolet 3.6L 6 Cylinder 304 hp 273 ft-lbs","True","6","6 Speed Manual","17","Gasoline","29","Manual transmission","2010 Chevrolet Camaro Coupe 1LS","Chevrolet","2010 Chevrolet Camaro Coupe","2010","304","273" +"96","228","125","Rear-wheel drive","Chevrolet 3.6L 6 Cylinder 304 hp 273 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","29","Automatic transmission","2010 Chevrolet Camaro Coupe 1LS AT","Chevrolet","2010 Chevrolet Camaro Coupe","2010","304","273" +"96","228","125","Rear-wheel drive","Chevrolet 3.6L 6 Cylinder 304 hp 273 ft-lbs","True","6","6 Speed Manual","17","Gasoline","29","Manual transmission","2010 Chevrolet Camaro Coupe 1LT","Chevrolet","2010 Chevrolet Camaro Coupe","2010","304","273" +"96","228","125","Rear-wheel drive","Chevrolet 3.6L 6 Cylinder 304 hp 273 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","29","Automatic transmission","2010 Chevrolet Camaro Coupe 1LT AT","Chevrolet","2010 Chevrolet Camaro Coupe","2010","304","273" +"96","228","125","Rear-wheel drive","Chevrolet 3.6L 6 Cylinder 304 hp 273 ft-lbs","True","6","6 Speed Manual","17","Gasoline","29","Manual transmission","2010 Chevrolet Camaro Coupe 2LT","Chevrolet","2010 Chevrolet Camaro Coupe","2010","304","273" +"96","228","125","Rear-wheel drive","Chevrolet 3.6L 6 Cylinder 304 hp 273 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","29","Automatic transmission","2010 Chevrolet Camaro Coupe 2LT AT","Chevrolet","2010 Chevrolet Camaro Coupe","2010","304","273" +"96","228","125","Rear-wheel drive","Chevrolet 6.2L 8 Cylinder 426 hp 420 ft-lbs","True","6","6 Speed Manual","16","Gasoline","24","Manual transmission","2010 Chevrolet Camaro Coupe 1SS","Chevrolet","2010 Chevrolet Camaro Coupe","2010","426","420" +"96","228","125","Rear-wheel drive","Chevrolet 6.2L 8 Cylinder 426 hp 420 ft-lbs","True","6","6 Speed Automatic","16","Gasoline","25","Automatic transmission","2010 Chevrolet Camaro Coupe 1SS AT","Chevrolet","2010 Chevrolet Camaro Coupe","2010","426","420" +"96","228","125","Rear-wheel drive","Chevrolet 6.2L 8 Cylinder 426 hp 420 ft-lbs","True","6","6 Speed Manual","16","Gasoline","24","Manual transmission","2010 Chevrolet Camaro Coupe 2SS","Chevrolet","2010 Chevrolet Camaro Coupe","2010","426","420" +"96","228","125","Rear-wheel drive","Chevrolet 6.2L 8 Cylinder 426 hp 420 ft-lbs","True","6","6 Speed Automatic","16","Gasoline","25","Automatic transmission","2010 Chevrolet Camaro Coupe 2SS AT","Chevrolet","2010 Chevrolet Camaro Coupe","2010","426","420" +"147","95","214","All-wheel drive","Audi 3.0L 6 Cylinder 333 hp 325 ft-lbs S-charged","True","6","6 Speed Manual","18","Gasoline","27","Manual transmission","2011 Audi S4 Sedan 3.0","Audi","2011 Audi S4 Sedan","2011","333","325" +"173","63","92","Front-wheel drive","Kia 2.4L 4 Cylinder 175 hp 169 ft-lbs","True","6","6 Speed Manual","20","Gasoline","27","Manual transmission","2011 Kia Sorento","Kia","2011 Kia Sorento","2011","175","169" +"173","63","92","Front-wheel drive","Kia 2.4L 4 Cylinder 175 hp 169 ft-lbs","True","6","6 Speed Automatic Select Shift","21","Gasoline","29","Automatic transmission","2011 Kia Sorento LX","Kia","2011 Kia Sorento","2011","175","169" +"173","63","92","All-wheel drive","Kia 2.4L 4 Cylinder 175 hp 169 ft-lbs","True","6","6 Speed Automatic Select Shift","21","Gasoline","27","Automatic transmission","2011 Kia Sorento LX AWD","Kia","2011 Kia Sorento","2011","175","169" +"208","63","92","Front-wheel drive","Kia 3.5L 6 Cylinder 276 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","26","Automatic transmission","2011 Kia Sorento LX V6","Kia","2011 Kia Sorento","2011","276","248" +"208","63","92","All-wheel drive","Kia 3.5L 6 Cylinder 276 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","24","Automatic transmission","2011 Kia Sorento LX V6 AWD","Kia","2011 Kia Sorento","2011","276","248" +"208","63","92","Front-wheel drive","Kia 2.4L 4 Cylinder 175 hp 169 ft-lbs","True","6","6 Speed Automatic Select Shift","21","Gasoline","29","Automatic transmission","2011 Kia Sorento EX","Kia","2011 Kia Sorento","2011","175","169" +"208","63","92","All-wheel drive","Kia 2.4L 4 Cylinder 175 hp 169 ft-lbs","True","6","6 Speed Automatic Select Shift","21","Gasoline","27","Automatic transmission","2011 Kia Sorento EX AWD","Kia","2011 Kia Sorento","2011","175","169" +"208","63","92","Front-wheel drive","Kia 3.5L 6 Cylinder 276 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","26","Automatic transmission","2011 Kia Sorento EX V6","Kia","2011 Kia Sorento","2011","276","248" +"208","63","92","All-wheel drive","Kia 3.5L 6 Cylinder 276 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","24","Automatic transmission","2011 Kia Sorento EX V6 AWD","Kia","2011 Kia Sorento","2011","276","248" +"198","52","92","Front-wheel drive","Kia 3.5L 6 Cylinder 276 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","26","Automatic transmission","2011 Kia Sorento SX","Kia","2011 Kia Sorento","2011","276","248" +"198","52","92","All-wheel drive","Kia 3.5L 6 Cylinder 276 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","24","Automatic transmission","2011 Kia Sorento SX AWD","Kia","2011 Kia Sorento","2011","276","248" +"99","87","62","Front-wheel drive","Kia 2.4L 4 Cylinder 176 hp 168 ft-lbs","True","6","6 Speed Manual","21","Gasoline","29","Manual transmission","2012 Kia Sportage","Kia","2012 Kia Sportage","2012","176","168" +"99","87","62","Front-wheel drive","Kia 2.4L 4 Cylinder 176 hp 168 ft-lbs","True","6","6 Speed Automatic Select Shift","22","Gasoline","32","Automatic transmission","2012 Kia Sportage LX","Kia","2012 Kia Sportage","2012","176","168" +"99","87","62","All-wheel drive","Kia 2.4L 4 Cylinder 176 hp 168 ft-lbs","True","6","6 Speed Automatic Select Shift","21","Gasoline","28","Automatic transmission","2012 Kia Sportage LX AWD","Kia","2012 Kia Sportage","2012","176","168" +"99","87","62","Front-wheel drive","Kia 2.4L 4 Cylinder 176 hp 168 ft-lbs","True","6","6 Speed Automatic Select Shift","22","Gasoline","32","Automatic transmission","2012 Kia Sportage EX","Kia","2012 Kia Sportage","2012","176","168" +"99","87","62","All-wheel drive","Kia 2.4L 4 Cylinder 176 hp 168 ft-lbs","True","6","6 Speed Automatic Select Shift","21","Gasoline","28","Automatic transmission","2012 Kia Sportage EX AWD","Kia","2012 Kia Sportage","2012","176","168" +"99","98","62","Front-wheel drive","Kia 2.0L 4 Cylinder 260 hp 269 ft-lbs Turbo","True","6","6 Speed Automatic Select Shift","22","Gasoline","29","Automatic transmission","2012 Kia Sportage SX","Kia","2012 Kia Sportage","2012","260","269" +"99","98","62","All-wheel drive","Kia 2.0L 4 Cylinder 260 hp 269 ft-lbs Turbo","True","6","6 Speed Automatic Select Shift","21","Gasoline","26","Automatic transmission","2012 Kia Sportage SX AWD","Kia","2012 Kia Sportage","2012","260","269" +"200","105","249","Front-wheel drive","Volkswagen 2.0L 4 Cylinder 140 hp 236 ft-lbs Turbo Diesel","True","6","6 Speed Manual","30","Diesel fuel","41","Manual transmission","2010 Volkswagen Golf 2.0L 2-Door TDI","Volkswagen","2010 Volkswagen Golf 2-Door","2010","140","236" +"200","105","249","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","5","5 Speed Manual","22","Gasoline","30","Manual transmission","2010 Volkswagen Golf 2-Door","Volkswagen","2010 Volkswagen Golf 2-Door","2010","170","177" +"200","105","249","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","6","6 Speed Automatic","23","Gasoline","30","Automatic transmission","2010 Volkswagen Golf 2-Door AT","Volkswagen","2010 Volkswagen Golf 2-Door","2010","170","177" +"99","87","62","Front-wheel drive","Kia 2.4L 4 Cylinder 176 hp 168 ft-lbs","True","6","6 Speed Manual","21","Gasoline","29","Manual transmission","2011 Kia Sportage","Kia","2011 Kia Sportage","2011","176","168" +"99","87","62","Front-wheel drive","Kia 2.4L 4 Cylinder 176 hp 168 ft-lbs","True","6","6 Speed Automatic Select Shift","22","Gasoline","31","Automatic transmission","2011 Kia Sportage LX","Kia","2011 Kia Sportage","2011","176","168" +"99","87","62","All-wheel drive","Kia 2.4L 4 Cylinder 176 hp 168 ft-lbs","True","6","6 Speed Automatic Select Shift","21","Gasoline","28","Automatic transmission","2011 Kia Sportage LX AWD","Kia","2011 Kia Sportage","2011","176","168" +"99","87","62","Front-wheel drive","Kia 2.4L 4 Cylinder 176 hp 168 ft-lbs","True","6","6 Speed Automatic Select Shift","22","Gasoline","31","Automatic transmission","2011 Kia Sportage EX","Kia","2011 Kia Sportage","2011","176","168" +"99","87","62","All-wheel drive","Kia 2.4L 4 Cylinder 176 hp 168 ft-lbs","True","6","6 Speed Automatic Select Shift","21","Gasoline","28","Automatic transmission","2011 Kia Sportage EX AWD","Kia","2011 Kia Sportage","2011","176","168" +"99","98","62","Front-wheel drive","Kia 2.0L 4 Cylinder 260 hp 264 ft-lbs Turbo","True","6","6 Speed Automatic Select Shift","22","Gasoline","27","Automatic transmission","2011 Kia Sportage SX","Kia","2011 Kia Sportage","2011","260","264" +"99","98","62","All-wheel drive","Kia 2.0L 4 Cylinder 260 hp 264 ft-lbs Turbo","True","6","6 Speed Automatic Select Shift","21","Gasoline","25","Automatic transmission","2011 Kia Sportage SX AWD","Kia","2011 Kia Sportage","2011","260","264" +"126","109","34","All-wheel drive","Audi 3.0L 6 Cylinder 333 hp 325 ft-lbs S-charged","True","6","6 Speed Manual","18","Gasoline","27","Manual transmission","2010 Audi S4 Sedan 3.0","Audi","2010 Audi S4 Sedan","2010","333","325" +"158","255","8","Front-wheel drive","Kia 2.0L 4 Cylinder 140 hp 136 ft-lbs","True","5","5 Speed Manual","20","Gasoline","25","Manual transmission","2010 Kia Sportage LX","Kia","2010 Kia Sportage","2010","140","136" +"158","255","8","Front-wheel drive","Kia 2.0L 4 Cylinder 140 hp 136 ft-lbs","True","4","4 Speed Automatic Select Shift","20","Gasoline","25","Automatic transmission","2010 Kia Sportage LX AT","Kia","2010 Kia Sportage","2010","140","136" +"158","255","8","Four-wheel drive","Kia 2.0L 4 Cylinder 140 hp 136 ft-lbs","True","5","5 Speed Manual","19","Gasoline","24","Manual transmission","2010 Kia Sportage LX 4WD","Kia","2010 Kia Sportage","2010","140","136" +"158","255","8","Front-wheel drive","Kia 2.7L 6 Cylinder 173 hp 178 ft-lbs","True","4","4 Speed Automatic Select Shift","18","Gasoline","23","Automatic transmission","2010 Kia Sportage LX V6","Kia","2010 Kia Sportage","2010","173","178" +"158","255","8","Four-wheel drive","Kia 2.7L 6 Cylinder 173 hp 178 ft-lbs","True","4","4 Speed Automatic Select Shift","18","Gasoline","23","Automatic transmission","2010 Kia Sportage LX V6 4WD","Kia","2010 Kia Sportage","2010","173","178" +"158","255","8","Front-wheel drive","Kia 2.7L 6 Cylinder 173 hp 178 ft-lbs","True","4","4 Speed Automatic Select Shift","18","Gasoline","23","Automatic transmission","2010 Kia Sportage EX","Kia","2010 Kia Sportage","2010","173","178" +"158","255","8","Four-wheel drive","Kia 2.7L 6 Cylinder 173 hp 178 ft-lbs","True","4","4 Speed Automatic Select Shift","18","Gasoline","23","Automatic transmission","2010 Kia Sportage EX 4WD","Kia","2010 Kia Sportage","2010","173","178" +"155","151","216","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Manual","26","Gasoline","34","Manual transmission","2010 Honda Civic DX Sedan","Honda","2010 Honda Civic Sedan","2010","140","128" +"117","105","214","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Automatic","25","Gasoline","36","Automatic transmission","2010 Honda Civic DX Sedan AT","Honda","2010 Honda Civic Sedan","2010","140","128" +"155","151","216","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Manual","26","Gasoline","34","Manual transmission","2010 Honda Civic DX-VP Sedan","Honda","2010 Honda Civic Sedan","2010","140","128" +"155","151","216","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Automatic","25","Gasoline","36","Automatic transmission","2010 Honda Civic DX-VP Sedan AT","Honda","2010 Honda Civic Sedan","2010","140","128" +"155","151","216","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Manual","26","Gasoline","34","Manual transmission","2010 Honda Civic LX Sedan","Honda","2010 Honda Civic Sedan","2010","140","128" +"155","151","216","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Automatic","25","Gasoline","36","Automatic transmission","2010 Honda Civic LX Sedan AT","Honda","2010 Honda Civic Sedan","2010","140","128" +"155","151","216","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Manual","26","Gasoline","34","Manual transmission","2010 Honda Civic LX-S Sedan","Honda","2010 Honda Civic Sedan","2010","140","128" +"155","151","216","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Automatic","25","Gasoline","36","Automatic transmission","2010 Honda Civic LX-S Sedan AT","Honda","2010 Honda Civic Sedan","2010","140","128" +"155","151","216","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Manual","26","Gasoline","34","Manual transmission","2010 Honda Civic EX Sedan","Honda","2010 Honda Civic Sedan","2010","140","128" +"155","151","216","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Automatic","25","Gasoline","36","Automatic transmission","2010 Honda Civic EX Sedan AT","Honda","2010 Honda Civic Sedan","2010","140","128" +"155","151","216","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Manual","26","Gasoline","34","Manual transmission","2010 Honda Civic EX-L Sedan","Honda","2010 Honda Civic Sedan","2010","140","128" +"155","151","216","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Automatic","25","Gasoline","36","Automatic transmission","2010 Honda Civic EX-L Sedan AT","Honda","2010 Honda Civic Sedan","2010","140","128" +"155","151","216","Front-wheel drive","Honda 2.0L 4 Cyinder 197 hp 139 ft-lbs","True","6","6 Speed Manual","21","Gasoline","29","Manual transmission","2010 Honda Civic Si Sedan","Honda","2010 Honda Civic Sedan","2010","197","139" +"155","151","216","Front-wheel drive","Honda 1.8L 4 Cylinder 113 hp 109 ft-lbs CNG","True","5","5 Speed Automatic","24","Compressed natural gas","36","Automatic transmission","2010 Honda Civic GX Sedan","Honda","2010 Honda Civic Sedan","2010","113","109" +"41","20","57","Rear-wheel drive","Nissan 4.0L 6 Cylinder 266 hp 288 ft-lbs","True","5","5 Speed Automatic Select Shift","15","Gasoline","22","Automatic transmission","2011 Nissan Pathfinder SV","Nissan","2011 Nissan Pathfinder","2011","266","288" +"41","20","57","Rear-wheel drive","Nissan 4.0L 6 Cylinder 266 hp 288 ft-lbs","True","5","5 Speed Automatic Select Shift","15","Gasoline","22","Automatic transmission","2011 Nissan Pathfinder Silver Edition","Nissan","2011 Nissan Pathfinder","2011","266","288" +"52","20","57","Four-wheel drive","Nissan 4.0L 6 Cylinder 266 hp 288 ft-lbs","True","5","5 Speed Automatic Select Shift","14","Gasoline","20","Automatic transmission","2011 Nissan Pathfinder Silver Edition 4x4","Nissan","2011 Nissan Pathfinder","2011","266","288" +"52","20","57","Four-wheel drive","Nissan 4.0L 6 Cylinder 266 hp 288 ft-lbs","True","5","5 Speed Automatic Select Shift","14","Gasoline","20","Automatic transmission","2011 Nissan Pathfinder SV 4x4","Nissan","2011 Nissan Pathfinder","2011","266","288" +"36","20","57","Rear-wheel drive","Nissan 4.0L 6 Cylinder 266 hp 288 ft-lbs","True","5","5 Speed Automatic","15","Gasoline","22","Automatic transmission","2011 Nissan Pathfinder S","Nissan","2011 Nissan Pathfinder","2011","266","288" +"52","20","57","Four-wheel drive","Nissan 4.0L 6 Cylinder 266 hp 288 ft-lbs","True","5","5 Speed Automatic","14","Gasoline","20","Automatic transmission","2011 Nissan Pathfinder S 4x4","Nissan","2011 Nissan Pathfinder","2011","266","288" +"41","20","57","Rear-wheel drive","Nissan 4.0L 6 Cylinder 266 hp 288 ft-lbs","True","5","5 Speed Automatic Select Shift","15","Gasoline","22","Automatic transmission","2011 Nissan Pathfinder LE","Nissan","2011 Nissan Pathfinder","2011","266","288" +"54","20","57","Four-wheel drive","Nissan 5.6L 8 Cylinder 310 hp 388 ft-lbs","True","5","5 Speed Automatic Select Shift","13","Gasoline","18","Automatic transmission","2011 Nissan Pathfinder LE 4x4 V8","Nissan","2011 Nissan Pathfinder","2011","310","388" +"52","20","57","Four-wheel drive","Nissan 4.0L 6 Cylinder 266 hp 288 ft-lbs","True","5","5 Speed Automatic Select Shift","14","Gasoline","20","Automatic transmission","2011 Nissan Pathfinder LE 4x4","Nissan","2011 Nissan Pathfinder","2011","266","288" +"188","68","97","Front-wheel drive","Hyundai 2.4L 4 Cylinder 175 hp 169 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","28","Automatic transmission","2011 Hyundai Santa Fe GLS AT","Hyundai","2011 Hyundai Santa Fe","2011","175","169" +"188","68","97","All-wheel drive","Hyundai 3.5L 6 Cylinder 276 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","26","Automatic transmission","2011 Hyundai Santa Fe SE AWD","Hyundai","2011 Hyundai Santa Fe","2011","276","248" +"188","68","97","All-wheel drive","Hyundai 3.5L 6 Cylinder 276 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","26","Automatic transmission","2011 Hyundai Santa Fe Limited 3.5 AWD","Hyundai","2011 Hyundai Santa Fe","2011","276","248" +"188","68","97","Front-wheel drive","Hyundai 3.5L 6 Cylinder 276 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","26","Automatic transmission","2011 Hyundai Santa Fe SE","Hyundai","2011 Hyundai Santa Fe","2011","276","248" +"188","68","97","All-wheel drive","Hyundai 2.4L 4 Cylinder 175 hp 169 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","25","Automatic transmission","2011 Hyundai Santa Fe GLS AT AWD","Hyundai","2011 Hyundai Santa Fe","2011","175","169" +"188","68","97","Front-wheel drive","Hyundai 3.5L 6 Cylinder 276 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","26","Automatic transmission","2011 Hyundai Santa Fe Limited 3.5","Hyundai","2011 Hyundai Santa Fe","2011","276","248" +"188","68","97","Front-wheel drive","Hyundai 2.4L 4 Cylinder 175 hp 169 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","28","Automatic transmission","2011 Hyundai Santa Fe Limited","Hyundai","2011 Hyundai Santa Fe","2011","175","169" +"188","68","97","Front-wheel drive","Hyundai 2.4L 4 Cylinder 175 hp 169 ft-lbs","True","6","6 Speed Manual","19","Gasoline","26","Manual transmission","2011 Hyundai Santa Fe GLS","Hyundai","2011 Hyundai Santa Fe","2011","175","169" +"188","68","97","All-wheel drive","Hyundai 3.5L 6 Cylinder 276 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","26","Automatic transmission","2011 Hyundai Santa Fe GLS 3.5 AWD","Hyundai","2011 Hyundai Santa Fe","2011","276","248" +"188","68","97","Front-wheel drive","Hyundai 3.5L 6 Cylinder 276 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","26","Automatic transmission","2011 Hyundai Santa Fe GLS 3.5","Hyundai","2011 Hyundai Santa Fe","2011","276","248" +"188","68","97","Front-wheel drive","Hyundai 3.5L 6 Cylinder 276 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","26","Automatic transmission","2010 Hyundai Santa Fe SE","Hyundai","2010 Hyundai Santa Fe","2010","276","248" +"188","68","97","All-wheel drive","Hyundai 3.5L 6 Cylinder 276 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","26","Automatic transmission","2010 Hyundai Santa Fe Limited 3.5 AWD","Hyundai","2010 Hyundai Santa Fe","2010","276","248" +"188","68","97","All-wheel drive","Hyundai 2.4L 4 Cylinder 175 hp 169 ft-lbs","True","6","6 Speed Automatic Select Shift","21","Gasoline","27","Automatic transmission","2010 Hyundai Santa Fe GLS AT AWD","Hyundai","2010 Hyundai Santa Fe","2010","175","169" +"188","68","97","Front-wheel drive","Hyundai 2.4L 4 Cylinder 175 hp 169 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","28","Automatic transmission","2010 Hyundai Santa Fe Limited","Hyundai","2010 Hyundai Santa Fe","2010","175","169" +"188","68","97","Front-wheel drive","Hyundai 3.5L 6 Cylinder 276 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","26","Automatic transmission","2010 Hyundai Santa Fe Limited 3.5","Hyundai","2010 Hyundai Santa Fe","2010","276","248" +"188","68","97","All-wheel drive","Hyundai 3.5L 6 Cylinder 276 hp 248 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","26","Automatic transmission","2010 Hyundai Santa Fe SE AWD","Hyundai","2010 Hyundai Santa Fe","2010","276","248" +"188","68","97","Front-wheel drive","Hyundai 2.4L 4 Cylinder 175 hp 169 ft-lbs","True","6","6 Speed Automatic Select Shift","20","Gasoline","28","Automatic transmission","2010 Hyundai Santa Fe GLS AT","Hyundai","2010 Hyundai Santa Fe","2010","175","169" +"188","68","97","Front-wheel drive","Hyundai 2.4L 4 Cylinder 175 hp 169 ft-lbs","True","6","6 Speed Manual","19","Gasoline","26","Manual transmission","2010 Hyundai Santa Fe GLS","Hyundai","2010 Hyundai Santa Fe","2010","175","169" +"5","33","143","Front-wheel drive","Ford 3.5L 6 Cylinder 263 hp 249 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","28","Automatic transmission","2012 Ford Taurus SE","Ford","2012 Ford Taurus","2012","263","249" +"5","33","143","Front-wheel drive","Ford 3.5L 6 Cylinder 263 hp 249 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","27","Automatic transmission","2012 Ford Taurus SEL","Ford","2012 Ford Taurus","2012","263","249" +"5","33","143","All-wheel drive","Ford 3.5L 6 Cylinder 263 hp 249 ft-lbs","True","6","6 Speed Automatic Select Shift","17","Gasoline","26","Automatic transmission","2012 Ford Taurus SEL AWD","Ford","2012 Ford Taurus","2012","263","249" +"5","33","143","Front-wheel drive","Ford 3.5L 6 Cylinder 263 hp 249 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","27","Automatic transmission","2012 Ford Taurus Limited","Ford","2012 Ford Taurus","2012","263","249" +"5","33","143","All-wheel drive","Ford 3.5L 6 Cylinder 263 hp 249 ft-lbs","True","6","6 Speed Automatic Select Shift","17","Gasoline","26","Automatic transmission","2012 Ford Taurus Limited AWD","Ford","2012 Ford Taurus","2012","263","249" +"5","33","143","Front-wheel drive","Ford 3.5L 6 Cylinder 263 hp 249 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","28","Automatic transmission","2011 Ford Taurus SE","Ford","2011 Ford Taurus","2011","263","249" +"5","33","143","Front-wheel drive","Ford 3.5L 6 Cylinder 263 hp 249 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","27","Automatic transmission","2011 Ford Taurus SEL","Ford","2011 Ford Taurus","2011","263","249" +"5","33","143","All-wheel drive","Ford 3.5L 6 Cylinder 263 hp 249 ft-lbs","True","6","6 Speed Automatic","17","Gasoline","25","Automatic transmission","2011 Ford Taurus SEL AWD","Ford","2011 Ford Taurus","2011","263","249" +"5","33","143","Front-wheel drive","Ford 3.5L 6 Cylinder 263 hp 249 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","27","Automatic transmission","2011 Ford Taurus Limited","Ford","2011 Ford Taurus","2011","263","249" +"5","33","143","All-wheel drive","Ford 3.5L 6 Cylinder 263 hp 249 ft-lbs","True","6","6 Speed Automatic","17","Gasoline","25","Automatic transmission","2011 Ford Taurus Limited AWD","Ford","2011 Ford Taurus","2011","263","249" +"5","33","143","Front-wheel drive","Ford 3.5L 6 Cylinder 263 hp 249 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","28","Automatic transmission","2010 Ford Taurus SE","Ford","2010 Ford Taurus","2010","263","249" +"5","33","143","Front-wheel drive","Ford 3.5L 6 Cylinder 263 hp 249 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","27","Automatic transmission","2010 Ford Taurus SEL","Ford","2010 Ford Taurus","2010","263","249" +"5","33","143","All-wheel drive","Ford 3.5L 6 Cylinder 263 hp 249 ft-lbs","True","6","6 Speed Automatic","17","Gasoline","25","Automatic transmission","2010 Ford Taurus SEL AWD","Ford","2010 Ford Taurus","2010","263","249" +"5","33","143","Front-wheel drive","Ford 3.5L 6 Cylinder 263 hp 249 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","27","Automatic transmission","2010 Ford Taurus Limited","Ford","2010 Ford Taurus","2010","263","249" +"5","33","143","All-wheel drive","Ford 3.5L 6 Cylinder 263 hp 249 ft-lbs","True","6","6 Speed Automatic","17","Gasoline","25","Automatic transmission","2010 Ford Taurus Limited AWD","Ford","2010 Ford Taurus","2010","263","249" +"200","105","249","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","6","6 Speed Automatic","23","Gasoline","30","Automatic transmission","2010 Volkswagen Golf 2.5L 4-Door","Volkswagen","2010 Volkswagen Golf 4-Door","2010","170","177" +"200","105","249","Front-wheel drive","Volkswagen 2.0L 4 Cylinder 140 hp 236 ft-lbs Turbo Diesel","True","6","6 Speed Manual","30","Diesel fuel","41","Manual transmission","2010 Volkswagen Golf 4-Door TDI","Volkswagen","2010 Volkswagen Golf 4-Door","2010","140","236" +"200","105","249","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","5","5 Speed Manual","23","Gasoline","33","Manual transmission","2011 Volkswagen Golf 2.5L 2-Door","Volkswagen","2011 Volkswagen Golf 2-Door","2011","170","177" +"200","105","249","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","6","6 Speed Automatic","24","Gasoline","31","Automatic transmission","2011 Volkswagen Golf 2.5L 2-Door AT","Volkswagen","2011 Volkswagen Golf 2-Door","2011","170","177" +"200","105","249","Front-wheel drive","Volkswagen 2.0L 4 Cylinder 140 hp 236 ft-lbs Turbo Diesel","True","6","6 Speed Manual","30","Diesel fuel","42","Manual transmission","2011 Volkswagen Golf TDI Clean Diesel 2-Door","Volkswagen","2011 Volkswagen Golf 2-Door","2011","140","236" +"165","70","138","Front-wheel drive","Ford 3.5L 6 Cylinder 285 hp 253 ft-lbs","True","6","6 Speed Automatic","19","Gasoline","26","Automatic transmission","2011 Ford Edge SE","Ford","2011 Ford Edge","2011","285","253" +"165","70","138","Front-wheel drive","Ford 3.5L 6 Cylinder 285 hp 253 ft-lbs","True","6","6 Speed Automatic","19","Gasoline","26","Automatic transmission","2011 Ford Edge SEL","Ford","2011 Ford Edge","2011","285","253" +"165","70","138","All-wheel drive","Ford 3.5L 6 Cylinder 285 hp 253 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","26","Automatic transmission","2011 Ford Edge SEL AWD","Ford","2011 Ford Edge","2011","285","253" +"165","70","138","Front-wheel drive","Ford 3.5L 6 Cylinder 285 hp 253 ft-lbs","True","6","6 Speed Automatic","19","Gasoline","26","Automatic transmission","2011 Ford Edge Limited","Ford","2011 Ford Edge","2011","285","253" +"165","70","138","All-wheel drive","Ford 3.5L 6 Cylinder 285 hp 253 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","26","Automatic transmission","2011 Ford Edge Limited AWD","Ford","2011 Ford Edge","2011","285","253" +"165","70","138","Front-wheel drive","Ford 3.7L 6 Cylinder 305 hp 280 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","25","Automatic transmission","2011 Ford Edge Sport","Ford","2011 Ford Edge","2011","305","280" +"165","70","138","All-wheel drive","Ford 3.7L 6 Cylinder 305 hp 280 ft-lbs","True","6","6 Speed Automatic","17","Gasoline","23","Automatic transmission","2011 Ford Edge Sport AWD","Ford","2011 Ford Edge","2011","305","280" +"200","105","249","Front-wheel drive","Volkswagen 2.5L 5 Cylinder 170 hp 177 ft-lbs","True","6","6 Speed Automatic","24","Gasoline","31","Automatic transmission","2011 Volkswagen Golf 2.5L 4-Door","Volkswagen","2011 Volkswagen Golf 4-Door","2011","170","177" +"200","105","249","Front-wheel drive","Volkswagen 2.0L 4 Cylinder 140 hp 236 ft-lbs Turbo Diesel","True","6","6 Speed Manual","30","Diesel fuel","42","Manual transmission","2011 Volkswagen Golf TDI Clean Diesel 4-Door","Volkswagen","2011 Volkswagen Golf 4-Door","2011","140","236" +"89","27","228","All-wheel drive","Audi 4.2L 8 cylinder 354hp 325 ft-lbs","True","6","6 Speed Automatic Select Shift","16","Gasoline","24","Automatic transmission","2012 Audi S5 Coupe 4.2 AT","Audi","2012 Audi S5 Coupe","2012","354","325" +"89","27","228","All-wheel drive","Audi 4.2L 8 cylinder 354hp 325 ft-lbs","True","6","6 Speed Manual","14","Gasoline","22","Manual transmission","2012 Audi S5 Coupe 4.2","Audi","2012 Audi S5 Coupe","2012","354","325" +"165","70","138","Front-wheel drive","Ford 3.5L 6 Cylinder 285 hp 253 ft-lbs","True","6","6 Speed Automatic Select Shift","19","Gasoline","27","Automatic transmission","2012 Ford Edge SE","Ford","2012 Ford Edge","2012","285","253" +"165","70","138","Front-wheel drive","Ford 3.5L 6 Cylinder 285 hp 253 ft-lbs","True","6","6 Speed Automatic Select Shift","19","Gasoline","27","Automatic transmission","2012 Ford Edge SEL","Ford","2012 Ford Edge","2012","285","253" +"165","70","138","All-wheel drive","Ford 3.5L 6 Cylinder 285 hp 253 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","25","Automatic transmission","2012 Ford Edge SEL AWD","Ford","2012 Ford Edge","2012","285","253" +"165","70","138","Front-wheel drive","Ford 3.5L 6 Cylinder 285 hp 253 ft-lbs","True","6","6 Speed Automatic Select Shift","19","Gasoline","27","Automatic transmission","2012 Ford Edge Limited","Ford","2012 Ford Edge","2012","285","253" +"165","70","138","All-wheel drive","Ford 3.5L 6 Cylinder 285 hp 253 ft-lbs","True","6","6 Speed Automatic Select Shift","18","Gasoline","25","Automatic transmission","2012 Ford Edge Limited AWD","Ford","2012 Ford Edge","2012","285","253" +"165","70","138","Front-wheel drive","Ford 3.7L 6 Cylinder 305 hp 280 ft-lbs","True","6","6 Speed Automatic Select Shift","19","Gasoline","26","Automatic transmission","2012 Ford Edge Sport","Ford","2012 Ford Edge","2012","305","280" +"165","70","138","All-wheel drive","Ford 3.7L 6 Cylinder 305 hp 280 ft-lbs","True","6","6 Speed Automatic Select Shift","17","Gasoline","23","Automatic transmission","2012 Ford Edge Sport AWD","Ford","2012 Ford Edge","2012","305","280" +"165","108","133","Front-wheel drive","Ford 3.5L 6 Cylinder 265 hp 250 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","25","Automatic transmission","2010 Ford Edge SE","Ford","2010 Ford Edge","2010","265","250" +"165","108","133","Front-wheel drive","Ford 3.5L 6 Cylinder 265 hp 250 ft-lbs","True","6","6 Speed Automatic","17","Gasoline","23","Automatic transmission","2010 Ford Edge SE Fleet","Ford","2010 Ford Edge","2010","265","250" +"165","108","133","Front-wheel drive","Ford 3.5L 6 Cylinder 265 hp 250 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","25","Automatic transmission","2010 Ford Edge SEL","Ford","2010 Ford Edge","2010","265","250" +"165","108","133","All-wheel drive","Ford 3.5L 6 Cylinder 265 hp 250 ft-lbs","True","6","6 Speed Automatic","17","Gasoline","23","Automatic transmission","2010 Ford Edge SEL AWD","Ford","2010 Ford Edge","2010","265","250" +"165","108","133","Front-wheel drive","Ford 3.5L 6 Cylinder 265 hp 250 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","25","Automatic transmission","2010 Ford Edge Limited","Ford","2010 Ford Edge","2010","265","250" +"165","108","133","All-wheel drive","Ford 3.5L 6 Cylinder 265 hp 250 ft-lbs","True","6","6 Speed Automatic","17","Gasoline","23","Automatic transmission","2010 Ford Edge Limited AWD","Ford","2010 Ford Edge","2010","265","250" +"165","108","133","Front-wheel drive","Ford 3.5L 6 Cylinder 265 hp 250 ft-lbs","True","6","6 Speed Automatic","18","Gasoline","25","Automatic transmission","2010 Ford Edge Sport","Ford","2010 Ford Edge","2010","265","250" +"165","108","133","All-wheel drive","Ford 3.5L 6 Cylinder 265 hp 250 ft-lbs","True","6","6 Speed Automatic","17","Gasoline","23","Automatic transmission","2010 Ford Edge Sport AWD","Ford","2010 Ford Edge","2010","265","250" +"92","17","62","All-wheel drive","Audi 4.2L 8 cylinder 354hp 325 ft-lbs","True","6","6 Speed Automatic Select Shift","16","Gasoline","24","Automatic transmission","2011 Audi S5 Coupe 4.2 AT","Audi","2011 Audi S5 Coupe","2011","354","325" +"92","17","62","All-wheel drive","Audi 4.2L 8 cylinder 354hp 325 ft-lbs","True","6","6 Speed Manual","14","Gasoline","22","Manual transmission","2011 Audi S5 Coupe 4.2","Audi","2011 Audi S5 Coupe","2011","354","325" +"165","70","138","Front-wheel drive","Ford 2.0L 4 Cylinder 240 hp 270 ft-lbs Turbo","True","6","6 Speed Automatic","21","Gasoline","30","Automatic transmission","2012 Ford Edge SE Turbo","Ford","2012 Ford Edge","2012","240","270" +"165","70","138","Front-wheel drive","Ford 2.0L 4 Cylinder 240 hp 270 ft-lbs Turbo","True","6","6 Speed Automatic","21","Gasoline","30","Automatic transmission","2012 Ford Edge Limited Turbo","Ford","2012 Ford Edge","2012","240","270" +"165","70","138","Front-wheel drive","Ford 2.0L 4 Cylinder 240 hp 270 ft-lbs Turbo","True","6","6 Speed Automatic","21","Gasoline","30","Automatic transmission","2012 Ford Edge SEL Turbo","Ford","2012 Ford Edge","2012","240","270" +"89","27","62","All-wheel drive","Audi 4.2L 8 cylinder 354hp 325 ft-lbs","True","6","6 Speed Automatic Select Shift","16","Gasoline","24","Automatic transmission","2010 Audi S5 Coupe 4.2 AT","Audi","2010 Audi S5 Coupe","2010","354","325" +"89","27","62","All-wheel drive","Audi 4.2L 8 cylinder 354hp 325 ft-lbs","True","6","6 Speed Manual","14","Gasoline","22","Manual transmission","2010 Audi S5 Coupe 4.2","Audi","2010 Audi S5 Coupe","2010","354","325" +"169","52","237","All-wheel drive","Audi 5.2L 10 Cylinder 435hp 398 ft-lbs","True","6","6 Speed Automatic Select Shift","14","Gasoline","21","Automatic transmission","2011 Audi S6","Audi","2011 Audi S6","2011","435","398" +"169","52","220","All-wheel drive","Audi 5.2L 10 Cylinder 435hp 398 ft-lbs","True","6","6 Speed Automatic Select Shift","14","Gasoline","19","Automatic transmission","2010 Audi S6","Audi","2010 Audi S6","2010","435","398" +"155","151","216","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Manual","26","Gasoline","34","Manual transmission","2011 Honda Civic DX Sedan","Honda","2011 Honda Civic Sedan","2011","140","128" +"155","151","216","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Automatic","25","Gasoline","36","Automatic transmission","2011 Honda Civic DX Sedan AT","Honda","2011 Honda Civic Sedan","2011","140","128" +"155","151","216","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Manual","26","Gasoline","34","Manual transmission","2011 Honda Civic DX-VP Sedan","Honda","2011 Honda Civic Sedan","2011","140","128" +"155","151","216","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Automatic","25","Gasoline","36","Automatic transmission","2011 Honda Civic DX-VP Sedan AT","Honda","2011 Honda Civic Sedan","2011","140","128" +"155","151","216","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Manual","26","Gasoline","34","Manual transmission","2011 Honda Civic LX Sedan","Honda","2011 Honda Civic Sedan","2011","140","128" +"155","151","216","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Automatic","25","Gasoline","36","Automatic transmission","2011 Honda Civic LX Sedan AT","Honda","2011 Honda Civic Sedan","2011","140","128" +"155","151","216","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Manual","26","Gasoline","34","Manual transmission","2011 Honda Civic LX-S Sedan","Honda","2011 Honda Civic Sedan","2011","140","128" +"155","151","216","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Automatic","25","Gasoline","36","Automatic transmission","2011 Honda Civic LX-S Sedan AT","Honda","2011 Honda Civic Sedan","2011","140","128" +"155","151","216","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Manual","26","Gasoline","34","Manual transmission","2011 Honda Civic EX Sedan","Honda","2011 Honda Civic Sedan","2011","140","128" +"155","151","216","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Automatic","25","Gasoline","36","Automatic transmission","2011 Honda Civic EX Sedan AT","Honda","2011 Honda Civic Sedan","2011","140","128" +"155","151","216","Front-wheel drive","Honda 1.8L 4 Cylinder 140hp 128 ft-lbs","True","5","5 Speed Automatic","25","Gasoline","36","Automatic transmission","2011 Honda Civic EX-L Sedan","Honda","2011 Honda Civic Sedan","2011","140","128" +"155","151","216","Front-wheel drive","Honda 2.0L 4 Cyinder 197 hp 139 ft-lbs","True","6","6 Speed Manual","21","Gasoline","29","Manual transmission","2011 Honda Civic Si Sedan","Honda","2011 Honda Civic Sedan","2011","197","139" +"155","151","216","Front-wheel drive","Honda 1.8L 4 Cylinder 113 hp 109 ft-lbs CNG","True","5","5 Speed Automatic","24","Compressed natural gas","36","Automatic transmission","2011 Honda Civic GX Sedan","Honda","2011 Honda Civic Sedan","2011","113","109" +"212","108","135","Rear-wheel drive","Chevrolet 7.0L 8 Cylinder 505 hp 470 ft-lbs","True","6","6 Speed Manual","15","Gasoline","24","Manual transmission","2012 Chevrolet Corvette Z06 1LZ","Chevrolet","2012 Chevrolet Corvette Z06","2012","505","470" +"212","108","135","Rear-wheel drive","Chevrolet 7.0L 8 Cylinder 505 hp 470 ft-lbs","True","6","6 Speed Manual","15","Gasoline","24","Manual transmission","2012 Chevrolet Corvette Z06 2LZ","Chevrolet","2012 Chevrolet Corvette Z06","2012","505","470" +"212","108","135","Rear-wheel drive","Chevrolet 7.0L 8 Cylinder 505 hp 470 ft-lbs","True","6","6 Speed Manual","15","Gasoline","24","Manual transmission","2012 Chevrolet Corvette Z06 3LZ","Chevrolet","2012 Chevrolet Corvette Z06","2012","505","470" +"212","108","135","Rear-wheel drive","Chevrolet 7.0L 8 Cylinder 505 hp 470 ft-lbs","True","6","6 Speed Manual","15","Gasoline","24","Manual transmission","2011 Chevrolet Corvette Z06 1LZ","Chevrolet","2011 Chevrolet Corvette Z06","2011","505","470" +"212","108","135","Rear-wheel drive","Chevrolet 7.0L 8 Cylinder 505 hp 470 ft-lbs","True","6","6 Speed Manual","15","Gasoline","24","Manual transmission","2011 Chevrolet Corvette Z06 2LZ","Chevrolet","2011 Chevrolet Corvette Z06","2011","505","470" +"212","108","135","Rear-wheel drive","Chevrolet 7.0L 8 Cylinder 505 hp 470 ft-lbs","True","6","6 Speed Manual","15","Gasoline","24","Manual transmission","2011 Chevrolet Corvette Z06 3LZ","Chevrolet","2011 Chevrolet Corvette Z06","2011","505","470" +"212","108","135","Rear-wheel drive","Chevrolet 7.0L 8 Cylinder 505 hp 470 ft-lbs","True","6","6 Speed Manual","15","Gasoline","24","Manual transmission","2010 Chevrolet Corvette Z06 1LZ","Chevrolet","2010 Chevrolet Corvette Z06","2010","505","470" +"212","108","135","Rear-wheel drive","Chevrolet 7.0L 8 Cylinder 505 hp 470 ft-lbs","True","6","6 Speed Manual","15","Gasoline","24","Manual transmission","2010 Chevrolet Corvette Z06 2LZ","Chevrolet","2010 Chevrolet Corvette Z06","2010","505","470" +"212","108","135","Rear-wheel drive","Chevrolet 7.0L 8 Cylinder 505 hp 470 ft-lbs","True","6","6 Speed Manual","15","Gasoline","24","Manual transmission","2010 Chevrolet Corvette Z06 3LZ","Chevrolet","2010 Chevrolet Corvette Z06","2010","505","470" +"223","82","52","Rear-wheel drive","Chevrolet 6.2L 8 Cylinder 430 hp 424 ft-lbs","True","6","6 Speed Manual","16","Gasoline","26","Manual transmission","2012 Chevrolet Corvette Convertible 1LT","Chevrolet","2012 Chevrolet Corvette Convertible","2012","430","424" +"223","82","52","Rear-wheel drive","Chevrolet 6.2L 8 Cylinder 430 hp 424 ft-lbs","True","6","6 Speed Automatic Select Shift","15","Gasoline","25","Automatic transmission","2012 Chevrolet Corvette Convertible 1LT AT","Chevrolet","2012 Chevrolet Corvette Convertible","2012","430","424" +"223","82","52","Rear-wheel drive","Chevrolet 6.2L 8 Cylinder 430 hp 424 ft-lbs","True","6","6 Speed Manual","16","Gasoline","26","Manual transmission","2012 Chevrolet Corvette Convertible 2LT","Chevrolet","2012 Chevrolet Corvette Convertible","2012","430","424" +"223","82","52","Rear-wheel drive","Chevrolet 6.2L 8 Cylinder 430 hp 424 ft-lbs","True","6","6 Speed Automatic Select Shift","15","Gasoline","25","Automatic transmission","2012 Chevrolet Corvette Convertible 2LT AT","Chevrolet","2012 Chevrolet Corvette Convertible","2012","430","424" +"223","82","52","Rear-wheel drive","Chevrolet 6.2L 8 Cylinder 430 hp 424 ft-lbs","True","6","6 Speed Manual","16","Gasoline","26","Manual transmission","2012 Chevrolet Corvette Convertible 3LT","Chevrolet","2012 Chevrolet Corvette Convertible","2012","430","424" +"223","82","52","Rear-wheel drive","Chevrolet 6.2L 8 Cylinder 430 hp 424 ft-lbs","True","6","6 Speed Automatic Select Shift","15","Gasoline","25","Automatic transmission","2012 Chevrolet Corvette Convertible 3LT AT","Chevrolet","2012 Chevrolet Corvette Convertible","2012","430","424" +"223","82","52","Rear-wheel drive","Chevrolet 6.2L 8 Cylinder 430 hp 424 ft-lbs","True","6","6 Speed Manual","16","Gasoline","26","Manual transmission","2012 Chevrolet Corvette Convertible 4LT","Chevrolet","2012 Chevrolet Corvette Convertible","2012","430","424" +"223","82","52","Rear-wheel drive","Chevrolet 6.2L 8 Cylinder 430 hp 424 ft-lbs","True","6","6 Speed Automatic Select Shift","15","Gasoline","25","Automatic transmission","2012 Chevrolet Corvette Convertible 4LT AT","Chevrolet","2012 Chevrolet Corvette Convertible","2012","430","424" +"52","20","57","Four-wheel drive","Nissan 4.0L 6 Cylinder 266 hp 288 ft-lbs","True","5","5 Speed Automatic","14","Gasoline","20","Automatic transmission","2010 Nissan Pathfinder S 4x4","Nissan","2010 Nissan Pathfinder","2010","266","288" +"36","20","57","Rear-wheel drive","Nissan 4.0L 6 Cylinder 266 hp 288 ft-lbs","True","5","5 Speed Automatic","15","Gasoline","22","Automatic transmission","2010 Nissan Pathfinder S FE+","Nissan","2010 Nissan Pathfinder","2010","266","288" +"41","20","57","Rear-wheel drive","Nissan 4.0L 6 Cylinder 266 hp 288 ft-lbs","True","5","5 Speed Automatic Select Shift","15","Gasoline","22","Automatic transmission","2010 Nissan Pathfinder SE","Nissan","2010 Nissan Pathfinder","2010","266","288" +"52","20","57","Four-wheel drive","Nissan 4.0L 6 Cylinder 266 hp 288 ft-lbs","True","5","5 Speed Automatic Select Shift","14","Gasoline","20","Automatic transmission","2010 Nissan Pathfinder LE 4x4","Nissan","2010 Nissan Pathfinder","2010","266","288" +"54","20","57","Four-wheel drive","Nissan 5.6L 8 Cylinder 310 hp 388 ft-lbs","True","5","5 Speed Automatic Select Shift","13","Gasoline","18","Automatic transmission","2010 Nissan Pathfinder LE 4x4 V8","Nissan","2010 Nissan Pathfinder","2010","310","388" +"52","20","57","Four-wheel drive","Nissan 4.0L 6 Cylinder 266 hp 288 ft-lbs","True","5","5 Speed Automatic Select Shift","14","Gasoline","20","Automatic transmission","2010 Nissan Pathfinder SE 4x4","Nissan","2010 Nissan Pathfinder","2010","266","288" +"41","20","57","Rear-wheel drive","Nissan 4.0L 6 Cylinder 266 hp 288 ft-lbs","True","5","5 Speed Automatic Select Shift","15","Gasoline","22","Automatic transmission","2010 Nissan Pathfinder LE","Nissan","2010 Nissan Pathfinder","2010","266","288" +"214","15","161","Front-wheel drive","Volkswagen 3.8l 6 Cylinder 197HP 230 ft-lbs","True","6","6 Speed Automatic","16","Gasoline","23","Automatic transmission","2010 Volkswagen Routan S","Volkswagen","2010 Volkswagen Routan","2010","197","230" +"214","23","161","Front-wheel drive","Volkswagen 3.8l 6 Cylinder 197HP 230 ft-lbs","True","6","6 Speed Automatic","16","Gasoline","23","Automatic transmission","2010 Volkswagen Routan SE","Volkswagen","2010 Volkswagen Routan","2010","197","230" +"214","15","161","Front-wheel drive","Volkswagen 4.0l 6 Cylinder 251HP 259 ft-lbs","True","6","6 Speed Automatic","17","Gasoline","25","Automatic transmission","2010 Volkswagen Routan SEL","Volkswagen","2010 Volkswagen Routan","2010","251","259" +"214","23","161","Front-wheel drive","Volkswagen 4.0l 6 Cylinder 251HP 259 ft-lbs","True","6","6 Speed Automatic","17","Gasoline","25","Automatic transmission","2010 Volkswagen Routan SEL Premium","Volkswagen","2010 Volkswagen Routan","2010","251","259" +"41","25","57","Rear-wheel drive","Nissan 4.0L 6 Cylinder 266 hp 288 ft-lbs","True","5","5 Speed Automatic","15","Gasoline","22","Automatic transmission","2009 Nissan Pathfinder LE","Nissan","2009 Nissan Pathfinder","2009","266","288" +"52","25","57","Four-wheel drive","Nissan 4.0L 6 Cylinder 266 hp 288 ft-lbs","True","5","5 Speed Automatic","14","Gasoline","20","Automatic transmission","2009 Nissan Pathfinder SE Off-Road","Nissan","2009 Nissan Pathfinder","2009","266","288" +"52","25","57","Four-wheel drive","Nissan 4.0L 6 Cylinder 266 hp 288 ft-lbs","True","5","5 Speed Automatic","14","Gasoline","20","Automatic transmission","2009 Nissan Pathfinder SE 4x4","Nissan","2009 Nissan Pathfinder","2009","266","288" +"54","25","57","Four-wheel drive","Nissan 5.6L 8 Cylinder 310 hp 388 ft-lbs","True","5","5 Speed Automatic","13","Gasoline","18","Automatic transmission","2009 Nissan Pathfinder LE 4x4 V8","Nissan","2009 Nissan Pathfinder","2009","310","388" +"36","25","57","Rear-wheel drive","Nissan 4.0L 6 Cylinder 266 hp 288 ft-lbs","True","5","5 Speed Automatic","15","Gasoline","22","Automatic transmission","2009 Nissan Pathfinder S","Nissan","2009 Nissan Pathfinder","2009","266","288" +"52","25","57","Four-wheel drive","Nissan 4.0L 6 Cylinder 266 hp 288 ft-lbs","True","5","5 Speed Automatic","14","Gasoline","20","Automatic transmission","2009 Nissan Pathfinder S 4x4","Nissan","2009 Nissan Pathfinder","2009","266","288" diff --git a/samples/Basic_Templates/files/classics.csv b/samples/Basic_Templates/files/classics.csv new file mode 100644 index 0000000000..99d8d5a84b --- /dev/null +++ b/samples/Basic_Templates/files/classics.csv @@ -0,0 +1,1007 @@ +"bibliography.congress classifications","bibliography.languages","bibliography.subjects","bibliography.title","bibliography.type","metadata.downloads","metadata.id","metadata.rank","metadata.url","bibliography.author.birth","bibliography.author.death","bibliography.author.name","bibliography.publication.day","bibliography.publication.full","bibliography.publication.month","bibliography.publication.month name","bibliography.publication.year","metadata.formats.total","metadata.formats.types","metrics.difficulty.automated readability index","metrics.difficulty.coleman liau index","metrics.difficulty.dale chall readability score","metrics.difficulty.difficult words","metrics.difficulty.flesch kincaid grade","metrics.difficulty.flesch reading ease","metrics.difficulty.gunning fog","metrics.difficulty.linsear write formula","metrics.difficulty.smog index","metrics.sentiments.polarity","metrics.sentiments.subjectivity","metrics.statistics.average letter per word","metrics.statistics.average sentence length","metrics.statistics.average sentence per word","metrics.statistics.characters","metrics.statistics.polysyllables","metrics.statistics.sentences","metrics.statistics.syllables","metrics.statistics.words" +"PR","en","Sisters -- Fiction,Courtship -- Fiction,Social classes -- Fiction,England -- Fiction,Domestic fiction,Young women -- Fiction,Love stories","Pride and Prejudice","Text","36576","1342","1","https://www.gutenberg.org/ebooks/1342","1775","1817","Austen, Jane","1","June, 1998","6","June","1998","8","text/plain,text/plain; charset=us-ascii,application/pdf,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","10.7","10.73","5.7","9032","7.9","70.13","9.200000000000001","13.5","3.1","0.13671337760500446","0.5222391494704692","4.83","18.0","0.05","586794","4603","6511","170648.1","121533" +"PS","en","Mentally ill women -- Fiction,Feminist fiction,Psychological fiction,Married women -- Psychology -- Fiction,Sex role -- Fiction","The Yellow Wallpaper","Text","26363","1952","2","https://www.gutenberg.org/ebooks/1952","1860","1935","Gilman, Charlotte Perkins","1","November, 1999","11","November","1999","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","7.2","8.0","6.24","714","5.6","81.63","8.0","5.5","3.1","0.054174293365012734","0.5347874264082076","4.41","15.0","0.06","26769","102","385","7686.9","6067" +"PZ,PR","en","Fantasy","Alice's Adventures in Wonderland","Text","18882","11","3","https://www.gutenberg.org/ebooks/11","1832","1898","Carroll, Lewis","1","March, 1994","3","March","1994","8","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/pdf","9.3","9.39","5.93","2425","6.4","79.6","8.8","14.0","3.1","0.04107860874944599","0.49727636711271855","4.65","17.0","0.06","122719","339","1501","33810.3","26389" +"PR","en","Monsters -- Fiction;Frankenstein's monster (Fictitious character) -- Fiction;Gothic fiction (Literary genre);Science fiction;Frankenstein, Victor (Fictitious character) -- Fiction;Scientists -- Fiction;Horror tales","Frankenstein; Or, The Modern Prometheus","Text","17128","84","4","https://www.gutenberg.org/ebooks/84","1797","1851","Shelley, Mary Wollstonecraft","17","June 17, 2008","6","June","2008","7","text/html; charset=iso-8859-1,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","12.6","10.68","6.44","7884","9.9","65.05","11.200000000000001","7.0","3.1","0.10090153627465286","0.5395161487551757","4.77","23.0","0.04","357604","2604","3239","106802.1","74959" +"PT","en","Psychological fiction,Metamorphosis -- Fiction","Metamorphosis","Text","15683","5200","5","https://www.gutenberg.org/ebooks/5200","1883","1924","Kafka, Franz","16","August 16, 2005","8","August","2005","8","text/plain; charset=us-ascii,text/rtf,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","13.8","9.46","6.37","1947","10.3","69.45","12.8","10.5","3.1","0.041996935670926445","0.47901921546913884","4.56","27.0","0.04","100372","397","800","28752.3","22022" +"PS","en","Male friendship -- Fiction;Humorous stories;Missouri -- Fiction;Race relations -- Fiction;Bildungsromans;Finn, Huckleberry (Fictitious character) -- Fiction;Fugitive slaves -- Fiction;Mississippi River -- Fiction;Adventure stories;Runaway children -- Fiction;Boys -- Fiction","Adventures of Huckleberry Finn","Text","15347","76","6","https://www.gutenberg.org/ebooks/76","1835","1910","Twain, Mark","20","August 20, 2006","8","August","2006","8","image/jpeg,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","8.7","8.01","5.59","7087","6.0","86.03","9.600000000000001","2.5","3.1","0.08931925862018178","0.4745187951630081","4.36","19.0","0.05","485099","1180","5792","132642.9","111219" +"PR","en","Identity (Psychology) -- Drama,Comedies,England -- Drama,Foundlings -- Drama","The Importance of Being Earnest: A Trivial Comedy for Serious People","Text","13638","844","7","https://www.gutenberg.org/ebooks/844","1854","1900","Wilde, Oscar","29","August 29, 2006","8","August","2006","7","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","7.0","9.89","5.96","2387","4.8","78.25","6.0","3.0","3.1","0.10026968514280647","0.534784343060185","4.94","10.0","0.1","101906","555","1994","29187.0","20625" +"PZ,PS","en","Male friendship -- Fiction;Humorous stories;Missouri -- Fiction;Child witnesses -- Fiction;Bildungsromans;Mississippi River Valley -- Fiction;Adventure stories;Runaway children -- Fiction;Boys -- Fiction;Sawyer, Tom (Fictitious character) -- Fiction","The Adventures of Tom Sawyer","Text","13237","74","8","https://www.gutenberg.org/ebooks/74","1835","1910","Twain, Mark","20","August 20, 2006","8","August","2006","8","image/jpeg,text/html; charset=iso-8859-1,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","8.8","10.15","6.16","7974","5.6","81.63","8.0","4.5","3.1","0.06476107829562262","0.48704844378158596","4.78","15.0","0.06","338075","1488","4594","92593.8","70796" +"E300","en","Slaves -- United States -- Biography;Douglass, Frederick, 1818-1895;African American abolitionists -- Biography;Abolitionists -- United States -- Biography","Narrative of the Life of Frederick Douglass, an American Slave","Text","12794","23","9","https://www.gutenberg.org/ebooks/23","1818","1895","Douglass, Frederick","10","January 10, 2006","1","January","2006","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","10.5","9.86","6.48","4894","8.3","69.11","9.600000000000001","7.0","3.1","0.09387813584045827","0.5074296460875009","4.68","19.0","0.05","190493","1226","2062","55913.4","40740" +"PT","en","Wives -- Drama,Man-woman relationships -- Drama,Marriage -- Drama,Norwegian drama -- Translations into English","A Doll's House : a play","Text","11625","2542","10","https://www.gutenberg.org/ebooks/2542","1828","1906","Ibsen, Henrik","1","March, 2001","3","March","2001","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","5.3","7.98","5.53","2342","3.7","86.71","6.0","4.0","3.1","0.026261727941188452","0.5805215079924373","4.61","10.0","0.1","121943","378","2624","33722.1","26466" +"PS","en","Ship captains -- Fiction;Whaling ships -- Fiction;Psychological fiction;Whaling -- Fiction;Whales -- Fiction;Ahab, Captain (Fictitious character) -- Fiction;Sea stories;Adventure stories;Mentally ill -- Fiction","Moby Dick; Or, The Whale","Text","11270","2701","11","https://www.gutenberg.org/ebooks/2701","1819","1891","Melville, Herman","1","June, 2001","6","June","2001","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","13.4","11.55","6.5","23167","9.9","65.05","11.200000000000001","11.0","3.1","0.08228645346376395","0.4780492613378924","4.92","23.0","0.04","1043045","6639","9104","294744.6","212099" +"PR","en","Private investigators -- England -- Fiction;Detective and mystery stories, English;Holmes, Sherlock (Fictitious character) -- Fiction","The Adventures of Sherlock Holmes","Text","11125","1661","12","https://www.gutenberg.org/ebooks/1661","1859","1930","Doyle, Arthur Conan","14","October 14, 1892","10","October","1892","8","application/rdf+xml,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,text/plain","8.2","9.1","5.81","9148","6.0","80.62","8.4","2.5","3.1","0.06259143797439362","0.48668184738715853","4.6","16.0","0.06","480294","1978","6522","137215.8","104488" +"PR","en","Revenge -- Fiction,Ex-convicts -- Fiction,Orphans -- Fiction,Bildungsromans,England -- Fiction,Man-woman relationships -- Fiction,Benefactors -- Fiction,Young men -- Fiction","Great Expectations","Text","11068","1400","13","https://www.gutenberg.org/ebooks/1400","1812","1870","Dickens, Charles","1","July, 1998","7","July","1998","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","9.9","9.34","5.8","14224","7.2","77.57","9.600000000000001","7.5","3.1","0.07798368485830932","0.4906242353128296","4.59","19.0","0.05","845501","4088","9487","240762.6","184398" +"PR","en","Male friendship -- Fiction,City and town life -- Fiction,Psychological fiction,Alienation (Social psychology) -- Fiction,Married people -- Fiction,Jewish men -- Fiction,Artists -- Fiction,Epic literature,Domestic fiction,Dublin (Ireland) -- Fiction","Ulysses","Text","10568","4300","14","https://www.gutenberg.org/ebooks/4300","1882","1941","Joyce, James","1","July, 2003","7","July","2003","7","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","8.6","10.84","6.35","34649","6.0","75.2","7.2","6.0","3.1","0.07123035788724716","0.46306693286286965","4.95","13.0","0.07","1311231","7005","19726","363292.2","264835" +"PR","en","War stories;France -- History -- Revolution, 1789-1799 -- Fiction;Paris (France) -- History -- 1789-1799 -- Fiction;French -- England -- London -- Fiction;Executions and executioners -- Fiction;London (England) -- History -- 18th century -- Fiction;British -- France -- Paris -- Fiction;Historical fiction;Lookalikes -- Fiction","A Tale of Two Cities","Text","10312","98","15","https://www.gutenberg.org/ebooks/98","1812","1870","Dickens, Charles","1","January, 1994","1","January","1994","8","application/rdf+xml,text/html; charset=iso-8859-1,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","10.3","10.44","6.0","12613","6.8","78.59","9.200000000000001","56.0","3.1","0.07806610204565802","0.4904532055717023","4.78","18.0","0.05","649070","3256","7396","183016.8","135820" +"PR","en","Ireland -- Politics and government -- 18th century -- Humor;Religious satire, English;Political satire, English","A Modest Proposal: For preventing the children of poor people in Ireland, from being a burden on their parents or country, and for making them beneficial to the publick","Text","10014","1080","16","https://www.gutenberg.org/ebooks/1080","1667","1745","Swift, Jonathan","1","October 1997","10","October","1997","6","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","26.6","11.91","9.24","674","20.4","37.65","22.0","18.0","8.8","0.1756914585039587","0.5064583455208455","4.88","50.0","0.02","16656","86","68","4864.5","3410" +"PR","en","Dracula, Count (Fictitious character) -- Fiction;Epistolary fiction;Vampires -- Fiction;Gothic fiction (Literary genre);Transylvania (Romania) -- Fiction;Whitby (England) -- Fiction;Horror tales","Dracula","Text","9852","345","17","https://www.gutenberg.org/ebooks/345","1847","1912","Stoker, Bram","16","August 16, 2013","8","August","2013","9","image/jpeg,text/html; charset=utf-8,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","8.8","8.3","5.65","11445","6.8","78.59","9.200000000000001","18.0","3.1","0.075270589540311","0.5030392097632636","4.41","18.0","0.05","708335","2338","8522","202932.9","160693" +"JC","en","Political ethics -- Early works to 1800;Political science -- Philosophy -- Early works to 1800;State, The -- Early works to 1800","The Prince","Text","9690","1232","18","https://www.gutenberg.org/ebooks/1232","1469","1527","Machiavelli, Niccolo","11","February 11, 2006","2","February","2006","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","20.6","11.33","7.23","5367","15.8","49.83","17.2","6.5","8.8","0.1465468177804127","0.5204133612464581","4.83","38.0","0.03","239378","1905","1287","71705.7","49525" +"PR","en","London (England) -- History -- 1800-1950 -- Fiction;Conduct of life -- Fiction;Paranormal fiction;Portraits -- Fiction;Appearance (Philosophy) -- Fiction;Supernatural -- Fiction;Great Britain -- History -- Victoria, 1837-1901 -- Fiction;Didactic fiction","The Picture of Dorian Gray","Text","9681","174","19","https://www.gutenberg.org/ebooks/174","1854","1900","Wilde, Oscar","9","June 9, 2008","6","June","2008","7","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","6.7","8.69","5.74","7523","4.4","84.68","6.800000000000001","4.5","3.1","0.06991381964989916","0.5458973341303766","4.63","12.0","0.08","365606","1647","6234","105003.9","78920" +"PG","en","War stories;Napoleonic Wars, 1800-1815 -- Campaigns -- Russia -- Fiction;Aristocracy (Social class) -- Russia -- Fiction;Historical fiction;Russia -- History -- Alexander I, 1801-1825 -- Fiction","War and Peace","Text","9580","2600","20","https://www.gutenberg.org/ebooks/2600","1828","1910","Tolstoy, Leo, graf","1","January 1, 1870","1","January","1870","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/html; charset=us-ascii","10.8","11.14","5.36","29647","7.9","70.13","9.200000000000001","53.0","3.1","0.08206641711733968","0.47401511558244336","4.9","18.0","0.05","2759940","16369","30757","787942.8","563029" +"PT","en","Fairy tales -- Germany","Grimms' Fairy Tales","Text","9016","2591","21","https://www.gutenberg.org/ebooks/2591","1786","1859","Grimm, Wilhelm","1","April, 2001","4","April","2001","8","application/x-mobipocket-ebook,text/plain; charset=us-ascii,application/pdf,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","10.5","8.01","1.91","4955","7.5","81.97","11.200000000000001","13.0","3.1","0.10661117464793538","0.4841397158628057","4.31","23.0","0.04","435880","394","4355","121229.1","101107" +"HQ","en","Love,Sex","The Kama Sutra of Vatsyayana: Translated From the Sanscrit in Seven Parts With Preface, Introduction and Concluding Remarks","Text","8559","27827","22","https://www.gutenberg.org/ebooks/27827","0","0","Vatsyayana","18","January 18, 2009","1","January","2009","8","application/rdf+xml,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,text/plain","13.5","10.91","6.36","5708","10.3","64.04","11.600000000000001","6.0","3.1","0.13107012953611397","0.46422065099943055","4.81","24.0","0.04","283286","1464","2397","81087.3","58912" +"PR","en","Fathers and daughters -- Fiction,Humorous stories,Bildungsromans,England -- Fiction,Mate selection -- Fiction,Female friendship -- Fiction,Young women -- Fiction,Love stories","Emma","Text","8513","158","23","https://www.gutenberg.org/ebooks/158","1775","1817","Austen, Jane","1","August, 1994","8","August","1994","8","text/plain,text/html; charset=us-ascii,text/plain; charset=us-ascii,application/pdf,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.6","10.26","5.68","12447","7.2","72.16","8.4","18.0","3.1","0.157109182497322","0.5423073450027583","4.8","16.0","0.06","755056","4851","9348","216434.7","157439" +"PR","en","Dragons -- Poetry;Epic poetry, English (Old);Monsters -- Poetry","Beowulf: An Anglo-Saxon Epic Poem","Text","8199","16328","24","https://www.gutenberg.org/ebooks/16328","0","0","Unknown","19","July 19, 2005","7","July","2005","8","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","13.3","14.03","7.5","7311","7.9","70.13","9.200000000000001","8.0","3.1","0.13712860361621118","0.5371790132759954","5.45","18.0","0.06","211970","900","2142","54235.8","38925" +"PQ","en","Paris (France) -- Fiction,Ex-convicts -- Fiction,Epic literature,Orphans -- Fiction,Historical fiction","Les Misérables","Text","7900","135","25","https://www.gutenberg.org/ebooks/135","1802","1885","Hugo, Victor","22","June 22, 2008","6","June","2008","5","text/html; charset=utf-8,application/rdf+xml,application/epub+zip,image/jpeg,application/x-mobipocket-ebook","10.2","11.02","5.51","38795","7.2","72.16","8.4","6.5","3.1","0.0777559225920661","0.494210060487325","4.93","16.0","0.06","2783024","17239","33543","790112.7","565071" +"PR","en","Erotic stories","The Romance of Lust: A Classic Victorian erotic novel","Text","7458","30254","26","https://www.gutenberg.org/ebooks/30254","0","0","Anonymous","14","October 14, 2009","10","October","2009","8","text/html,text/plain; charset=us-ascii,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","12.9","9.93","5.68","10266","10.3","64.04","11.600000000000001","7.0","3.1","0.19117116184685465","0.5466514480657667","4.64","24.0","0.04","876698","4879","7588","256281.3","188911" +"PR","en","Country homes -- Fiction,Fathers and daughters -- Fiction,Charity-schools -- Fiction,Orphans -- Fiction,Bildungsromans,England -- Fiction,Married people -- Fiction,Mentally ill women -- Fiction,Governesses -- Fiction,Young women -- Fiction,Love stories","Jane Eyre: An Autobiography","Text","7449","1260","27","https://www.gutenberg.org/ebooks/1260","1816","1855","Bronte, Charlotte","29","April 29, 2007","4","April","2007","6","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","10.4","10.1","6.17","18723","8.3","69.11","9.600000000000001","8.5","3.1","0.0841139886145198","0.5025611302873831","4.72","19.0","0.05","876153","4697","9674","250376.4","185452" +"PS","en","American poetry -- 19th century","Leaves of Grass","Text","6899","1322","28","https://www.gutenberg.org/ebooks/1322","1819","1892","Whitman, Walt","1","May, 1998","5","May","1998","6","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","19.1","12.25","7.34","15547","14.2","53.89","15.600000000000001","26.0","3.1","0.14474490574127938","0.5076378089163257","4.99","34.0","0.03","607831","2727","3570","165151.8","121711" +"PR","en","Short stories,Dublin (Ireland) -- Fiction","Dubliners","Text","6879","2814","29","https://www.gutenberg.org/ebooks/2814","1882","1941","Joyce, James","1","September, 2001","9","September","2001","6","text/html; charset=utf-8,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","8.0","9.21","6.0","7147","5.2","82.65","7.6000000000000005","17.0","3.1","0.06809492924074417","0.47237120583594877","4.67","14.0","0.07","315667","1148","4530","88344.0","67546" +"PR","en","Gentry -- England -- Fiction,Sisters -- Fiction,Social classes -- Fiction,England -- Social life and customs -- 19th century -- Fiction,England -- Fiction,Mate selection -- Fiction,Regency fiction,Inheritance and succession -- Fiction,Domestic fiction,Young women -- Fiction,Love stories","Sense and Sensibility","Text","6503","161","30","https://www.gutenberg.org/ebooks/161","1775","1817","Austen, Jane","25","May 25, 2008","5","May","2008","8","application/x-mobipocket-ebook,text/html; charset=iso-8859-1,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/pdf","12.3","10.85","5.9","9203","9.1","67.08","10.4","13.5","3.1","0.131879813586973","0.5325451309613446","4.85","21.0","0.05","574844","3913","5447","167003.1","118578" +"JC","en","Political science -- Early works to 1800;State, The -- Early works to 1800","Leviathan","Text","6411","3207","31","https://www.gutenberg.org/ebooks/3207","1588","1679","Hobbes, Thomas","1","May, 2002","5","May","2002","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","20.6","11.56","6.72","16169","15.8","49.83","17.2","11.0","8.8","0.11616782697752301","0.46430038311161786","4.87","38.0","0.03","1038638","7741","5581","305930.7","213304" +"PR","en","Self-experimentation in medicine -- Fiction,Psychological fiction,Multiple personality -- Fiction,Physicians -- Fiction,London (England) -- Fiction,Science fiction,Horror tales","The Strange Case of Dr. Jekyll and Mr. Hyde","Text","6410","42","32","https://www.gutenberg.org/ebooks/42","1850","1894","Stevenson, Robert Louis","1","October, 1992","10","October","1992","7","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","11.0","9.63","6.82","3485","7.9","75.54","10.4","7.5","3.1","0.06787933764993412","0.4877173556522048","4.64","21.0","0.05","119352","545","1215","34174.8","25740" +"PR,PZ","en","Treasure Island (Imaginary place) -- Fiction,Pirates -- Fiction,Treasure troves -- Fiction,Sea stories","Treasure Island","Text","6396","120","33","https://www.gutenberg.org/ebooks/120","1850","1894","Stevenson, Robert Louis","25","February 25, 2006","2","February","2006","8","application/x-mobipocket-ebook,image/jpeg,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","9.2","8.88","5.96","6192","6.8","78.59","9.200000000000001","18.0","3.1","0.07407747334028003","0.47350471800100735","4.51","18.0","0.05","307677","782","3625","85782.6","68267" +"PR","en","Revenge -- Fiction,Psychological fiction,Foundlings -- Fiction,Heathcliff (Fictitious character : Brontë) -- Fiction,Triangles (Interpersonal relations) -- Fiction,Rural families -- Fiction,Domestic fiction,Rejection (Psychology) -- Fiction,Yorkshire (England) -- Fiction,Love stories","Wuthering Heights","Text","6237","768","34","https://www.gutenberg.org/ebooks/768","1818","1848","Bronte, Emily","19","April 19, 2007","4","April","2007","7","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","9.9","10.09","6.07","11639","6.4","79.6","8.8","5.0","3.1","0.04585489516510218","0.510068286883796","4.77","17.0","0.06","552364","2750","6524","156315.6","115874" +"PR","en","Africa -- Fiction,Psychological fiction,Imperialism -- Fiction,Trading posts -- Fiction,Europeans -- Africa -- Fiction,Degeneration -- fiction","Heart of Darkness","Text","5875","219","35","https://www.gutenberg.org/ebooks/219","1857","1924","Conrad, Joseph","1","February 1995","2","February","1995","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","9.0","9.8","6.68","5407","7.2","72.16","8.4","13.0","3.1","0.04901319630088766","0.5026182298220377","4.72","16.0","0.06","178939","1128","2309","51631.2","37902" +"PQ","en","Adventure stories;Revenge -- Fiction;France -- History -- 19th century -- Fiction;Pirates -- Fiction;Historical fiction;Prisoners -- Fiction;Dantès, Edmond (Fictitious character) -- Fiction","The Count of Monte Cristo, Illustrated","Text","5861","1184","36","https://www.gutenberg.org/ebooks/1184","1802","1870","Dumas, Alexandre","1","January, 1998","1","January","1998","7","application/x-mobipocket-ebook,image/jpeg,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/rdf+xml,application/epub+zip,text/plain","10.8","11.14","5.51","28477","7.9","70.13","9.200000000000001","13.5","3.1","0.09324194609829525","0.4975364718118205","4.9","18.0","0.05","2248795","13018","25116","638292.6","459021" +"PR","en","Fantasy fiction;Satire;Voyages, Imaginary -- Early works to 1800;Travelers -- Fiction;Gulliver, Lemuel (Fictitious character) -- Fiction","Gulliver's Travels into Several Remote Nations of the World","Text","5752","829","37","https://www.gutenberg.org/ebooks/829","1667","1745","Swift, Jonathan","15","June 15, 2009","6","June","2009","6","text/html,text/plain; charset=utf-8,text/plain; charset=us-ascii,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","19.3","10.63","6.89","9363","15.4","50.84","16.8","4.0","8.8","0.11480158865025024","0.47662289873120817","4.71","37.0","0.03","491558","2822","2818","144955.8","104293" +"PS","en","Louisiana -- Social life and customs -- Fiction,Women -- Louisiana -- New Orleans -- Social conditions -- Fiction,New Orleans (La.) -- Fiction,Self-actualization (Psychology) -- Fiction,Adultery -- Fiction","The Awakening, and Selected Short Stories","Text","5702","160","38","https://www.gutenberg.org/ebooks/160","1850","1904","Chopin, Kate","11","March 11, 2006","3","March","2006","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","8.8","10.08","6.1","6963","6.8","73.17","8.0","18.5","3.1","0.0958378068054441","0.4823495632383955","4.82","15.0","0.07","308607","1688","4264","87984.0","63991" +"PZ,PR","en","Peter Pan (Fictitious character) -- Fiction,Fantasy,Fairies -- Juvenile fiction,Never-Never Land (Imaginary place) -- Fiction,Pirates -- Juvenile fiction","Peter Pan","Text","5657","16","39","https://www.gutenberg.org/ebooks/16","1860","1937","Barrie, J. M. (James Matthew)","1","July, 1991","7","July","1991","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","8.2","9.34","5.91","4608","5.6","81.63","8.0","12.5","3.1","0.0908218570698009","0.5243416869206348","4.64","15.0","0.06","220012","686","3054","60405.3","47437" +"PT","en","Buddhist philosophy -- Fiction,Religious fiction,Buddhism -- Fiction,India -- Fiction,Gautama Buddha -- Fiction","Siddhartha","Text","5483","2500","40","https://www.gutenberg.org/ebooks/2500","1877","1962","Hesse, Hermann","6","April 6, 2008","4","April","2008","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","11.5","10.04","6.08","3481","9.1","67.08","10.4","17.0","3.1","0.15748246437739877","0.5129865197688851","4.71","21.0","0.05","184183","817","1820","52859.7","39139" +"PA,JC","en","Utopias -- Early works to 1800,Justice -- Early works to 1800,Political science -- Early works to 1800,Classical literature","The Republic","Text","5360","1497","41","https://www.gutenberg.org/ebooks/1497","-428","-348","Plato","1","October, 1998","10","October","1998","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","14.3","10.45","6.01","14787","11.1","62.01","12.4","14.0","3.1","0.14313108039777567","0.5215148170441171","4.73","26.0","0.04","1022560","7886","8025","302949.9","216169" +"E300","en","Statesmen -- United States -- Biography;Franklin, Benjamin, 1706-1790","Autobiography of Benjamin Franklin","Text","5169","20203","42","https://www.gutenberg.org/ebooks/20203","1706","1790","Franklin, Benjamin","28","December 28, 2006","12","December","2006","9","image/jpeg,text/html; charset=iso-8859-1,text/plain,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","15.7","11.38","6.89","8971","11.8","59.98","13.200000000000001","7.5","8.8","0.14349507113184382","0.4669560103725871","4.89","28.0","0.04","371844","2885","2699","106481.7","75983" +"PR","en","Atlantic Ocean -- Fiction;Crusoe, Robinson (Fictitious character) -- Fiction;Adventure stories;Shipwreck survival -- Fiction;Castaways -- Fiction;Islands -- Fiction","The Life and Adventures of Robinson Crusoe","Text","5140","521","43","https://www.gutenberg.org/ebooks/521","0","1731","Defoe, Daniel","6","April 6, 2010","4","April","2010","7","text/html,text/plain; charset=utf-8,text/plain; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","24.0","8.55","7.0","6734","19.3","46.11","22.0","7.5","3.1","0.10530021393955503","0.47691803683950124","4.3","50.0","0.02","519352","2113","2396","153371.7","120813" +"PR","en","Pastoral poetry,English poetry -- 18th century","Songs of Innocence, and Songs of Experience","Text","5115","1934","44","https://www.gutenberg.org/ebooks/1934","1757","1827","Blake, William","25","December 25, 2008","12","December","2008","7","text/html,text/plain; charset=utf-8,text/plain; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","11.2","10.68","6.52","690","6.0","86.03","9.600000000000001","13.5","3.1","0.13704874290797575","0.5125445559491018","4.82","19.0","0.05","27028","24","283","6803.1","5602" +"PQ","en","French essays -- Translations into English","Essays of Michel de Montaigne — Complete","Text","5056","3600","45","https://www.gutenberg.org/ebooks/3600","1533","1592","Montaigne, Michel de","17","September 17, 2006","9","September","2006","8","application/x-mobipocket-ebook,image/jpeg,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","20.5","11.09","6.61","36163","15.8","49.83","17.2","11.0","8.8","0.1433959400389251","0.5253461387990033","4.79","38.0","0.03","2518187","17948","13566","745985.7","525749" +"PQ","en","Epic poetry, Italian -- Translations into English;Italian poetry -- To 1400 -- Translations into English","The Divine Comedy by Dante, Illustrated","Text","4973","8800","46","https://www.gutenberg.org/ebooks/8800","1265","1321","Dante Alighieri","1","September, 2005","9","September","2005","8","image/jpeg,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","13.9","11.09","6.62","12004","9.5","71.48","12.0","26.5","3.1","0.10851235681394195","0.49442483431831064","4.84","25.0","0.04","525296","931","4318","138464.1","108513" +"PR","en","Ghost stories;Scrooge, Ebenezer (Fictitious character) -- Fiction;Poor families -- Fiction;Christmas stories;London (England) -- Fiction;Misers -- Fiction;Sick children -- Fiction","A Christmas Carol in Prose; Being a Ghost Story of Christmas","Text","4741","46","47","https://www.gutenberg.org/ebooks/46","1812","1870","Dickens, Charles","11","August 11, 2004","8","August","2004","9","image/jpeg,text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","9.4","10.21","6.46","3668","6.0","80.62","8.4","13.0","3.1","0.10297132260911637","0.4994608844449129","4.79","16.0","0.06","136753","450","1716","37429.2","28541" +"PR","en","England -- Fiction;Detective and mystery stories;Holmes, Sherlock (Fictitious character) -- Fiction;Private investigators -- England -- Fiction","A Study in Scarlet","Text","4703","244","48","https://www.gutenberg.org/ebooks/244","1859","1930","Doyle, Arthur Conan","1","April, 1995","4","April","1995","8","text/plain; charset=us-ascii,text/plain,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","9.0","9.8","6.4","5471","7.2","72.16","8.4","11.0","3.1","0.06919942616516865","0.47509671037368656","4.72","16.0","0.06","207047","1127","2669","59502.6","43863" +"PR","en","Jungles -- Fiction;Jungle animals -- Fiction;Feral children -- Fiction;Mowgli (Fictitious character) -- Fiction;Adventure stories, English;Animals -- Fiction;Short stories;India -- Fiction","The Jungle Book","Text","4526","236","49","https://www.gutenberg.org/ebooks/236","1865","1936","Kipling, Rudyard","16","January 16, 2006","1","January","2006","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","8.8","8.7","5.86","4450","5.2","88.06","8.8","9.0","3.1","0.03740099163602172","0.4545637425100307","4.53","17.0","0.06","230331","484","2873","63501.3","50835" +"PG","en","Saint Petersburg (Russia) -- Fiction,Russia -- Fiction,Detective and mystery stories,Psychological fiction","Crime and Punishment","Text","4483","2554","50","https://www.gutenberg.org/ebooks/2554","1821","1881","Dostoyevsky, Fyodor","28","March 28, 2006","3","March","2006","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","7.9","9.79","5.39","14257","6.0","75.2","7.2","8.0","3.1","0.046716302142544165","0.503362543913968","4.77","13.0","0.07","971506","7095","14828","278055.9","203492" +"PA","en","Classical literature;Epic poetry, Greek -- Translations into English;Achilles (Mythological character) -- Poetry;Trojan War -- Poetry","The Iliad","Text","4443","6130","51","https://www.gutenberg.org/ebooks/6130","-750","-650","Homer","1","September 2006","9","September","2006","11","application/x-mobipocket-ebook,application/prs.tei,text/plain; charset=us-ascii,text/html; charset=utf-8,text/plain,application/octet-stream,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/pdf","14.7","12.31","6.17","16082","9.1","72.5","11.600000000000001","5.5","3.1","0.10970939288906147","0.5226854109617926","5.05","24.0","0.04","957200","2876","7692","252473.4","189422" +"B","en","Philosophy, German;Ethics","Beyond Good and Evil","Text","4347","4363","52","https://www.gutenberg.org/ebooks/4363","1844","1900","Nietzsche, Friedrich Wilhelm","1","August, 2003","8","August","2003","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","21.0","13.94","7.92","10092","16.9","35.95","16.0","11.0","11.2","0.11232784809361654","0.5330417084098305","5.28","35.0","0.03","330833","4344","1779","97875.9","62652" +"PQ","en","Satire,Optimism -- Fiction","Candide","Text","4339","19942","53","https://www.gutenberg.org/ebooks/19942","1694","1778","Voltaire","27","November 27, 2006","11","November","2006","8","text/html; charset=iso-8859-1,text/plain,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","11.4","11.02","6.78","4984","8.3","69.11","9.600000000000001","10.5","3.1","0.1460440424213166","0.5073950483530955","4.88","19.0","0.05","174417","972","1815","49873.5","35756" +"TJ","en","Steam-boilers, Water-tube","Steam, Its Generation and Use","Text","4297","22657","54","https://www.gutenberg.org/ebooks/22657","0","0","Babcock & Wilcox Company","18","September 18, 2007","9","September","2007","9","application/x-mobipocket-ebook,text/html,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","14.8","15.14","5.54","8281","8.3","69.11","9.600000000000001","5.5","8.8","0.06752817391808001","0.4375601575874635","5.59","19.0","0.05","760404","8364","6885","189327.6","135920" +"PR","en","Linguistics teachers -- Drama,London (England) -- Drama,Flower vending -- Drama,Social classes -- Drama,Comedies,Speech and social status -- Drama","Pygmalion","Text","4287","3825","55","https://www.gutenberg.org/ebooks/3825","1856","1950","Shaw, Bernard","1","March, 2003","3","March","2003","6","text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","7.5","9.9","6.13","4041","4.4","84.68","6.800000000000001","6.5","3.1","0.07226004796407746","0.5083710206194251","4.84","12.0","0.08","162315","877","2747","45265.5","33552" +"PR","en","English drama -- Early modern and Elizabethan, 1500-1600","The Complete Works of William Shakespeare","Text","4166","100","56","https://www.gutenberg.org/ebooks/100","1564","1616","Shakespeare, William","1","January, 1994","1","January","1994","6","text/html,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","7.9","9.62","5.15","45905","5.2","82.65","7.6000000000000005","52.0","3.1","0.1612295008427009","0.5319494401471125","4.74","14.0","0.07","4183870","10391","62662","1138463.1","882996" +"PR","en","Criminals -- Fiction,Orphans -- Fiction,Bildungsromans,London (England) -- Fiction,Kidnapping victims -- Fiction,Boys -- Fiction","Oliver Twist","Text","4066","730","57","https://www.gutenberg.org/ebooks/730","1812","1870","Dickens, Charles","1","November, 1996","11","November","1996","6","text/html; charset=iso-8859-1,text/plain,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","10.5","10.67","5.85","13659","6.4","79.6","8.8","27.5","3.1","0.08524467195611543","0.4930866916052946","4.87","17.0","0.06","768704","3916","8818","212969.7","157966" +"PR","en","Africa -- Fiction,Psychological fiction,Imperialism -- Fiction,Trading posts -- Fiction,Europeans -- Africa -- Fiction,Degeneration -- fiction","Heart of Darkness","Text","3957","526","58","https://www.gutenberg.org/ebooks/526","1857","1924","Conrad, Joseph","9","January 9, 2006","1","January","2006","6","text/html,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.0","9.8","6.68","5410","7.2","72.16","8.4","13.0","3.1","0.04865516543463206","0.5031388547876838","4.72","16.0","0.06","179060","1128","2309","51667.2","37926" +"PR","en","English literature -- History and criticism","English Literature: Its History and Its Significance for the Life of the English-Speaking World","Text","3933","10609","59","https://www.gutenberg.org/ebooks/10609","1867","1952","Long, William J. (William Joseph)","6","January 6, 2004","1","January","2004","8","text/html; charset=iso-8859-1,text/plain,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","15.0","13.12","6.31","20473","11.1","56.59","11.200000000000001","19.0","8.8","0.161227693729917","0.47428246508787136","5.19","23.0","0.04","1095489","9421","8806","313941.6","210885" +"PS","en","Short stories;United States -- History -- Civil War, 1861-1865 -- Fiction;Prisoners -- Fiction","An Occurrence at Owl Creek Bridge","Text","3850","375","60","https://www.gutenberg.org/ebooks/375","1842","1913","Bierce, Ambrose","19","March 19, 2008","3","March","2008","7","text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","10.8","10.91","7.65","740","7.9","70.13","9.200000000000001","10.5","3.1","0.05319318393470936","0.47741535018653686","4.86","18.0","0.05","18193","102","200","5162.4","3744" +"JC","en","Toleration -- Early works to 1800,Liberty -- Early works to 1800,Political science -- Early works to 1800","Second Treatise of Government","Text","3842","7370","61","https://www.gutenberg.org/ebooks/7370","1632","1704","Locke, John","1","January, 2005","1","January","2005","7","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","27.9","10.98","7.64","4737","22.0","33.59","23.6","7.0","8.8","0.1282687278468411","0.5010064127308006","4.72","54.0","0.02","266846","2015","1043","80451.0","56543" +"BS","en","Bible","The King James Version of the Bible","Text","3776","10","62","https://www.gutenberg.org/ebooks/10","0","0","Unknown","2","March 2, 2011","3","March","2011","7","text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","13.6","9.06","1.74","20764","9.1","77.91","12.8","7.5","3.1","0.11573526589564455","0.5157096435810404","4.49","27.0","0.04","3684178","9815","29667","991401.3","821130" +"HQ","en","Pornography,Sex addicts -- Biography,Erotic literature","My Secret Life, Volumes I. to III.: 1888 Edition","Text","3765","30360","63","https://www.gutenberg.org/ebooks/30360","0","0","Anonymous","1","January 1, 1888","1","January","1888","8","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/html; charset=us-ascii","8.0","7.72","5.41","14622","6.8","78.59","9.200000000000001","8.5","3.1","0.04672881965553007","0.4668574404642869","4.31","18.0","0.05","1124639","3737","14292","328711.5","260851" +"PZ,PS","en","Fantasy,Oz (Imaginary place) -- Fiction","The Wonderful Wizard of Oz","Text","3704","55","64","https://www.gutenberg.org/ebooks/55","1856","1919","Baum, L. Frank (Lyman Frank)","1","July 1, 2008","7","July","2008","7","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","8.7","8.47","5.48","2376","5.6","87.05","9.200000000000001","1.5","3.1","0.1229120952124936","0.517479858012894","4.44","18.0","0.05","175909","205","2152","49077.9","39588" +"JC","en","Liberty","On Liberty","Text","3683","34901","65","https://www.gutenberg.org/ebooks/34901","1806","1873","Mill, John Stuart","10","January 10, 2011","1","January","2011","8","text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","20.5","12.66","7.39","6481","16.2","43.4","16.400000000000002","11.0","11.2","0.1137606823079467","0.48822027532369205","5.06","36.0","0.03","263422","3273","1439","80190.9","52040" +"PR","en","Detective and mystery stories;Holmes, Sherlock (Fictitious character) -- Fiction;Private investigators -- England -- Fiction;Blessing and cursing -- Fiction;Dogs -- Fiction;Dartmoor (England) -- Fiction","The Hound of the Baskervilles","Text","3677","2852","66","https://www.gutenberg.org/ebooks/2852","1859","1930","Doyle, Arthur Conan","1","October, 2001","10","October","2001","6","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","8.0","8.99","5.84","5482","5.6","81.63","8.0","5.5","3.1","0.06625768484988138","0.495383983104905","4.58","15.0","0.06","270731","1301","3768","77996.7","59122" +"PR","en","Male friendship -- Fiction;Thames River (England) -- Fiction;Boats and boating -- England -- Thames River -- Fiction;Dogs -- Fiction;Humorous stories, English;Young men -- Travel -- England -- Thames River -- Fiction","Three Men in a Boat","Text","3647","308","67","https://www.gutenberg.org/ebooks/308","1859","1927","Jerome, Jerome K. (Jerome Klapka)","19","October 19, 2010","10","October","2010","7","text/html,text/plain; charset=utf-8,text/plain; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","10.0","9.34","6.18","6772","7.2","77.57","9.600000000000001","4.0","3.1","0.06767916178700085","0.4749958644650665","4.59","19.0","0.05","306930","1271","3401","86480.1","66828" +"PR,PZ","en","Fantasy","Through the Looking-Glass","Text","3626","12","68","https://www.gutenberg.org/ebooks/12","1832","1898","Carroll, Lewis","1","February, 1991","2","February","1991","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","8.3","9.45","5.84","2700","5.6","81.63","8.0","10.5","3.1","0.08724284395584836","0.486644805436109","4.71","15.0","0.07","137377","373","1938","37274.4","29170" +"PR","en","Science fiction,Dystopias -- Fiction,Time travel -- Fiction","The Time Machine","Text","3599","35","69","https://www.gutenberg.org/ebooks/35","1866","1946","Wells, H. G. (Herbert George)","2","October 2, 2004","10","October","2004","6","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","9.3","9.86","6.54","4316","7.2","72.16","8.4","11.0","3.1","0.05436392619954661","0.46304118056541577","4.73","16.0","0.06","152740","1011","1902","44856.0","32298" +"HT","en","Slaves -- United States -- Biography;Slaves -- Great Britain -- Biography;Equiano, Olaudah, 1745-1797","The Interesting Narrative of the Life of Olaudah Equiano, Or Gustavus Vassa, The African: Written By Himself","Text","3526","15399","70","https://www.gutenberg.org/ebooks/15399","1745","1797","Equiano, Olaudah","17","March 17, 2005","3","March","2005","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","14.8","9.82","6.52","7539","11.1","67.42","13.600000000000001","4.5","3.1","0.13309690461316803","0.48691924409779647","4.57","29.0","0.03","377573","2010","2809","110958.3","82531" +"PS","en","Immigrants -- Fiction,Political fiction,Meat industry and trade -- Fiction,Lithuanian Americans -- Fiction,Chicago (Ill.) -- Fiction,Stockyards -- Fiction,Working class -- Fiction","The Jungle","Text","3522","140","71","https://www.gutenberg.org/ebooks/140","1878","1968","Sinclair, Upton","11","March 11, 2006","3","March","2006","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","12.0","9.7","6.08","12320","8.7","73.51","11.200000000000001","17.5","3.1","0.040068339228926046","0.4644464232121743","4.6","23.0","0.04","686087","2947","6321","196649.1","149118" +"PT","de","Erotic stories, German","Josefine Mutzenbacher: oder Die Geschichte einer Wienerischen Dirne von ihr selbst erzählt","Text","3506","31284","72","https://www.gutenberg.org/ebooks/31284","1869","1945","Salten, Felix","15","February 15, 2010","2","February","2010","9","image/jpeg,text/html; charset=iso-8859-1,text/plain,application/octet-stream,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","9.3","12.22","5.8","6950","4.0","85.69","6.4","10.5","3.1","0.27326448344748866","0.5073059360730594","5.29","11.0","0.09","359174","986","5825","87192.9","67852" +"PS","en","Civil disobedience;Solitude;Thoreau, Henry David, 1817-1862 -- Homes and haunts -- Massachusetts -- Walden Woods;Government, Resistance to;Natural history -- Massachusetts -- Walden Woods;Wilderness areas -- Massachusetts -- Walden Woods;Authors, American -- 19th century -- Biography;Walden Woods (Mass.) -- Social life and customs","Walden, and On The Duty Of Civil Disobedience","Text","3501","205","73","https://www.gutenberg.org/ebooks/205","1817","1862","Thoreau, Henry David","1","January, 1995","1","January","1995","7","application/rdf+xml,text/plain; charset=utf-8,text/html; charset=iso-8859-1,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","14.5","9.93","6.67","12047","11.8","59.98","13.200000000000001","58.0","3.1","0.11396075580986613","0.48933162360383486","4.64","28.0","0.04","536586","3414","4113","157520.7","115646" +"PR","en","England -- Fiction,Political fiction,Education -- Fiction,Utilitarianism -- Fiction,Social problems -- Fiction,Domestic fiction","Hard Times","Text","3494","786","74","https://www.gutenberg.org/ebooks/786","1812","1870","Dickens, Charles","17","March 17, 2013","3","March","2013","6","text/html,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.1","10.03","6.04","10494","6.0","80.62","8.4","8.0","3.1","0.08739687382130339","0.4984569708076884","4.76","16.0","0.06","491593","2587","6369","137771.1","103230" +"PG","en","Brothers -- Fiction,Fathers and sons -- Fiction,Didactic fiction,Russia -- Social life and customs -- 1533-1917 -- Fiction","The Brothers Karamazov","Text","3478","28054","75","https://www.gutenberg.org/ebooks/28054","1821","1881","Dostoyevsky, Fyodor","12","February 12, 2009","2","February","2009","10","text/plain; charset=utf-8,text/plain; charset=us-ascii,text/html; charset=utf-8,application/pdf,application/prs.tei,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","8.1","9.5","5.24","20241","6.4","74.19","7.6000000000000005","2.5","3.1","0.07042299049882597","0.5213109524677764","4.72","14.0","0.07","1651301","9371","23925","474897.6","350214" +"JK","en","United States -- Social conditions,Democracy -- United States,United States -- Politics and government","Democracy in America — Volume 1","Text","3455","815","76","https://www.gutenberg.org/ebooks/815","1805","1859","Tocqueville, Alexis de","21","January 21, 2006","1","January","2006","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","18.7","12.95","6.33","13330","15.8","39.0","14.8","22.0","11.2","0.10755925097210459","0.4520576184782361","5.11","32.0","0.03","974148","13853","5911","297308.7","190451" +"PQ","en","Short stories, French -- Translations into English","Complete Original Short Stories of Guy De Maupassant","Text","3437","3090","77","https://www.gutenberg.org/ebooks/3090","1850","1893","Maupassant, Guy de","2","October 2, 2004","10","October","2004","7","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","9.8","9.86","5.41","28790","6.4","79.6","8.8","11.0","3.1","0.06199086277678568","0.48696359089374347","4.73","17.0","0.06","2322316","10385","27322","659071.8","490717" +"PE","en","English language -- Composition and exercises;English language -- Grammar -- Problems, exercises, etc.","Practical Grammar and Composition","Text","3434","22577","78","https://www.gutenberg.org/ebooks/22577","1883","0","Wood, Thomas","11","September 11, 2007","9","September","2007","7","application/rdf+xml,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,text/plain","8.6","11.53","6.15","7927","5.2","77.23","6.4","11.0","3.1","0.07272736011839737","0.47077537834726185","5.12","11.0","0.08","326211","2252","5396","88321.5","63677" +"PR","en","England -- Social life and customs -- 19th century -- Fiction,Bildungsromans,Orphans -- Fiction,Child labor -- Fiction,Autobiographical fiction,England -- Fiction,Young men -- Fiction,Boys -- Fiction,Stepfathers -- Fiction","David Copperfield","Text","3427","766","79","https://www.gutenberg.org/ebooks/766","1812","1870","Dickens, Charles","1","December, 1996","12","December","1996","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","9.4","9.34","5.49","22731","6.4","79.6","8.8","3.0","3.1","0.11308074909969966","0.5024246743371027","4.64","17.0","0.06","1647137","8232","19863","468659.7","354823" +"E011","en","Lancaster (Mass.) -- History -- Colonial period, ca. 1600-1775;King Philip's War, 1675-1676;Massachusetts -- Biography;Indian captivities -- Massachusetts;Rowlandson, Mary White, approximately 1635-1711","Narrative of the Captivity and Restoration of Mrs. Mary Rowlandson","Text","3389","851","80","https://www.gutenberg.org/ebooks/851","0","1711","Rowlandson, Mary White","1","March, 1997","3","March","1997","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","11.8","8.13","6.2","1694","8.3","79.94","12.0","7.0","3.1","0.06631670834305593","0.4901305831917258","4.33","25.0","0.04","87391","184","786","25089.3","20204" +"PS","en","Plantation life -- Fiction,Slavery -- Fiction,Uncle Tom (Fictitious character) -- Fiction,African Americans -- Fiction,Political fiction,Master and servant -- Fiction,Fugitive slaves -- Fiction,Southern States -- Fiction,Slaves -- Fiction,Didactic fiction","Uncle Tom's Cabin","Text","3336","203","81","https://www.gutenberg.org/ebooks/203","1811","1896","Stowe, Harriet Beecher","1","January, 1995","1","January","1995","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","10.3","10.39","5.96","16310","6.8","78.59","9.200000000000001","14.0","3.1","0.09891227793965336","0.5116378773145582","4.77","18.0","0.05","861422","4298","9784","238465.8","180551" +"BF","en","Characters and characteristics","How to Analyze People on Sight: Through the Science of Human Analysis: The Five Human Types","Text","3334","30601","82","https://www.gutenberg.org/ebooks/30601","0","0","Benedict, Ralph Paine","4","December 4, 2009","12","December","2009","9","image/jpeg,text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","12.5","12.13","6.5","7140","9.9","59.64","10.0","8.5","8.8","0.1371448671445656","0.474026024346619","5.07","20.0","0.05","305692","3102","3014","89637.3","60336" +"PS","en","Ghosts -- Fiction,New York (State) -- History -- 1775-1865 -- Fiction","The Legend of Sleepy Hollow","Text","3287","41","83","https://www.gutenberg.org/ebooks/41","1783","1859","Irving, Washington","1","October, 1992","10","October","1992","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","19.1","11.62","8.36","2311","14.6","52.87","16.0","10.5","8.8","0.1018072872960371","0.4915572668997665","4.88","35.0","0.03","59630","350","348","17145.9","12214" +"PQ","en","Voyages around the world -- Fiction,Adventure stories","Around the World in Eighty Days","Text","3248","103","84","https://www.gutenberg.org/ebooks/103","1828","1905","Verne, Jules","15","May 15, 2008","5","May","2008","6","text/html; charset=iso-8859-1,text/plain,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","11.2","11.71","6.4","7679","7.6","71.14","8.8","57.0","3.1","0.08740576805122494","0.4686212457735507","5.05","17.0","0.06","319415","2235","3591","89117.1","63266" +"PG","en","Russia -- Fiction,Adultery -- Fiction,Married women -- Fiction,Didactic fiction,Love stories","Anna Karenina","Text","3208","1399","85","https://www.gutenberg.org/ebooks/1399","1828","1910","Tolstoy, Leo, graf","1","July 01, 1998","7","July","1998","10","application/rdf+xml,text/html; charset=utf-8,text/plain; charset=us-ascii,application/pdf,text/plain; charset=utf-8,application/zip,text/x-rst,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","9.9","10.38","5.38","19834","7.6","71.14","8.8","13.5","3.1","0.10004575263442515","0.5115122310494378","4.82","17.0","0.06","1687204","10895","20362","477379.8","349769" +"PR","en","Belgians -- England -- Fiction;Private investigators -- England -- Fiction;Detective and mystery stories;Poirot, Hercule (Fictitious character) -- Fiction","The Mysterious Affair at Styles","Text","3192","863","86","https://www.gutenberg.org/ebooks/863","1890","1976","Christie, Agatha","27","July 27, 2008","7","July","2008","7","text/plain; charset=utf-8,text/html; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","7.4","10.13","5.9","6140","5.2","77.23","6.4","2.5","3.1","0.07411903040996154","0.5251063198597463","4.93","11.0","0.09","278825","1576","5058","77225.4","56518" +"PS","en","Pet theft -- Fiction,Animal welfare -- Fiction,Klondike River Valley (Yukon) -- Fiction,Feral dogs -- Fiction,Dogs -- Fiction,Adventure stories,Nature stories,Sled dogs -- Fiction","The Call of the Wild","Text","3141","215","87","https://www.gutenberg.org/ebooks/215","1876","1916","London, Jack","1","July 1, 2008","7","July","2008","6","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","10.3","9.98","6.58","4042","7.2","77.57","9.600000000000001","17.0","3.1","0.04083216632255282","0.46791663658639887","4.7","19.0","0.05","149454","612","1657","41653.8","31821" +"PZ","en","Friendship -- Fiction;Country life -- Prince Edward Island -- Fiction;Orphans -- Fiction;Bildungsromans;Prince Edward Island -- History -- 20th century -- Fiction;Canada -- History -- 1867-1914 -- Fiction;Shirley, Anne (Fictitious character) -- Fiction;Girls -- Fiction;Islands -- Fiction","Anne of Green Gables","Text","3089","45","88","https://www.gutenberg.org/ebooks/45","1874","1942","Montgomery, L. M. (Lucy Maud)","1","1992","1","January","1992","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","7.9","9.1","5.62","8388","5.2","82.65","7.6000000000000005","18.0","3.1","0.10220159941153109","0.5154635664971338","4.65","14.0","0.07","476944","1966","6924","135656.1","102511" +"PR","en","Ship captains -- Fiction,First loves -- Fiction,Regency fiction,Rejection (Psychology) -- Fiction,England -- Social life and customs -- 19th century -- Fiction,Young women -- Fiction,Psychological fiction,Dysfunctional families -- Fiction,Motherless families -- Fiction,Love stories","Persuasion","Text","3079","105","89","https://www.gutenberg.org/ebooks/105","1775","1817","Austen, Jane","5","June 5, 2008","6","June","2008","7","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","12.8","10.62","6.13","7119","9.9","65.05","11.200000000000001","29.5","3.1","0.14846723501433723","0.5223530305658459","4.76","23.0","0.04","396720","2450","3535","114975.0","83284" +"PQ","en","Picaresque literature,Spain -- Social life and customs -- 16th century -- Fiction,Knights and knighthood -- Spain -- Fiction,Romances","Don Quixote","Text","3043","996","90","https://www.gutenberg.org/ebooks/996","1547","1616","Cervantes Saavedra, Miguel de","27","July 27, 2004","7","July","2004","7","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","23.2","9.94","6.75","22548","17.7","50.17","20.400000000000002","25.5","3.1","0.14166755999532418","0.5195606622067284","4.54","46.0","0.02","1935500","7853","9144","563107.5","425899" +"LB","en","Education -- Social aspects,Education -- Philosophy","Democracy and Education: An Introduction to the Philosophy of Education","Text","3023","852","91","https://www.gutenberg.org/ebooks/852","1859","1952","Dewey, John","1","March, 1997","3","March","1997","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","15.3","13.7","6.08","11228","12.3","48.13","11.200000000000001","7.5","11.2","0.10159095894223814","0.4353317066151927","5.29","23.0","0.04","718535","11696","5727","220891.5","135857" +"PR","en","Autobiographical fiction,Artists -- Fiction,Bildungsromans,Dublin (Ireland) -- Fiction,Young men -- Fiction","A Portrait of the Artist as a Young Man","Text","2979","4217","92","https://www.gutenberg.org/ebooks/4217","1882","1941","Joyce, James","1","July, 2003","7","July","2003","7","text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","9.2","9.51","6.12","8799","6.4","79.6","8.8","7.5","3.1","0.03554906410600196","0.4884063071953489","4.67","17.0","0.06","395910","1303","4923","111563.1","84793" +"PR","en","Faust, -approximately 1540 -- Drama;Tragedies;Germany -- Drama;Magicians -- Drama","The Tragical History of Doctor Faustus: From the Quarto of 1604","Text","2963","779","93","https://www.gutenberg.org/ebooks/779","1564","1593","Marlowe, Christopher","1","January, 1997","1","January","1997","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","10.1","11.71","6.82","3039","5.6","81.63","8.0","4.5","3.1","0.14776705553116318","0.4695431073029048","5.1","15.0","0.07","100446","428","1306","26560.8","19693" +"PS","en","New England -- Fiction,Accident victims -- Fiction,Triangles (Interpersonal relations) -- Fiction,Rural poor -- Fiction,Married people -- Fiction,Domestic fiction","Ethan Frome","Text","2951","4517","94","https://www.gutenberg.org/ebooks/4517","1862","1937","Wharton, Edith","1","October, 2003","10","October","2003","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","10.2","9.57","6.32","3826","7.2","77.57","9.600000000000001","13.5","3.1","0.0306267863553043","0.44939740874617345","4.63","19.0","0.05","160545","594","1767","44937.9","34710" +"PR","en","Eve (Biblical figure) -- Poetry,Bible. Genesis -- History of Biblical events -- Poetry,Fall of man -- Poetry,Adam (Biblical figure) -- Poetry","Paradise Lost","Text","2942","20","95","https://www.gutenberg.org/ebooks/20","1608","1674","Milton, John","1","October, 1991","10","October","1991","7","text/html,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","27.0","12.32","8.15","10293","19.3","46.11","22.0","11.0","3.1","0.12722387226707854","0.49999766485443625","4.95","50.0","0.02","395670","910","1590","104795.1","79996" +"PR","en","Vendetta -- Drama,Verona (Italy) -- Drama,Conflict of generations -- Drama,Juliet (Fictitious character) -- Drama,Romeo (Fictitious character) -- Drama,Youth -- Drama","The Tragedy of Romeo and Juliet","Text","2938","1112","96","https://www.gutenberg.org/ebooks/1112","1564","1616","Shakespeare, William","1","November, 1997","11","November","1997","7","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","6.6","8.92","5.94","2809","3.3","93.14","6.800000000000001","7.0","3.1","0.1548142319461203","0.5319646527777393","4.67","12.0","0.08","120950","195","2136","32065.2","25896" +"HX","en","Utopias -- Early works to 1800","Utopia","Text","2933","2130","97","https://www.gutenberg.org/ebooks/2130","1478","1535","More, Thomas, Saint","22","April 22, 2005","4","April","2005","7","text/html,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","27.8","10.35","7.98","4435","22.4","32.57","24.0","11.0","8.8","0.15149196999712472","0.5181731204153892","4.61","55.0","0.02","200527","998","789","59189.4","43482" +"BL","en","Mythology, Classical","Myths and Legends of Ancient Greece and Rome","Text","2924","22381","98","https://www.gutenberg.org/ebooks/22381","0","0","Berens, E. M.","23","August 23, 2007","8","August","2007","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","15.4","13.18","6.62","12067","11.5","55.58","11.600000000000001","7.0","8.8","0.13449462052865618","0.5469891415189978","5.2","24.0","0.04","552373","4536","4303","157635.0","106324" +"PR","en","Erotic stories","Forbidden Fruit: Luscious and exciting story and More forbidden fruit or; Master Percy's progress in and beyond the domestic circle","Text","2905","28520","99","https://www.gutenberg.org/ebooks/28520","0","0","Anonymous","6","April 6, 2009","4","April","2009","6","text/html,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","12.7","9.0","6.35","2999","9.5","71.48","12.0","26.5","3.1","0.09923857269010143","0.5387476048591193","4.48","25.0","0.04","143755","414","1235","41028.3","32090" +"E201","en","United States -- Politics and government -- 1775-1783,Monarchy -- Early works to 1800,Political science -- Early works to 1800","Common Sense","Text","2884","147","100","https://www.gutenberg.org/ebooks/147","1737","1809","Paine, Thomas","9","June 9, 2008","6","June","2008","6","text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","17.0","11.73","7.54","3366","13.8","49.49","14.0","12.0","8.8","0.08690141866407124","0.4516109063840314","4.9","30.0","0.03","107703","906","717","31945.5","21983" +"PR","en","Gentry -- England -- Fiction,Horror tales -- Appreciation -- Fiction,Books and reading -- Fiction,Satire,Gothic fiction (Literary genre),England -- Social life and customs -- 19th century -- Fiction,England -- Fiction,Marriage -- Economic aspects -- Fiction,Young women -- Fiction,Love stories","Northanger Abbey","Text","2871","121","101","https://www.gutenberg.org/ebooks/121","1775","1817","Austen, Jane","1","April, 1994","4","April","1994","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","11.8","10.62","6.2","7437","9.1","67.08","10.4","14.0","3.1","0.1329917032107995","0.5324596012053024","4.81","21.0","0.05","370744","2548","3651","108090.0","77140" +"PS","en","Boston (Mass.) -- History -- Colonial period, ca. 1600-1775 -- Fiction;Revenge -- Fiction;Married women -- Fiction;Adultery -- Fiction;Triangles (Interpersonal relations) -- Fiction;Women immigrants -- Fiction;Illegitimate children -- Fiction;Historical fiction;Psychological fiction;Clergy -- Fiction;Puritans -- Fiction","The Scarlet Letter","Text","2861","33","102","https://www.gutenberg.org/ebooks/33","1804","1864","Hawthorne, Nathaniel","1","February, 1992","2","February","1992","6","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","14.0","12.07","6.69","10146","9.9","65.05","11.200000000000001","8.5","3.1","0.08749191565687943","0.49615507267083653","5.01","23.0","0.04","418571","3224","3537","120357.9","83625" +"HX","en","Socialism,Communism","The Communist Manifesto","Text","2856","61","103","https://www.gutenberg.org/ebooks/61","1820","1895","Engels, Friedrich","25","January 25, 2005","1","January","2005","6","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","17.2","15.44","7.66","2054","13.8","38.66","11.600000000000001","11.0","11.2","0.07784983329792561","0.4060106377896978","5.59","24.0","0.04","64006","970","464","18942.3","11444" +"PS","en","Governesses -- Fiction,England -- Fiction,Children -- Fiction,Ghost stories,Psychological fiction","The Turn of the Screw","Text","2850","209","104","https://www.gutenberg.org/ebooks/209","1843","1916","James, Henry","1","February, 1995","2","February","1995","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","8.8","9.1","6.25","4731","6.4","79.6","8.8","19.0","3.1","0.08200194096170156","0.5136270407633582","4.6","17.0","0.06","194581","1092","2458","55821.6","42259" +"PA","en","Women and peace -- Drama;Aristophanes -- Translations into English;Lysistrata (Fictitious character) -- Drama;Peace movements -- Drama;Greece -- History -- Peloponnesian War, 431-404 B.C. -- Drama;Greek drama (Comedy) -- Translations into English;Comedies","Lysistrata","Text","2849","7700","105","https://www.gutenberg.org/ebooks/7700","-450","-388","Aristophanes","6","April 6, 2008","4","April","2008","6","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","9.4","11.7","7.01","2499","6.0","75.2","7.2","15.0","3.1","0.10793940174579962","0.5199961623408366","5.15","13.0","0.08","74555","526","1108","20212.2","14468" +"E151","en","African Americans","The Souls of Black Folk","Text","2793","408","106","https://www.gutenberg.org/ebooks/408","1868","1963","Du Bois, W. E. B. (William Edward Burghardt)","29","January 29, 2008","1","January","2008","6","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","15.1","12.02","7.01","9265","10.7","63.02","12.0","2.5","8.8","0.06111789126742021","0.4601602615773403","5.0","25.0","0.04","343713","2816","2648","98614.8","68674" +"PQ","en","Domestic fiction,Married women -- Fiction,Middle class -- Fiction,Suicide victims -- Fiction,Physicians' spouses -- Fiction,France -- Fiction,Adultery -- Fiction","Madame Bovary","Text","2744","2413","107","https://www.gutenberg.org/ebooks/2413","1821","1880","Flaubert, Gustave","25","February 25, 2006","2","February","2006","6","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/rdf+xml,application/epub+zip,text/plain","10.5","10.79","6.2","12247","7.9","70.13","9.200000000000001","19.5","3.1","0.06922024030812969","0.4590923260839012","4.84","18.0","0.05","560219","2824","6320","157302.0","115638" +"PQ","en","Philippine fiction (Spanish) -- Translations into English,Nationalists -- Philippines -- Fiction,Philippines -- History -- Fiction","The Reign of Greed","Text","2741","10676","108","https://www.gutenberg.org/ebooks/10676","1861","1896","Rizal, Jose","10","October 10, 2005","10","October","2005","8","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","12.8","11.84","6.55","13647","9.1","67.08","10.4","7.0","3.1","0.0976941390835676","0.4833835467028061","5.02","21.0","0.05","578558","4330","5447","166715.1","115145" +"PT","en","Norwegian drama -- Translations into English,Man-woman relationships -- Drama,Identity (Psychology) -- Drama,Women -- Social conditions -- Drama","Hedda Gabler","Text","2713","4093","109","https://www.gutenberg.org/ebooks/4093","1828","1906","Ibsen, Henrik","1","May, 2003","5","May","2003","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","8.3","11.86","5.91","3451","3.3","87.72","5.6000000000000005","10.5","3.1","0.09366223190931607","0.4941808009278353","5.28","9.0","0.1","157809","629","3074","39351.6","29886" +"PR","en","Detective and mystery stories, English;Holmes, Sherlock (Fictitious character) -- Fiction","The Return of Sherlock Holmes","Text","2669","108","110","https://www.gutenberg.org/ebooks/108","1859","1930","Doyle, Arthur Conan","8","July 8, 2007","7","July","2007","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","7.8","8.98","5.67","9537","5.2","82.65","7.6000000000000005","53.0","3.1","0.07326527162074108","0.4914083094224273","4.63","14.0","0.07","519512","2372","7596","149137.2","112117" +"PR","en","Arthur, King -- Legends;Arthurian romances","Le Morte d'Arthur: Volume 1","Text","2638","1251","111","https://www.gutenberg.org/ebooks/1251","0","1471","Malory, Thomas, Sir","1","March, 1998","3","March","1998","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","13.3","8.48","2.0","6569","9.5","76.9","13.200000000000001","7.5","3.1","0.22456605115114528","0.5164913692682644","4.39","28.0","0.04","740589","1202","6003","208327.5","168802" +"PS","en","Fantasy fiction;American fiction -- 19th century;Horror tales, American;Poe, Edgar Allan, 1809-1849","The Works of Edgar Allan Poe — Volume 1","Text","2613","2147","112","https://www.gutenberg.org/ebooks/2147","1809","1849","Poe, Edgar Allan","19","May 19, 2008","5","May","2008","7","text/html; charset=utf-8,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","13.3","11.67","6.67","11117","10.7","57.61","10.8","19.0","8.8","0.08257139572409698","0.4946267826313452","4.94","22.0","0.04","446218","4307","3952","132003.9","90289" +"PR","en","Don Juan (Legendary character) -- Poetry","Don Juan","Text","2572","21700","113","https://www.gutenberg.org/ebooks/21700","1788","1824","Byron, George Gordon Byron, Baron","6","June 6, 2007","6","June","2007","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","20.2","11.44","7.43","15606","14.2","59.3","16.8","8.5","3.1","0.10905534605205591","0.49283640958751895","4.85","37.0","0.03","610338","2115","3343","164398.5","125740" +"PR","en","War stories,Mars (Planet) -- Fiction,Science fiction,Martians -- Fiction,Space warfare -- Fiction,Life on other planets -- Fiction,Imaginary wars and battles -- Fiction","The War of the Worlds","Text","2546","36","114","https://www.gutenberg.org/ebooks/36","1866","1946","Wells, H. G. (Herbert George)","1","July, 1992","7","July","1992","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","10.8","10.68","6.4","6900","8.3","69.11","9.600000000000001","11.0","3.1","0.016246177983388527","0.4607173822816555","4.82","19.0","0.05","289027","1605","3148","82836.9","59928" +"PR","en","Country homes -- Fiction,Adoptees -- Fiction,Children of the rich -- Fiction,Uncles -- Fiction,Cousins -- Fiction,England -- Fiction,Domestic fiction,Young women -- Fiction,Love stories","Mansfield Park","Text","2537","141","115","https://www.gutenberg.org/ebooks/141","1775","1817","Austen, Jane","1","June, 1994","6","June","1994","8","text/plain,text/html; charset=us-ascii,text/plain; charset=us-ascii,application/pdf,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","11.7","10.1","5.78","11128","9.1","67.08","10.4","18.0","3.1","0.14300907255419276","0.5262603786360919","4.72","21.0","0.05","752380","4733","7336","217970.1","159540" +"PZ,PR","en","Animals -- Fiction;Children's stories, English;Short stories","Just So Stories","Text","2526","2781","116","https://www.gutenberg.org/ebooks/2781","1865","1936","Kipling, Rudyard","1","July 2004","7","July","2004","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.8","9.75","5.93","2558","6.8","78.59","9.200000000000001","53.0","3.1","0.15921675255458467","0.49804876406841136","4.66","18.0","0.05","134002","489","1551","36732.6","28785" +"PR","en","City and town life -- Fiction,Bildungsromans,England -- Fiction,Married people -- Fiction,Domestic fiction,Didactic fiction,Young women -- Fiction,Love stories","Middlemarch","Text","2461","145","117","https://www.gutenberg.org/ebooks/145","1819","1880","Eliot, George","24","May 24, 2008","5","May","2008","8","application/rdf+xml,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,text/plain","11.1","10.73","5.73","23142","8.3","69.11","9.600000000000001","17.0","3.1","0.10609691721052102","0.5217086404065896","4.83","19.0","0.05","1526614","10472","16092","439630.2","316294" +"B","en","Philosophy,Superman (Philosophical concept)","Thus Spake Zarathustra: A Book for All and None","Text","2454","1998","118","https://www.gutenberg.org/ebooks/1998","1844","1900","Nietzsche, Friedrich Wilhelm","1","December, 1999","12","December","1999","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","10.3","11.31","6.29","13085","7.2","72.16","8.4","3.5","3.1","0.14316186167275682","0.5308728224289592","4.98","16.0","0.06","552707","3800","6717","154259.1","110904" +"B","en","Life,Ethics,Stoics","Meditations","Text","2452","2680","119","https://www.gutenberg.org/ebooks/2680","121","180","Marcus Aurelius, Emperor of Rome","1","June, 2001","6","June","2001","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","13.4","10.33","6.39","6921","10.7","63.02","12.0","7.0","3.1","0.13703841545734968","0.5080040609673661","4.71","25.0","0.04","339097","2218","2850","98676.9","72026" +"QH","en","Evolution (Biology),Natural selection","On the Origin of Species By Means of Natural Selection: Or, the Preservation of Favoured Races in the Struggle for Life","Text","2449","1228","120","https://www.gutenberg.org/ebooks/1228","1809","1882","Darwin, Charles","1","March, 1998","3","March","1998","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","18.2","13.41","6.13","9946","15.0","41.03","14.0","4.5","8.8","0.09891696134668664","0.44012115514250405","5.19","30.0","0.03","806411","9557","5130","241299.0","155427" +"PT","en","Legends -- Germany -- Drama;Magicians -- Drama;German poetry -- Translations into English;Faust, -approximately 1540 -- Drama","Faust","Text","2439","14591","121","https://www.gutenberg.org/ebooks/14591","1749","1832","Goethe, Johann Wolfgang von","4","January 4, 2005","1","January","2005","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","10.2","12.58","6.83","5977","6.0","75.2","7.2","5.0","3.1","0.14458337174661146","0.5251604274010934","5.25","13.0","0.07","194148","986","2669","50288.4","36990" +"HB","en","Economics","An Inquiry into the Nature and Causes of the Wealth of Nations","Text","2407","3300","122","https://www.gutenberg.org/ebooks/3300","1723","1790","Smith, Adam","1","April, 2002","4","April","2002","7","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","18.2","12.25","2.17","14143","14.6","47.46","14.8","13.5","8.8","0.13544390923539837","0.464048845307881","4.99","32.0","0.03","1898965","19143","11832","569280.6","380565" +"PZ","en","Rabbits -- Juvenile fiction","The Tale of Peter Rabbit","Text","2371","14838","123","https://www.gutenberg.org/ebooks/14838","1866","1943","Potter, Beatrix","30","January 30, 2005","1","January","2005","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","10.6","12.18","6.66","146","6.8","73.17","8.0","8.0","3.1","0.05392908528809689","0.4250390113762206","5.13","15.0","0.06","5188","39","64","1365.3","1011" +"BJ","en","Etiquette for women;Formulas, recipes, etc.;Etiquette -- United States -- Handbooks, manuals, etc.","The Ladies' Book of Etiquette, and Manual of Politeness: A Complete Hand Book for the Use of the Lady in Polite Society","Text","2351","35123","124","https://www.gutenberg.org/ebooks/35123","0","0","Hartley, Florence","30","January 30, 2011","1","January","2011","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","13.0","11.26","6.44","9295","9.5","66.07","10.8","11.0","3.1","0.11532912839896901","0.5014291887363775","4.87","22.0","0.04","418464","3053","3740","122143.5","85929" +"B","en","Knowledge, Theory of","A Treatise of Human Nature","Text","2345","4705","125","https://www.gutenberg.org/ebooks/4705","1711","1776","Hume, David","1","December, 2003","12","December","2003","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","18.5","12.49","2.33","10580","15.8","39.0","14.8","4.5","8.8","0.09478567635764747","0.4644049921874799","5.03","32.0","0.03","1135584","12026","6935","350307.0","225719" +"PS","en","New England -- Fiction,Sisters -- Fiction,Bildungsromans,Autobiographical fiction,Family life -- New England -- Fiction,Young women -- Fiction,March family (Fictitious characters) -- Fiction,Domestic fiction,Mothers and daughters -- Fiction","Little Women","Text","2340","514","126","https://www.gutenberg.org/ebooks/514","1832","1888","Alcott, Louisa May","1","May, 1996","5","May","1996","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","10.1","9.46","5.67","12841","7.2","77.57","9.600000000000001","27.0","3.1","0.1474168109313772","0.5399897570310996","4.61","19.0","0.05","857711","3379","9517","241852.5","186040" +"B","en","Metaphysics;Knowledge, Theory of;Philosophy -- Introductions","The Problems of Philosophy","Text","2332","5827","127","https://www.gutenberg.org/ebooks/5827","1872","1970","Russell, Bertrand","1","June, 2004","6","June","2004","8","text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","15.7","11.55","6.32","3643","12.6","52.53","12.8","11.0","8.8","0.07787404365669819","0.4593884955648212","4.92","27.0","0.04","210540","2182","1537","63419.4","42752" +"PR","en","Bildungsromans,Illegitimate children -- Fiction,London (England) -- Fiction,Guardian and ward -- Fiction,Legal stories,Inheritance and succession -- Fiction,Domestic fiction,Young women -- Fiction","Bleak House","Text","2330","1023","128","https://www.gutenberg.org/ebooks/1023","1812","1870","Dickens, Charles","1","August 1, 1997","8","August","1997","7","text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","9.1","9.63","5.46","22952","6.0","80.62","8.4","1.0","3.1","0.09988108042692631","0.498810919581587","4.69","16.0","0.06","1659331","8749","20968","470421.9","353471" +"PS","en","Fantasy fiction;American fiction -- 19th century;Horror tales, American;Short stories","The Works of Edgar Allan Poe — Volume 2","Text","2307","2148","129","https://www.gutenberg.org/ebooks/2148","1809","1849","Poe, Edgar Allan","19","May 19, 2008","5","May","2008","7","application/rdf+xml,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,text/plain","13.5","11.84","6.9","12760","11.1","56.59","11.200000000000001","14.0","8.8","0.07792719931242845","0.5032331289518348","4.97","23.0","0.04","472152","4391","4108","139190.4","95020" +"PS","en","Vocabulary -- Humor,English language -- Semantics -- Humor,English language -- Dictionaries -- Humor","The Devil's Dictionary","Text","2287","972","130","https://www.gutenberg.org/ebooks/972","1842","1913","Bierce, Ambrose","1","January 1, 1911","1","January","1911","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","12.1","12.65","7.51","11352","9.1","61.67","9.200000000000001","18.0","3.1","0.11822304908726318","0.488925517373905","5.16","18.0","0.05","310497","3137","3253","88947.0","60117" +"U","en","Military art and science -- Early works to 1800,War -- Early works to 1800","The Art of War","Text","2270","132","131","https://www.gutenberg.org/ebooks/132","0","0","Sunzi, active 6th century B.C.","1","May 1994","5","May","1994","7","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","12.2","11.08","6.62","6632","9.1","67.08","10.4","11.0","3.1","0.08029742809239326","0.49574391074579144","4.89","21.0","0.05","263909","1926","2538","74476.8","53931" +"B","en","Philosophy, German;Causation;Reason;Knowledge, Theory of","The Critique of Pure Reason","Text","2252","4280","132","https://www.gutenberg.org/ebooks/4280","1724","1804","Kant, Immanuel","1","July, 2003","7","July","2003","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","21.2","13.82","6.19","10748","16.9","35.95","16.0","13.0","11.2","0.06396450369004515","0.48896221523111144","5.26","35.0","0.03","1093379","17269","5832","337282.2","208005" +"PR","en","Prostitutes -- Fiction,England -- Fiction,Erotic stories","Memoirs Of Fanny Hill: A New and Genuine Edition from the Original Text (London, 1749)","Text","2210","25305","133","https://www.gutenberg.org/ebooks/25305","1709","1789","Cleland, John","2","May 2, 2008","5","May","2008","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","26.5","10.75","7.75","8502","20.8","36.63","22.400000000000002","14.0","8.8","0.13352193907269483","0.5170861938370543","4.68","51.0","0.02","396142","2561","1635","115991.1","84602" +"NC","en","Drawing","The Practice and Science of Drawing","Text","2209","14264","134","https://www.gutenberg.org/ebooks/14264","1873","0","Speed, Harold","6","December 6, 2004","12","December","2004","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","14.4","11.32","6.14","6105","10.7","63.02","12.0","11.0","8.8","0.1349879607045014","0.4947034199933793","4.88","25.0","0.04","373627","3125","2968","110839.5","76540" +"PR","en","Private investigators -- England -- Fiction;Detective and mystery stories;Holmes, Sherlock (Fictitious character) -- Fiction","The Sign of the Four","Text","2200","2097","135","https://www.gutenberg.org/ebooks/2097","1859","1930","Doyle, Arthur Conan","1","March, 2000","3","March","2000","7","text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","7.6","8.69","6.16","4979","5.2","82.65","7.6000000000000005","14.0","3.1","0.05915935182624819","0.4816925374541576","4.58","14.0","0.07","196825","869","2868","56484.9","43012" +"PA","en","Epic poetry, Greek -- Translations into English;Odysseus (Greek mythology);Homer -- Translations into English","The Odyssey: Rendered into English prose for the use of those who cannot read the original","Text","2199","1727","136","https://www.gutenberg.org/ebooks/1727","-750","-650","Homer","1","April, 1999","4","April","1999","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","14.1","8.89","6.03","7838","11.1","67.42","13.600000000000001","17.5","3.1","0.13093947054176486","0.49696217468111475","4.41","29.0","0.03","570379","1835","4386","164098.8","129408" +"PS","en","Princesses -- Fiction;Dejah Thoris (Fictitious character) -- Fiction;Carter, John (Fictitious character) -- Fiction;Mars (Planet) -- Fiction;Science fiction","A Princess of Mars","Text","2190","62","137","https://www.gutenberg.org/ebooks/62","1875","1950","Burroughs, Edgar Rice","23","June 23, 2008","6","June","2008","7","text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","15.1","10.51","6.51","6342","11.8","59.98","13.200000000000001","18.0","3.1","0.07796436439011051","0.49648401625994754","4.69","28.0","0.03","316458","1696","2333","92512.8","67407" +"GR","en","Tales -- China;Legends -- China;Mythology, Chinese","Myths and Legends of China","Text","2187","15250","138","https://www.gutenberg.org/ebooks/15250","1864","1954","Werner, E. T. C. (Edward Theodore Chalmers)","4","March 4, 2005","3","March","2005","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","13.0","11.55","6.41","12623","9.5","66.07","10.8","14.0","3.1","0.09975725992609417","0.4372038528463008","4.92","22.0","0.04","584463","4019","5293","166521.6","118826" +"PQ","en","France -- History -- Louis XIII, 1610-1643 -- Fiction;Adventure and adventurers -- Fiction;Swordsmen -- Fiction;Historical fiction","The Three Musketeers","Text","2162","1257","139","https://www.gutenberg.org/ebooks/1257","1802","1870","Dumas, Alexandre","1","March 01, 1998","3","March","1998","8","text/plain; charset=utf-8,text/plain; charset=us-ascii,text/html; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","9.9","10.79","5.52","15805","7.2","72.16","8.4","17.0","3.1","0.1025973212465513","0.5061792930204096","4.89","16.0","0.06","1120021","5121","13786","314599.5","229258" +"PS","en","Science fiction,Short stories","2 B R 0 2 B","Text","2144","21279","140","https://www.gutenberg.org/ebooks/21279","1922","2007","Vonnegut, Kurt","3","May 3, 2007","5","May","2007","6","text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","7.3","10.3","6.93","454","3.7","86.71","6.0","2.5","3.1","0.21205875600929072","0.4959627790510145","5.01","10.0","0.1","12848","59","249","3446.1","2564" +"PT","en","Unrequited love -- Fiction,Young men -- Germany -- Fiction,Germany -- Social life and customs -- Fiction","The Sorrows of Young Werther","Text","2130","2527","141","https://www.gutenberg.org/ebooks/2527","1749","1832","Goethe, Johann Wolfgang von","1","February, 2001","2","February","2001","6","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","10.4","10.1","6.54","5264","8.3","69.11","9.600000000000001","10.5","3.1","0.11397710656759845","0.5246238896056035","4.72","19.0","0.05","200590","1087","2218","58281.3","42490" +"PR","en","Country homes -- Fiction,Psychological fiction,Art teachers -- Fiction,Nobility -- Fiction,Deception -- Fiction,Gothic fiction (Literary genre),England -- Fiction,Psychiatric hospital patients -- Fiction,Inheritance and succession -- Fiction,Love stories","The Woman in White","Text","2127","583","142","https://www.gutenberg.org/ebooks/583","1824","1889","Collins, Wilkie","1","July, 1996","7","July","1996","7","text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","9.9","9.8","5.53","15514","7.9","70.13","9.200000000000001","9.0","3.1","0.06320621633532139","0.4936742786869371","4.72","18.0","0.06","1155740","7097","13486","336146.4","244709" +"PG","en","Political fiction,Russia -- Officials and employees -- Fiction,Russia -- History -- 1801-1917 -- Fiction","Notes from the Underground","Text","2125","600","143","https://www.gutenberg.org/ebooks/600","1821","1881","Dostoyevsky, Fyodor","1","July, 1996","7","July","1996","6","text/html; charset=iso-8859-1,text/plain,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","9.2","9.28","6.28","5025","7.6","71.14","8.8","11.0","3.1","0.07162614804534533","0.5395232313722474","4.63","17.0","0.06","203528","1336","2480","60156.0","43966" +"PA","en","Latin language -- Grammar -- Problems, exercises, etc.","Latin for Beginners","Text","2116","18251","144","https://www.gutenberg.org/ebooks/18251","1860","1940","D'Ooge, Benjamin L. (Benjamin Leonard)","25","April 25, 2006","4","April","2006","10","text/html,text/plain; charset=utf-8,text/plain; charset=us-ascii,text/plain,text/html; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","12.3","16.22","7.17","19541","7.6","60.31","6.4","8.5","3.1","0.08592232578156872","0.4670817205027396","5.98","11.0","0.09","617437","5242","9248","161719.2","103202" +"PR","en","Private investigators -- England -- Fiction;Detective and mystery stories, English;Holmes, Sherlock (Fictitious character) -- Fiction","The Memoirs of Sherlock Holmes","Text","2115","834","145","https://www.gutenberg.org/ebooks/834","1859","1930","Doyle, Arthur Conan","1","March, 1997","3","March","1997","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","8.5","9.1","5.86","7949","6.0","80.62","8.4","7.5","3.1","0.06201643898520983","0.4823579329735425","4.6","16.0","0.06","403005","1834","5311","115796.7","87586" +"DG","en","Rome -- History -- Empire, 30 B.C.-476 A.D.;Byzantine Empire -- History -- To 527;Indexes","The History Of The Decline And Fall Of The Roman Empire: Table of Contents with links in the HTML file to the two; Project Gutenberg editions (12 volumes)","Text","2105","25717","146","https://www.gutenberg.org/ebooks/25717","1737","1794","Gibbon, Edward","7","June 7, 2008","6","June","2008","9","application/rdf+xml,image/jpeg,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,text/plain","11.4","15.74","5.73","1026","6.4","63.36","5.2","9.0","3.1","0.08406771799628945","0.2545902092894577","6.05","8.0","0.12","57743","906","1098","15119.1","9538" +"PT","en","Social problems -- Fiction","The Trial","Text","2099","7849","147","https://www.gutenberg.org/ebooks/7849","1883","1924","Kafka, Franz","1","April, 2005","4","April","2005","10","text/html,text/plain; charset=us-ascii,text/rtf,text/plain,application/octet-stream,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","9.1","8.94","5.49","5132","6.8","78.59","9.200000000000001","4.5","3.1","0.055229266442657333","0.49242972733871276","4.52","18.0","0.05","379078","1837","4552","108990.9","83946" +"PR","en","Hamlet (Legendary character) -- Drama,Tragedies,Murder victims' families -- Drama,Princes -- Drama,Denmark -- Drama,Fathers -- Death -- Drama,Revenge -- Drama,Kings and rulers -- Succession -- Drama","Hamlet, Prince of Denmark","Text","2092","1524","148","https://www.gutenberg.org/ebooks/1524","1564","1616","Shakespeare, William","1","January 1, 1603","1","January","1603","6","text/html,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.4","10.61","6.4","4049","5.6","81.63","8.0","2.5","3.1","0.14968219265275548","0.5373529448984683","4.86","15.0","0.06","153985","355","1999","39654.9","31677" +"PE","en","English language -- Middle English, 1100-1500 -- Dictionaries","A Concise Dictionary of Middle English from A.D. 1150 to 1580","Text","2069","10625","149","https://www.gutenberg.org/ebooks/10625","1835","1912","Skeat, Walter W. (Walter William)","7","January 7, 2004","1","January","2004","7","text/plain; charset=utf-8,text/html; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","12.5","17.13","7.66","38626","0.5","105.66","5.2","8.0","3.1","0.012648869657036167","0.4812178879586168","6.29","8.0","0.12","1059372","3136","19457","184911.3","168326" +"","en","","Journal of Small Things","Text","2046","51245","150","https://www.gutenberg.org/ebooks/51245","1876","1961","Mackay, Helen","18","February 18, 2016","2","February","2016","7","image/jpeg,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","7.8","8.52","5.59","4310","6.0","80.62","8.4","18.5","3.1","0.039612960070634674","0.48073930849241087","4.5","16.0","0.06","263162","530","3632","73294.2","58530" +"PZ,PR","en","Country life -- Fiction,Humorous stories,Pastoral fiction,England -- Fiction,Fantasy fiction,Animals -- Fiction,Friendship -- Fiction,River life -- Fiction","The Wind in the Willows","Text","2019","289","151","https://www.gutenberg.org/ebooks/289","1859","1932","Grahame, Kenneth","1","July, 1995","7","July","1995","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","10.6","10.27","6.44","6882","7.2","77.57","9.600000000000001","2.5","3.1","0.08163899351171122","0.49872714509169946","4.75","19.0","0.05","277439","1185","3035","77015.7","58401" +"PR","en","Pastoral fiction,Wessex (England) -- Fiction,Children of clergy -- Fiction,Children of the rich -- Fiction,Triangles (Interpersonal relations) -- Fiction,Poor families -- Fiction,Women household employees -- Fiction,Man-woman relationships -- Fiction,Women murderers -- Fiction,Rape victims -- Fiction,Didactic fiction","Tess of the d'Urbervilles: A Pure Woman","Text","2014","110","152","https://www.gutenberg.org/ebooks/110","1840","1928","Hardy, Thomas","1","February, 1994","2","February","1994","8","text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","10.9","10.68","6.17","14997","8.3","69.11","9.600000000000001","26.0","3.1","0.06836649990827988","0.4748895078441672","4.82","19.0","0.05","715944","4209","7676","201971.7","148537" +"PR","en","Scotland -- Kings and rulers -- Drama;Tragedies;Macbeth, King of Scotland, active 11th century -- Drama;Regicides -- Drama","Macbeth","Text","2012","2264","153","https://www.gutenberg.org/ebooks/2264","1564","1616","Shakespeare, William","1","January 1, 1623","1","January","1623","7","text/html,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.9","10.84","6.68","2620","6.0","80.62","8.4","13.5","3.1","0.14628671015465597","0.519673238787798","4.9","16.0","0.06","90199","132","1117","23691.6","18412" +"PE","en","Report writing,English language -- Style,English language -- Rhetoric","The Elements of Style","Text","2000","37134","154","https://www.gutenberg.org/ebooks/37134","1869","1946","Strunk, William","19","August 19, 2011","8","August","2011","9","image/jpeg,text/html; charset=utf-8,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","11.9","13.05","7.35","2567","8.4","63.7","8.4","6.0","3.1","0.08680284837742207","0.43255171554035177","5.28","16.0","0.06","73214","698","820","21087.9","13871" +"PR","en","London (England) -- Drama,Comedies","An Ideal Husband","Text","1980","885","155","https://www.gutenberg.org/ebooks/885","1854","1900","Wilde, Oscar","27","March 27, 2009","3","March","2009","7","text/html,text/plain; charset=utf-8,text/plain; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","6.3","9.36","5.64","3042","3.3","87.72","5.6000000000000005","5.5","3.1","0.09129321773780148","0.5298345766259349","4.9","9.0","0.11","151199","612","3310","41577.3","30887" +"PQ","es","Picaresque literature,Spain -- Social life and customs -- 16th century -- Fiction,Knights and knighthood -- Spain -- Fiction,Romances","Don Quijote","Text","1975","2000","156","https://www.gutenberg.org/ebooks/2000","1547","1616","Cervantes Saavedra, Miguel de","1","December, 1999","12","December","1999","7","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","20.9","10.75","7.07","34979","18.9","30.88","18.0","28.0","11.2","0.004399545859744715","0.5446898944477654","4.68","40.0","0.02","1782519","20363","9404","600512.4","381225" +"PS","en","Edward VI, King of England, 1537-1553 -- Fiction;Princes -- Fiction;Social classes -- Fiction;Poor children -- Fiction;London (England) -- Fiction;Impostors and imposture -- Fiction;Historical fiction;Lookalikes -- Fiction;Boys -- Fiction","The Prince and the Pauper","Text","1955","1837","157","https://www.gutenberg.org/ebooks/1837","1835","1910","Twain, Mark","20","August 20, 2006","8","August","2006","8","image/jpeg,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","12.0","10.91","6.69","8932","7.9","75.54","10.4","17.0","3.1","0.08902463709683353","0.5050723719566816","4.86","21.0","0.05","340217","1540","3315","93936.6","69972" +"PR","en","Children of clergy -- Fiction;Bildungsromans;Social classes -- Fiction;Didactic fiction;Young women -- Fiction;England, Northern -- Fiction;Mothers and daughters -- Fiction","North and South","Text","1948","4276","158","https://www.gutenberg.org/ebooks/4276","1810","1865","Gaskell, Elizabeth Cleghorn","12","June 12, 2012","6","June","2012","7","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","9.2","9.51","5.71","14113","6.4","79.6","8.8","19.5","3.1","0.08456673554903724","0.52295691874082","4.67","17.0","0.06","847167","3651","10509","239356.8","181508" +"PR","en","Pilgrims and pilgrimages -- Europe -- Poetry,Voyages and travels -- Poetry,English poetry","Childe Harold's Pilgrimage","Text","1947","5131","159","https://www.gutenberg.org/ebooks/5131","1788","1824","Byron, George Gordon Byron, Baron","1","February, 2004","2","February","2004","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","17.9","12.31","7.58","5702","11.8","65.39","14.4","25.5","3.1","0.11135453064288713","0.5122775117698445","5.0","31.0","0.03","187170","448","1189","48936.6","37406" +"PR","en","Melancholy -- Early works to 1800","The Anatomy of Melancholy","Text","1939","10800","160","https://www.gutenberg.org/ebooks/10800","1577","1640","Burton, Robert","13","January 13, 2004","1","January","2004","9","text/html,text/html; charset=iso-8859-1,text/plain,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","16.2","13.76","7.01","73779","11.9","54.56","12.0","12.0","8.8","0.12455067298478117","0.5382994787170491","5.3","25.0","0.04","2889437","25910","21457","812164.5","545013" +"ND","en","Leonardo, da Vinci, 1452-1519 -- Notebooks, sketchbooks, etc.","The Notebooks of Leonardo Da Vinci — Complete","Text","1927","5000","161","https://www.gutenberg.org/ebooks/5000","1452","1519","Leonardo, da Vinci","1","January, 2004","1","January","2004","6","text/html,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","12.7","10.62","6.03","19756","8.7","73.51","11.200000000000001","14.0","3.1","0.09809955952919824","0.43838408049982786","4.76","23.0","0.04","1187359","6987","10603","334213.2","249345" +"PZ","en","Fairy tales -- Denmark;Fairy tales;Children's stories, Danish -- Translations into English","Andersen's Fairy Tales","Text","1924","1597","162","https://www.gutenberg.org/ebooks/1597","1805","1875","Andersen, H. C. (Hans Christian)","1","January, 1999","1","January","1999","6","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","9.7","9.28","6.11","5383","7.2","77.57","9.600000000000001","26.0","3.1","0.12041990630933559","0.5024558298999244","4.58","19.0","0.05","253942","863","2889","71139.6","55394" +"","en","","Great Disasters and Horrors in the World's History","Text","1904","51246","163","https://www.gutenberg.org/ebooks/51246","1864","1948","Godbey, Allen Howard","18","February 18, 2016","2","February","2016","6","image/jpeg,text/html; charset=utf-8,text/plain; charset=utf-8,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","12.8","11.84","6.33","15233","9.1","67.08","10.4","13.5","3.1","0.06490356258815431","0.4742080997566672","5.02","21.0","0.05","730982","4902","6905","210030.3","145545" +"PS","en","American drama","Plays","Text","1897","10623","164","https://www.gutenberg.org/ebooks/10623","1876","1948","Glaspell, Susan","7","January 7, 2004","1","January","2004","7","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","7.0","9.96","5.7","5678","3.7","86.71","6.0","14.0","3.1","0.007323418325545181","0.5582377801030164","4.9","10.0","0.09","280155","1358","5295","75384.0","57186" +"","en","","Dead End","Text","1896","51247","165","https://www.gutenberg.org/ebooks/51247","1918","1999","Macfarlane, Wallace","18","February 18, 2016","2","February","2016","8","application/x-mobipocket-ebook,image/jpeg,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","9.5","11.76","7.39","798","6.0","75.2","7.2","6.0","3.1","0.09057882141332839","0.47233314103736607","5.16","13.0","0.08","20878","143","306","5811.3","4048" +"QA","la","Celestial mechanics -- Early works to 1800,Mechanics -- Early works to 1800","Philosophiae Naturalis Principia Mathematica","Text","1895","28233","166","https://www.gutenberg.org/ebooks/28233","1642","1727","Newton, Isaac, Sir","2","March 2, 2009","3","March","2009","9","application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/pdf,application/prs.tex,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","17.3","16.83","6.68","14867","14.2","32.22","10.8","7.5","11.2","0.114673812603955","0.3745364381198783","5.83","22.0","0.04","701744","15148","5352","211159.8","120406" +"BR","en","Catholic Church -- Bishops -- Biography;Bishops -- Algeria -- Hippo (Extinct city) -- Biography;Augustine, Saint, Bishop of Hippo;Christian saints -- Algeria -- Hippo (Extinct city) -- Biography","The Confessions of St. Augustine","Text","1890","3296","167","https://www.gutenberg.org/ebooks/3296","354","430","Augustine, Saint, Bishop of Hippo","1","June, 2002","6","June","2002","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","15.3","9.7","6.39","8939","11.5","66.41","14.0","13.0","3.1","0.16772999198256466","0.5239941687704005","4.55","30.0","0.03","509067","2119","3663","146779.2","111824" +"PQ","en","Autobiographical fiction,Villages -- France -- Fiction,France -- Social life and customs -- 19th century -- Fiction","Swann's Way","Text","1877","7178","168","https://www.gutenberg.org/ebooks/7178","1871","1922","Proust, Marcel","21","March 21, 2009","3","March","2009","6","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","19.5","10.75","6.77","16104","15.4","50.84","16.8","13.0","8.8","0.09773590586803396","0.5107603697500214","4.73","37.0","0.03","922547","5922","5235","270441.9","195216" +"E300","en","Slaves -- United States -- Biography;Plantation life -- Louisiana -- History -- 19th century;Northup, Solomon, 1808-1863?;Slaves' writings, American;African Americans -- Biography;Slavery -- Louisiana -- History -- 19th century","Twelve Years a Slave: Narrative of Solomon Northup, a Citizen of New-York, Kidnapped in Washington City in 1841, and Rescued in 1853, from a Cotton Plantation near the Red River in Louisiana","Text","1868","45631","169","https://www.gutenberg.org/ebooks/45631","1808","0","Northup, Solomon","11","May 11, 2014","5","May","2014","9","image/jpeg,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","12.3","11.37","6.51","9775","8.7","68.1","10.0","5.0","3.1","0.07398433220491253","0.47994540074383263","4.94","20.0","0.05","405024","2913","3931","116656.2","81946" +"PG","en","Russia -- Social life and customs -- Drama;Authors, Russian -- 19th century -- Drama;Russian drama -- Translations into English;Man-woman relationships -- Drama","The Sea-Gull","Text","1856","1754","170","https://www.gutenberg.org/ebooks/1754","1860","1904","Chekhov, Anton Pavlovich","21","February 21, 2006","2","February","2006","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","6.4","8.69","6.04","2169","4.4","84.68","6.800000000000001","13.0","3.1","0.095969144143421","0.5173707433029797","4.63","12.0","0.08","87650","446","1575","25110.0","18923" +"","en","","Spacemen Die at Home","Text","1846","51249","171","https://www.gutenberg.org/ebooks/51249","1920","1990","Ludwig, Edward W.","18","February 18, 2016","2","February","2016","8","text/plain,image/jpeg,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","6.4","8.62","6.51","707","4.0","85.69","6.4","4.0","3.1","0.09520774278993455","0.48800513945719426","4.67","11.0","0.09","22449","67","413","6167.7","4803" +"PR","en","Beresford, Tommy (Fictitious character) -- Fiction;Detective and mystery stories;Private investigators -- England -- Fiction;Beresford, Tuppence (Fictitious character) -- Fiction;Missing persons -- Fiction;Married people -- Fiction;Domestic fiction","The Secret Adversary","Text","1825","1155","172","https://www.gutenberg.org/ebooks/1155","1890","1976","Christie, Agatha","14","September 14, 2008","9","September","2008","6","text/plain; charset=utf-8,text/html; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","6.7","9.72","5.75","7723","4.8","78.25","6.0","3.5","3.1","0.06912464247463623","0.4909403713550411","4.91","10.0","0.1","369756","1876","7467","101785.5","75285" +"NA,PA","en","Architecture -- Early works to 1800","The Ten Books on Architecture","Text","1823","20239","173","https://www.gutenberg.org/ebooks/20239","0","0","Vitruvius Pollio","31","December 31, 2006","12","December","2006","9","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","14.5","11.38","6.33","9288","10.7","63.02","12.0","15.5","3.1","0.0827434781542821","0.40140000728447495","4.89","25.0","0.04","492780","3302","3909","139015.8","100866" +"PQ","en","Epic poetry, Italian -- Translations into English;Italian poetry -- To 1400 -- Translations into English;Hell -- Poetry","The vision of hell.: By Dante Alighieri.; Translated by Rev. Henry Francis Cary, M.A.; and illustrated with the seventy-five designs of Gustave Doré.","Text","1822","8789","174","https://www.gutenberg.org/ebooks/8789","1265","1321","Dante Alighieri","7","August 7, 2004","8","August","2004","7","image/jpeg,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","12.7","10.97","6.87","4953","8.3","74.53","10.8","13.0","3.1","0.03585212206790738","0.4925737400321064","4.82","22.0","0.04","176090","278","1599","46282.5","36498" +"PQ","tl","Philippines -- History -- 1812-1898 -- Fiction,Historical fiction","Noli Me Tangere","Text","1819","20228","175","https://www.gutenberg.org/ebooks/20228","1861","1896","Rizal, Jose","30","December 30, 2006","12","December","2006","7","image/jpeg,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","16.4","16.88","7.32","29751","11.1","51.18","10.0","10.5","11.2","-0.15398419091366541","0.471951121794872","5.89","20.0","0.05","1030259","19725","8626","282948.3","174826" +"DS","en","Communism -- Soviet Union,Mongolia -- Description and travel","Beasts, Men and Gods","Text","1801","2067","176","https://www.gutenberg.org/ebooks/2067","1878","1945","Ossendowski, Ferdynand Antoni","13","May 13, 2006","5","May","2006","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","11.1","10.73","6.13","7958","8.3","69.11","9.600000000000001","19.5","3.1","0.06493827159073796","0.4378957725531045","4.83","19.0","0.05","391573","2267","4162","113910.3","81057" +"PR","en","Inheritance and succession -- Fiction,Gothic fiction (Literary genre),Horror tales","The Castle of Otranto","Text","1797","696","177","https://www.gutenberg.org/ebooks/696","1717","1797","Walpole, Horace","5","May 5, 2012","5","May","2012","5","text/plain; charset=utf-8,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook,text/html","10.8","11.13","6.6","4912","7.6","71.14","8.8","8.0","3.1","0.09420797946324658","0.5244182064866908","4.95","17.0","0.06","181332","1241","2052","51256.8","36600" +"PR","en","English poetry -- 18th century","Lyrical Ballads, With a Few Other Poems (1798)","Text","1793","9622","178","https://www.gutenberg.org/ebooks/9622","1770","1850","Wordsworth, William","1","January, 2006","1","January","2006","8","application/rdf+xml,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,text/plain","12.0","10.16","6.54","2467","7.2","82.98","10.8","8.5","3.1","0.08144759408198557","0.502518012902231","4.68","22.0","0.04","100332","164","944","26404.2","21451" +"PR","en","Country homes -- Fiction,Jewelry theft -- Fiction,Police -- England -- Fiction,England -- Fiction,East Indians -- England -- Fiction,Mystery fiction","The Moonstone","Text","1770","155","179","https://www.gutenberg.org/ebooks/155","1824","1889","Collins, Wilkie","12","January 12, 2006","1","January","2006","6","text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","8.6","9.74","5.46","13369","6.8","73.17","8.0","11.0","3.1","0.07974315271470545","0.4823653315658476","4.71","15.0","0.06","916844","5228","12428","263012.4","194758" +"PS","en","Gothic fiction (Literary genre),Short stories,Horror tales","The Fall of the House of Usher","Text","1739","932","180","https://www.gutenberg.org/ebooks/932","1809","1849","Poe, Edgar Allan","1","June, 1997","6","June","1997","7","text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","17.4","12.83","8.73","1634","13.4","50.5","13.600000000000001","18.0","8.8","0.038482829393291056","0.5227199016550099","5.09","29.0","0.03","35955","358","237","10618.2","7064" +"PS","en","Upper class -- Fiction,Separated people -- Fiction,Triangles (Interpersonal relations) -- Fiction,Married people -- Fiction,New York (N.Y.) -- Fiction,Domestic fiction,Love stories","The Age of Innocence","Text","1737","541","181","https://www.gutenberg.org/ebooks/541","1862","1937","Wharton, Edith","1","May, 1996","5","May","1996","6","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","11.3","11.2","6.35","11389","8.3","69.11","9.600000000000001","13.5","3.1","0.06933607569964957","0.47493391125564133","4.91","19.0","0.05","497605","3221","5271","140980.5","101308" +"PA","en","Legends -- Rome -- Poetry;Aeneas (Legendary character) -- Poetry;Epic poetry, Latin -- Translations into English","The Aeneid","Text","1723","228","182","https://www.gutenberg.org/ebooks/228","-70","-19","Virgil","10","March 10, 2008","3","March","2008","7","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","14.3","11.78","6.16","9012","9.1","72.5","11.600000000000001","17.0","3.1","0.06606333784291592","0.5002243074529552","4.96","24.0","0.04","528282","443","4293","135104.4","106461" +"PR","en","Wishes -- Fiction,Horror tales","The Monkey's Paw: The Lady of the Barge and Others, Part 2.","Text","1692","12122","183","https://www.gutenberg.org/ebooks/12122","1863","1943","Jacobs, W. W. (William Wymark)","22","April 22, 2004","4","April","2004","7","image/jpeg,text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","7.8","9.85","6.85","643","4.8","83.66","7.2","7.5","3.1","-0.004097215120837167","0.41643838080845985","4.78","13.0","0.07","18896","77","296","5079.6","3953" +"PZ,PR","en","Fantasy","Alice's Adventures in Wonderland","Text","1660","19033","184","https://www.gutenberg.org/ebooks/19033","1832","1898","Carroll, Lewis","12","August 12, 2006","8","August","2006","9","application/rdf+xml,image/jpeg,text/html; charset=iso-8859-1,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","8.7","9.45","6.14","1052","6.0","80.62","8.4","14.5","3.1","0.030640044124964197","0.47015203304447434","4.66","16.0","0.06","45325","139","592","12559.5","9721" +"PZ,PS","en","People with disabilities -- Fiction,Gardens -- Fiction,Orphans -- Fiction,Yorkshire (England) -- Fiction","The Secret Garden","Text","1621","113","185","https://www.gutenberg.org/ebooks/113","1849","1924","Burnett, Frances Hodgson","15","May 15, 2008","5","May","2008","6","text/html; charset=iso-8859-1,text/plain,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","7.0","8.34","5.33","5087","5.2","82.65","7.6000000000000005","17.0","3.1","0.08636277851696303","0.501351816094606","4.52","14.0","0.07","364915","877","5669","100968.3","80712" +"DF","en","Greece -- History -- Peloponnesian War, 431-404 B.C.","The History of the Peloponnesian War","Text","1605","7142","186","https://www.gutenberg.org/ebooks/7142","-460","-395","Thucydides","1","December, 2004","12","December","2004","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","21.9","12.2","6.61","12844","17.7","39.34","18.0","63.0","8.8","0.10852604049405788","0.46109339534316296","4.93","40.0","0.02","1010983","8137","5089","298561.5","205021" +"PS","en","Britons -- Fiction,Time travel -- Fiction,Fantasy fiction,Satire,Kings and rulers -- Fiction,Arthurian romances -- Adaptations,Americans -- Great Britain -- Fiction,Knights and knighthood -- Fiction","A Connecticut Yankee in King Arthur's Court","Text","1605","86","187","https://www.gutenberg.org/ebooks/86","1835","1910","Twain, Mark","20","July 20, 2006","7","July","2006","8","image/jpeg,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","10.8","9.57","6.23","11887","7.6","76.56","10.0","18.5","3.1","0.10211814154391177","0.504403045209017","4.63","20.0","0.05","543973","2768","5645","155107.8","117534" +"","en","Packing-house products,Animal industry -- United States","The Livestock Producer and Armour","Text","1601","51244","188","https://www.gutenberg.org/ebooks/51244","0","0","Unknown","18","February 18, 2016","2","February","2016","6","image/jpeg,text/html; charset=utf-8,text/plain; charset=utf-8,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","16.3","14.1","7.94","1233","13.0","46.1","12.0","4.0","8.8","0.12573176633756833","0.45013978105701674","5.36","25.0","0.04","34052","350","254","9873.0","6350" +"PR","en","Vampires -- Fiction,Young women -- Fiction","Carmilla","Text","1583","10007","189","https://www.gutenberg.org/ebooks/10007","1814","1873","Le Fanu, Joseph Sheridan","7","November 7, 2003","11","November","2003","8","text/html; charset=iso-8859-1,text/plain,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","11.0","10.27","6.76","3776","8.7","68.1","10.0","14.5","3.1","0.08910934668657577","0.5148756506527203","4.75","20.0","0.05","133260","781","1393","38634.3","28033" +"PS","en","Diary fiction,Humorous stories,Eve (Biblical figure) -- Fiction,Bible. Genesis -- History of Biblical events -- Fiction","Eve's Diary, Complete","Text","1553","8525","190","https://www.gutenberg.org/ebooks/8525","1835","1910","Twain, Mark","14","June 14, 2004","6","June","2004","8","image/jpeg,text/html; charset=iso-8859-1,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","8.4","7.2","6.42","792","7.2","77.57","9.600000000000001","5.5","3.1","0.18946600048642648","0.5297351086736568","4.22","19.0","0.05","28589","131","340","8496.0","6780" +"B","en","Ethics","Ethics","Text","1552","3800","191","https://www.gutenberg.org/ebooks/3800","1632","1677","Spinoza, Benedictus de","1","February, 2003","2","February","2003","8","text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","14.3","11.38","5.71","4652","11.9","54.56","12.0","11.0","3.1","0.10059054879135672","0.5107495225890184","4.89","25.0","0.04","430451","3436","3475","128610.9","87939" +"PS","en","Men -- Psychology -- Fiction,Psychological fiction,Time travel -- Fiction,Science fiction,Love stories,Individuality -- Fiction","Anthem","Text","1551","1250","192","https://www.gutenberg.org/ebooks/1250","1905","1982","Rand, Ayn","1","March, 1998","3","March","1998","6","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","6.5","7.01","5.47","1316","4.4","90.09","8.0","4.5","3.1","0.12349921736860534","0.4873084244100969","4.29","15.0","0.07","82019","110","1244","22923.0","19127" +"PR","en","England -- Fiction,British -- Italy -- Fiction,Humorous stories,Young women -- Fiction,Florence (Italy) -- Fiction","A Room with a View","Text","1546","2641","193","https://www.gutenberg.org/ebooks/2641","1879","1970","Forster, E. M. (Edward Morgan)","1","May, 2001","5","May","2001","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","7.5","10.08","6.06","7935","5.2","77.23","6.4","3.0","3.1","0.08442956732515124","0.535943540649572","4.87","11.0","0.08","323940","1616","5596","90181.8","66574" +"PQ","en","Epic poetry, Italian -- Translations into English;Italian poetry -- To 1400 -- Translations into English","The Divine Comedy by Dante, Illustrated, Paradise, Complete","Text","1545","8799","194","https://www.gutenberg.org/ebooks/8799","1265","1321","Dante Alighieri","2","August 2, 2004","8","August","2004","8","image/jpeg,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","16.3","11.62","7.34","5074","11.1","67.42","13.600000000000001","26.5","3.1","0.17167433478627506","0.5026311608167952","4.88","29.0","0.03","172852","395","1202","45771.3","35436" +"TA","en","Wood,Wood -- Testing","The Mechanical Properties of Wood: Including a Discussion of the Factors Affecting the Mechanical Properties, and Methods of Timber Testing","Text","1544","12299","195","https://www.gutenberg.org/ebooks/12299","1881","1945","Record, Samuel J. (Samuel James)","8","May 8, 2004","5","May","2004","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","12.7","14.96","5.86","4620","5.6","81.63","8.0","6.0","3.1","0.03410247808381846","0.41584870215677555","5.61","15.0","0.06","276151","1901","3175","64301.4","49209" +"PR","en","Virtue -- Fiction,Epistolary fiction,Kidnapping victims -- Fiction,Didactic fiction,Women household employees -- Fiction,England -- Fiction,Master and servant -- Fiction","Pamela, or Virtue Rewarded","Text","1541","6124","196","https://www.gutenberg.org/ebooks/6124","1689","1761","Richardson, Samuel","1","July, 2004","7","July","2004","6","text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","10.1","8.19","5.58","11988","8.3","74.53","10.8","13.5","3.1","0.14630243595671302","0.5662605962291251","4.34","22.0","0.04","961887","3057","9955","277317.0","221390" +"PS","en","College students -- Fiction;Children of the rich -- Fiction;Bildungsromans;World War, 1914-1918 -- Veterans -- Fiction;Advertising -- Fiction;Young men -- Fiction;Love stories","This Side of Paradise","Text","1536","805","197","https://www.gutenberg.org/ebooks/805","1896","1940","Fitzgerald, F. Scott (Francis Scott)","1","February, 1997","2","February","1997","8","application/rdf+xml,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,text/plain","10.2","11.77","6.55","11124","6.8","73.17","8.0","2.5","3.1","0.06048886714971879","0.5086551718255465","5.06","15.0","0.06","408838","2773","5193","114721.2","80780" +"PZ,PR","en","Short stories, English;Children's stories, English;Fairy tales","The Happy Prince, and Other Tales","Text","1530","902","198","https://www.gutenberg.org/ebooks/902","1854","1900","Wilde, Oscar","29","March 29, 2015","3","March","2015","7","image/jpeg,text/html,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","8.1","8.64","6.03","1655","6.0","80.62","8.4","17.0","3.1","0.14450213619948019","0.5431964834937072","4.52","16.0","0.06","73985","236","988","20679.3","16358" +"PS","en","Voyages and travels,Middle East -- Description and travel,Europe -- Description and travel","The Innocents Abroad","Text","1523","3176","199","https://www.gutenberg.org/ebooks/3176","1835","1910","Twain, Mark","18","August 18, 2006","8","August","2006","8","image/jpeg,text/html; charset=iso-8859-1,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","12.6","11.09","6.38","20216","9.5","66.07","10.8","6.5","3.1","0.11035215055445223","0.5020033974127331","4.84","22.0","0.04","934065","6047","8620","271872.9","193159" +"PR","en","English poetry -- 18th century","An Essay on Man; Moral Essays and Satires","Text","1517","2428","200","https://www.gutenberg.org/ebooks/2428","1688","1744","Pope, Alexander","20","August 20, 2007","8","August","2007","7","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","12.4","10.97","6.99","6719","8.3","74.53","10.8","5.0","3.1","0.134123244134029","0.5156627428683408","4.82","22.0","0.04","225628","497","2106","61194.6","46813" +"PS","en","Trials (Murder) -- Fiction,Missouri -- Fiction,Race relations -- Fiction,Infants switched at birth -- Fiction,Impostors and imposture -- Fiction,Passing (Identity) -- Fiction,Legal stories","The Tragedy of Pudd'nhead Wilson","Text","1511","102","201","https://www.gutenberg.org/ebooks/102","1835","1910","Twain, Mark","1","January, 1994","1","January","1994","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","10.5","9.98","6.47","6345","7.2","77.57","9.600000000000001","13.5","3.1","0.0956260273269285","0.4799843336862573","4.7","19.0","0.05","249191","1248","2697","70360.2","53063" +"B,PA","en","Classical literature;Philosophy, Ancient;Socrates, 470 BC-399 BC;Love -- Early works to 1800","Symposium","Text","1511","1600","202","https://www.gutenberg.org/ebooks/1600","-428","-348","Plato","1","January, 1999","1","January","1999","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","15.8","10.22","6.96","3783","12.6","57.95","14.0","13.5","8.8","0.21123565090641883","0.5475211028218456","4.64","30.0","0.03","151197","1065","1059","45428.4","32587" +"BJ","en","Etiquette for men,Etiquette,Men -- Conduct of life","The Gentlemen's Book of Etiquette and Manual of Politeness: Being a Complete Guide for a Gentleman's Conduct in All His Relations Towards Society","Text","1510","39293","203","https://www.gutenberg.org/ebooks/39293","0","0","Hartley, Cecil B.","28","March 28, 2012","3","March","2012","8","text/html; charset=utf-8,text/plain; charset=us-ascii,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","14.0","10.68","6.58","9407","11.1","62.01","12.4","7.0","3.1","0.12525634853742382","0.5093012626802647","4.77","26.0","0.04","427624","3077","3445","126439.2","89603" +"","en","","The Man Who Was Six","Text","1501","51295","204","https://www.gutenberg.org/ebooks/51295","1915","2004","Wallace, F. L. (Floyd L.)","24","February 24, 2016","2","February","2016","8","application/x-mobipocket-ebook,image/jpeg,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","7.1","9.84","6.61","2230","5.2","77.23","6.4","4.0","3.1","0.053869615615906585","0.4698068371939046","4.88","11.0","0.09","70956","461","1318","19800.9","14531" +"PA","en","Antigone (Mythological character) -- Drama,Greek drama (Tragedy) -- Translations into English,Oedipus (Greek mythological figure) -- Drama,Tragedies","Plays of Sophocles: Oedipus the King; Oedipus at Colonus; Antigone","Text","1496","31","205","https://www.gutenberg.org/ebooks/31","-496","-406","Sophocles","7","March 7, 2006","3","March","2006","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","9.2","10.55","6.23","4381","5.6","81.63","8.0","13.5","3.1","0.056766180435339195","0.5225989365925331","4.85","15.0","0.06","181303","341","2414","48235.5","37390" +"PS","en","Virginia -- History -- Civil War, 1861-1865 -- Fiction;War stories;United States -- History -- Civil War, 1861-1865 -- Fiction;Historical fiction;Chancellorsville, Battle of, Chancellorsville, Va., 1863 -- Fiction","The Red Badge of Courage: An Episode of the American Civil War","Text","1496","73","206","https://www.gutenberg.org/ebooks/73","1871","1900","Crane, Stephen","1","July 1, 2008","7","July","2008","7","text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","7.9","9.73","6.21","5629","4.8","83.66","7.2","14.0","3.1","0.039197601684168575","0.48418519699101503","4.81","13.0","0.08","221566","1105","3478","62172.0","46088" +"HD","en","Working class -- Great Britain,Great Britain -- Economic conditions","The Condition of the Working-Class in England in 1844: with a Preface written in 1892","Text","1489","17306","207","https://www.gutenberg.org/ebooks/17306","1820","1895","Engels, Friedrich","13","December 13, 2005","12","December","2005","6","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","16.9","12.94","6.53","11475","12.6","52.53","12.8","18.0","8.8","0.06258988757878826","0.45907164652198745","5.16","27.0","0.04","603104","6007","4177","174299.4","116909" +"PQ","en","Epic poetry, Italian -- Translations into English;Italian poetry -- To 1400 -- Translations into English;Hell -- Poetry","Divine Comedy, Longfellow's Translation, Hell","Text","1487","1001","208","https://www.gutenberg.org/ebooks/1001","1265","1321","Dante Alighieri","1","August, 1997","8","August","1997","7","text/html; charset=iso-8859-1,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","14.8","10.68","7.05","5039","10.3","69.45","12.8","8.5","3.1","0.04675495891741249","0.48611313812916784","4.77","27.0","0.04","182524","463","1387","50258.7","38266" +"PQ","en","France -- History -- 17th century -- Drama;Authors, French -- 17th century -- Drama;Cyrano de Bergerac, 1619-1655 -- Drama","Cyrano de Bergerac","Text","1486","1254","209","https://www.gutenberg.org/ebooks/1254","1868","1918","Rostand, Edmond","1","March, 1998","3","March","1998","7","text/html; charset=iso-8859-1,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","8.7","12.38","6.43","5156","4.4","79.26","5.6000000000000005","26.0","3.1","0.1191783740069421","0.44194780542406775","5.42","9.0","0.11","187927","513","3742","47763.9","34675" +"PR","en","Hamlet (Legendary character) -- Drama,Tragedies,Murder victims' families -- Drama,Princes -- Drama,Denmark -- Drama,Fathers -- Death -- Drama,Revenge -- Drama,Kings and rulers -- Succession -- Drama","Hamlet","Text","1481","2265","210","https://www.gutenberg.org/ebooks/2265","1564","1616","Shakespeare, William","1","January 1, 1603","1","January","1603","7","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","8.9","9.74","6.42","3821","6.0","80.62","8.4","13.5","3.1","0.16213268040907727","0.5166288924632603","4.71","16.0","0.06","142685","255","1859","38560.5","30269" +"B","en","Methodology,Science -- Methodology","Discourse on the Method of Rightly Conducting One's Reason and of Seeking Truth in the Sciences","Text","1476","59","211","https://www.gutenberg.org/ebooks/59","1596","1650","Descartes, Rene","1","July 1, 2008","7","July","2008","8","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/octet-stream,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","40.7","11.4","9.35","2624","31.7","8.21","33.6","55.0","13.0","0.1617800003925614","0.4990168499792906","4.74","79.0","0.01","109197","933","289","33185.7","23024" +"PS","en","Slums -- Fiction,Poor women -- Fiction,Psychological fiction,Prostitutes -- Fiction,Poor families -- Fiction,Suicide victims -- Fiction,New York (N.Y.) -- Fiction","Maggie: A Girl of the Streets","Text","1470","447","212","https://www.gutenberg.org/ebooks/447","1871","1900","Crane, Stephen","1","February, 1996","2","February","1996","7","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","8.0","10.25","6.51","3307","5.6","76.22","6.800000000000001","5.5","3.1","0.025554916472369512","0.4847445000271683","4.9","12.0","0.08","112317","579","1818","31070.7","22924" +"","en","Literature -- Collections","The Library of Entertainment Handbook","Text","1466","51248","213","https://www.gutenberg.org/ebooks/51248","0","0","Scammell, John Chilton","18","February 18, 2016","2","February","2016","7","image/jpeg,text/plain; charset=utf-8,text/html; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","12.2","13.4","6.95","8230","8.7","62.68","8.8","5.0","3.1","0.16266973588623995","0.44347054893786564","5.34","17.0","0.06","280673","2548","3086","77789.7","52587" +"PQ","en","Submarines (Ships) -- Fiction,Science fiction,Sea stories,Underwater exploration -- Fiction","Twenty Thousand Leagues under the Sea","Text","1459","164","214","https://www.gutenberg.org/ebooks/164","1828","1905","Verne, Jules","24","May 24, 2008","5","May","2008","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","9.8","10.84","6.0","10269","7.2","72.16","8.4","14.5","3.1","0.09317147812664044","0.4856869624332647","4.9","16.0","0.06","504932","3030","6292","144011.7","103035" +"PS","en","Short stories, American;Horror tales, American;United States -- Social life and customs -- 19th century -- Fiction","The King in Yellow","Text","1453","8492","215","https://www.gutenberg.org/ebooks/8492","1865","1933","Chambers, Robert W. (Robert William)","1","July, 2005","7","July","2005","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","9.4","10.15","6.3","8474","6.0","80.62","8.4","11.0","3.1","0.06425368631840757","0.46843977272886683","4.78","16.0","0.06","342362","1320","4317","95631.3","71562" +"B","en","Will;Philosophy;Idea (Philosophy);Knowledge, Theory of","The World as Will and Idea (Vol. 1 of 3)","Text","1452","38427","216","https://www.gutenberg.org/ebooks/38427","1788","1860","Schopenhauer, Arthur","27","December 27, 2011","12","December","2011","11","application/prs.tei,text/plain; charset=us-ascii,text/html; charset=utf-8,application/x-mobipocket-ebook,text/plain; charset=utf-8,application/octet-stream,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/pdf","21.5","13.18","6.47","12675","16.5","42.38","16.8","3.5","11.2","0.044499707696633965","0.47782094638957295","5.15","37.0","0.03","1031991","12094","5367","304776.9","200540" +"DS","en","Philippines -- Politics and government -- 1898-1935,Philippines -- History -- 1898-1946","The American Occupation of the Philippines 1898-1912","Text","1448","36542","217","https://www.gutenberg.org/ebooks/36542","1869","1918","Blount, James H. (James Henderson)","28","June 28, 2011","6","June","2011","9","image/jpeg,text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","16.3","12.89","6.23","15505","12.6","52.53","12.8","12.5","8.8","0.08865768322846684","0.4333744878868633","5.15","27.0","0.04","1001457","12139","7200","292791.6","194573" +"PR","en","Chaucer, Geoffrey, -1400;English poetry;Christian pilgrims and pilgrimages -- Poetry","The Canterbury Tales, and Other Poems","Text","1447","2383","218","https://www.gutenberg.org/ebooks/2383","1342","1400","Chaucer, Geoffrey","1","January 1, 1475","1","January","1475","7","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","15.9","10.57","6.57","25497","11.5","66.41","14.0","7.0","3.1","0.1704708340227229","0.5266262077636364","4.7","30.0","0.03","1313149","3815","9201","361503.9","279127" +"PR","en","Humorous stories;Valets -- Fiction;Jeeves (Fictitious character) -- Fiction;Wooster, Bertie (Fictitious character) -- Fiction;England -- Fiction;Single men -- Fiction","My Man Jeeves","Text","1444","8164","219","https://www.gutenberg.org/ebooks/8164","1881","1975","Wodehouse, P. G. (Pelham Grenville)","1","May, 2005","5","May","2005","7","application/rdf+xml,text/plain; charset=us-ascii,text/plain,text/plain; charset=iso-8859-1,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","6.4","8.57","5.75","4871","4.4","84.68","6.800000000000001","7.5","3.1","0.09973980078566184","0.4772984361617066","4.61","12.0","0.08","233636","915","4166","64909.8","50731" +"PR","en","Virtues -- Poetry,Knights and knighthood -- Poetry","Spenser's The Faerie Queene, Book I","Text","1443","15272","220","https://www.gutenberg.org/ebooks/15272","1551","1599","Spenser, Edmund","7","March 7, 2005","3","March","2005","8","text/plain; charset=us-ascii,text/plain,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","13.1","11.72","6.91","10283","8.3","74.53","10.8","3.5","3.1","0.1295838614977687","0.5274408877921158","5.0","22.0","0.05","371807","1167","3376","98006.4","74391" +"PR","en","Prostitution -- Great Britain -- Drama,Working class women -- Great Britain -- Drama,Prostitutes -- Great Britain -- Drama,Great Britain -- Social conditions -- 19th century -- Drama","Mrs. Warren's Profession","Text","1441","1097","221","https://www.gutenberg.org/ebooks/1097","1856","1950","Shaw, Bernard","11","February 11, 2006","2","February","2006","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","8.5","9.91","6.4","4547","5.2","82.65","7.6000000000000005","29.5","3.1","0.08346501077278332","0.524449917069139","4.79","14.0","0.07","166013","1038","2346","46748.7","34687" +"B","en","Apologetics,Philosophy","Pascal's Pensées","Text","1435","18269","222","https://www.gutenberg.org/ebooks/18269","1623","1662","Pascal, Blaise","27","April 27, 2006","4","April","2006","8","text/html; charset=utf-8,text/plain; charset=us-ascii,text/plain; charset=utf-8,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","10.9","10.97","6.03","10517","6.8","78.59","9.200000000000001","7.0","3.1","0.11915840551483528","0.5506872509536349","4.87","18.0","0.05","539550","3658","5912","149237.1","110771" +"PT","en","Erotic stories,Sadomasochism -- Fiction","Venus in Furs","Text","1425","6852","223","https://www.gutenberg.org/ebooks/6852","1836","1895","Sacher-Masoch, Leopold, Ritter von","1","November, 2004","11","November","2004","8","text/html,text/plain; charset=us-ascii,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","8.7","9.79","6.29","5069","6.8","73.17","8.0","10.5","3.1","0.09942970495554342","0.5301048301011001","4.77","15.0","0.07","200172","1111","2748","57140.1","41936" +"PN","en","Arthur, King -- Legends;Knights and knighthood -- Folklore;Folklore -- England;Arthurian romances -- Adaptations","The Legends of King Arthur and His Knights","Text","1421","12753","224","https://www.gutenberg.org/ebooks/12753","1831","1908","Knowles, James, Sir","28","June 28, 2004","6","June","2004","8","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","13.1","9.23","5.86","5537","8.7","78.93","12.4","13.0","3.1","0.1813419405642443","0.5325351251258362","4.52","26.0","0.04","423607","596","3549","115843.5","93648" +"PA","en","Rome -- Fiction;Satire, Latin -- Translations into English","The Satyricon — Complete","Text","1412","5225","225","https://www.gutenberg.org/ebooks/5225","20","66","Petronius Arbiter","31","October 31, 2006","10","October","2006","8","image/jpeg,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","14.3","11.15","6.97","13013","10.7","63.02","12.0","15.0","3.1","0.10596892310572777","0.49729381873675305","4.85","25.0","0.04","474848","2794","3799","137394.9","98005" +"PR","en","Christian fiction,Christian pilgrims and pilgrimages -- Fiction","The Pilgrim's Progress from this world to that which is to come: Delivered under the similitude of a dream, by John Bunyan","Text","1402","131","226","https://www.gutenberg.org/ebooks/131","1628","1688","Bunyan, John","12","June 12, 2008","6","June","2008","6","text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","12.0","8.83","5.99","4291","7.9","80.96","11.600000000000001","7.0","3.1","0.1417832540379696","0.4803898570030388","4.45","24.0","0.04","258035","644","2324","70731.0","58049" +"PZ,PR","en","Adventure and adventurers -- Fiction,Kidnapping -- Fiction,Scotland -- History -- 18th century -- Fiction,Historical fiction","Kidnapped","Text","1402","421","227","https://www.gutenberg.org/ebooks/421","1850","1894","Stevenson, Robert Louis","16","January 16, 2006","1","January","2006","8","image/jpeg,text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","10.0","7.89","5.98","6754","6.8","84.0","10.4","18.0","3.1","0.08661149447207453","0.4890777658807104","4.34","21.0","0.05","355162","725","3742","100635.3","81861" +"U","en","Military art and science,War","On War — Volume 1","Text","1399","1946","228","https://www.gutenberg.org/ebooks/1946","1780","1831","Clausewitz, Carl von","25","February 25, 2006","2","February","2006","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","19.7","11.96","6.63","8562","15.8","44.41","16.0","7.5","8.8","0.11320892962762458","0.4873319062396729","4.94","35.0","0.03","530178","5293","3000","160555.5","107354" +"PQ","en","Rousseau, Jean-Jacques, 1712-1778;Authors, French -- 18th century -- Biography","The Confessions of Jean Jacques Rousseau — Complete","Text","1397","3913","229","https://www.gutenberg.org/ebooks/3913","1712","1778","Rousseau, Jean-Jacques","5","September 5, 2015","9","September","2015","9","application/rdf+xml,image/jpeg,text/html; charset=iso-8859-1,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","16.4","10.92","6.13","17579","12.6","57.95","14.0","21.0","8.8","0.12966197228800797","0.5215507421005268","4.76","30.0","0.03","1310575","11232","8946","396227.7","275047" +"PT","de","Psychological fiction,Metamorphosis -- Fiction","Die Verwandlung","Text","1389","22367","230","https://www.gutenberg.org/ebooks/22367","1883","1924","Kafka, Franz","21","August 21, 2007","8","August","2007","8","image/jpeg,text/html; charset=iso-8859-1,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","18.0","15.03","7.74","3422","11.1","62.01","12.4","14.5","3.1","0.17980387369791673","0.5096296296296299","5.52","26.0","0.04","105822","630","712","27589.5","19180" +"PG","en","Russia -- Social conditions -- 1801-1917 -- Fiction,Historical fiction","The Idiot","Text","1386","2638","231","https://www.gutenberg.org/ebooks/2638","1821","1881","Dostoyevsky, Fyodor","1","May, 2001","5","May","2001","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","9.0","10.21","5.47","16594","6.8","73.17","8.0","13.5","3.1","0.08061246516920759","0.511100759341765","4.79","15.0","0.06","1157000","7507","15375","332942.4","241531" +"","en","","Famous Impostors","Text","1381","51391","232","https://www.gutenberg.org/ebooks/51391","1847","1912","Stoker, Bram","8","March 8, 2016","3","March","2016","7","image/jpeg,text/plain; charset=utf-8,text/html; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","14.1","11.84","6.96","10598","11.5","55.58","11.600000000000001","14.0","8.8","0.09138486519911225","0.4849238510798955","4.97","24.0","0.04","389989","3528","3249","115050.6","78507" +"PR","en","Self-experimentation in medicine -- Fiction,Psychological fiction,Multiple personality -- Fiction,Physicians -- Fiction,London (England) -- Fiction,Science fiction,Horror tales","The Strange Case of Dr. Jekyll and Mr. Hyde","Text","1380","43","233","https://www.gutenberg.org/ebooks/43","1850","1894","Stevenson, Robert Louis","31","October 31, 1992","10","October","1992","6","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","10.8","9.4","6.81","3462","7.9","75.54","10.4","10.5","3.1","0.06790731767918158","0.4869953516543177","4.6","21.0","0.05","117634","539","1216","34103.7","25585" +"","en","","The Addicts","Text","1379","51240","234","https://www.gutenberg.org/ebooks/51240","1906","1980","Samachson, Joseph","17","February 17, 2016","2","February","2016","8","text/plain,image/jpeg,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","7.5","9.38","6.74","563","4.8","83.66","7.2","5.5","3.1","0.09122868543493541","0.5539778795278799","4.75","13.0","0.08","17152","91","274","4848.3","3614" +"PR","en","Challenger, Professor (Fictitious character) -- Fiction;Fantasy fiction;Prehistoric peoples -- Fiction;Dinosaurs -- Fiction;South America -- Fiction","The Lost World","Text","1378","139","235","https://www.gutenberg.org/ebooks/139","1859","1930","Doyle, Arthur Conan","19","June 19, 2008","6","June","2008","7","text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","9.7","9.86","6.22","8371","7.6","71.14","8.8","11.0","3.1","0.07634689491409588","0.48508208018969845","4.73","17.0","0.06","358664","1966","4259","103773.6","75759" +"PS","en","Mississippi River -- Description and travel;Mississippi River Valley -- Social life and customs -- 19th century;Authors, American -- 19th century -- Biography;Pilots and pilotage -- Mississippi River;Twain, Mark, 1835-1910 -- Travel -- Mississippi River","Life on the Mississippi","Text","1368","245","236","https://www.gutenberg.org/ebooks/245","1835","1910","Twain, Mark","20","August 20, 2006","8","August","2006","7","image/jpeg,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","11.4","10.5","6.34","15660","8.7","68.1","10.0","2.5","3.1","0.08813787521241054","0.4565427618891448","4.79","20.0","0.05","691132","4369","7009","197305.2","144374" +"B","en","Ethics;Knowledge, Theory of","An Enquiry Concerning Human Understanding","Text","1350","9662","237","https://www.gutenberg.org/ebooks/9662","1711","1776","Hume, David","1","January, 2006","1","January","2006","8","application/rdf+xml,text/html; charset=iso-8859-1,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","18.5","13.01","6.77","5852","14.2","48.47","14.4","4.0","8.8","0.09556415926297585","0.47618840202705703","5.12","31.0","0.03","296154","3345","1822","89534.7","57801" +"","en","","The Marching Morons","Text","1349","51233","238","https://www.gutenberg.org/ebooks/51233","1923","1958","Kornbluth, C. M. (Cyril M.)","16","February 16, 2016","2","February","2016","7","application/x-mobipocket-ebook,image/jpeg,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/rdf+xml,application/epub+zip,text/plain","9.7","12.06","7.5","2255","6.0","75.2","7.2","5.0","3.1","0.08834073629032801","0.48487265403063917","5.16","13.0","0.07","57058","466","810","15806.7","11054" +"PQ","en","Plague -- Europe -- History -- Fiction,Allegories,Frame-stories,Storytelling -- Fiction","The Decameron of Giovanni Boccaccio","Text","1339","23700","239","https://www.gutenberg.org/ebooks/23700","1313","1375","Boccaccio, Giovanni","3","December 3, 2007","12","December","2007","9","image/jpeg,text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","22.3","10.81","6.68","17717","17.7","44.75","19.200000000000003","9.0","3.1","0.18166130226146168","0.5190554120228744","4.69","43.0","0.02","1442516","6455","7101","415779.3","307841" +"HQ","en","Women's rights -- Great Britain,Women -- History -- 19th century,Women -- Education -- Great Britain,Feminism","A Vindication of the Rights of Woman: With Strictures on Political and Moral Subjects","Text","1339","3420","240","https://www.gutenberg.org/ebooks/3420","1759","1797","Wollstonecraft, Mary","1","September, 2002","9","September","2002","6","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","19.3","12.72","6.94","9116","15.0","46.44","15.200000000000001","5.0","8.8","0.11309840367224837","0.5240286068222014","5.07","33.0","0.03","438290","4087","2560","129982.5","86456" +"PS","en","Africa -- Fiction,Tarzan (Fictitious character) -- Fiction,Fantasy fiction,Wild men -- Fiction,British -- Africa -- Fiction,Adventure stories","Tarzan of the Apes","Text","1336","78","241","https://www.gutenberg.org/ebooks/78","1875","1950","Burroughs, Edgar Rice","23","June 23, 2008","6","June","2008","7","text/html; charset=iso-8859-1,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","11.4","10.73","6.06","7727","8.7","68.1","10.0","53.0","3.1","0.07473859659261137","0.48893439915853887","4.83","20.0","0.05","412646","1822","4234","116465.4","85520" +"HV","en","Lynching","Southern Horrors: Lynch Law in All Its Phases","Text","1333","14975","242","https://www.gutenberg.org/ebooks/14975","1862","1931","Wells-Barnett, Ida B.","8","February 8, 2005","2","February","2005","7","application/x-mobipocket-ebook,image/jpeg,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","12.6","11.31","7.43","1687","10.3","58.62","10.4","11.5","3.1","0.0381264150498412","0.41374366318373623","4.93","21.0","0.05","47665","398","448","14031.0","9664" +"PG","en","Russia -- Social life and customs -- Drama,Country life -- Russia -- Drama,Russian drama -- Translations into English,Families -- Russia -- Drama","Uncle Vanya: Scenes from Country Life in Four Acts","Text","1333","1756","243","https://www.gutenberg.org/ebooks/1756","1860","1904","Chekhov, Anton Pavlovich","1","May, 1999","5","May","1999","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","6.1","8.62","6.01","1902","4.0","85.69","6.4","14.0","3.1","0.05659511237563874","0.5494429115745127","4.67","11.0","0.09","76783","347","1495","21947.4","16449" +"PQ","en","Philippines -- History -- 1812-1898 -- Fiction,Historical fiction","The Social Cancer: A Complete English Version of Noli Me Tangere","Text","1333","6737","244","https://www.gutenberg.org/ebooks/6737","1861","1896","Rizal, Jose","17","June 17, 2007","6","June","2007","9","image/jpeg,text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","11.2","11.26","6.13","17329","8.3","69.11","9.600000000000001","8.5","3.1","0.07850745367911736","0.4758420130712635","4.92","19.0","0.05","864628","5781","9251","248754.6","175846" +"PQ","en","Giants -- Fiction;Fantasy fiction, French -- Translations into English;Gargantua (Legendary character) -- Fiction","Gargantua and Pantagruel","Text","1328","1200","245","https://www.gutenberg.org/ebooks/1200","0","0","Rabelais, Francois","8","August 8, 2004","8","August","2004","7","image/jpeg,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","15.1","11.09","6.6","32916","11.5","60.99","12.8","5.5","3.1","0.146353827142644","0.5080541682189238","4.84","27.0","0.04","1548310","9558","11605","443115.0","319655" +"BV","en","Spirituality,God (Christianity) -- Worship and love","The Pursuit of God","Text","1328","25141","246","https://www.gutenberg.org/ebooks/25141","1897","1963","Tozer, A. W. (Aiden Wilson)","23","April 23, 2008","4","April","2008","8","text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","10.0","9.4","6.47","3498","8.3","69.11","9.600000000000001","8.5","3.1","0.11572133708240111","0.4768617989070636","4.6","19.0","0.05","134387","795","1501","39607.2","29217" +"KF,JK","en","Constitutional law -- United States,Constitutional history -- United States -- Sources","The Federalist Papers","Text","1327","1404","247","https://www.gutenberg.org/ebooks/1404","1745","1829","Jay, John","1","July, 1998","7","July","1998","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","19.2","13.24","6.25","12556","15.8","39.0","14.8","15.5","11.2","0.10619526352642564","0.45126228123323703","5.16","32.0","0.03","991913","14140","5901","303713.1","192349" +"PR","en","Fiction -- Authorship -- Fiction,Infants -- Fiction,Fetus -- Fiction,Experimental fiction,Stream of consciousness fiction","The Life and Opinions of Tristram Shandy, Gentleman","Text","1326","1079","248","https://www.gutenberg.org/ebooks/1079","1713","1768","Sterne, Laurence","1","October, 1997","10","October","1997","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","19.5","12.08","7.28","21613","14.6","52.87","16.0","18.0","8.8","0.1145691664755748","0.47425201895906327","4.96","35.0","0.03","886874","6319","5096","250581.6","178843" +"PR","en","Erotic literature;Heidegger, John James, 1659?-1748;Penis -- Poetry","The Ladies Delight","Text","1322","14005","249","https://www.gutenberg.org/ebooks/14005","0","0","Anonymous","10","November 10, 2004","11","November","2004","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","25.2","12.84","9.02","972","17.3","51.18","20.0","6.5","3.1","0.20972126173384031","0.5171780548824576","5.04","45.0","0.02","24516","55","106","6429.6","4863" +"DG","en","Rome -- History -- Empire, 30 B.C.-284 A.D.;Emperors -- Rome -- Biography -- Early works to 1800","The Lives of the Twelve Caesars, Complete","Text","1317","6400","250","https://www.gutenberg.org/ebooks/6400","0","0","Suetonius","22","October 22, 2006","10","October","2006","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","16.7","12.49","6.44","20876","13.0","51.52","13.200000000000001","8.0","8.8","0.10777752741685483","0.45940787683969164","5.03","28.0","0.03","1173111","9332","8098","342845.1","233339" +"PS,E660","en","West (U.S.) -- Description and travel;West (U.S.) -- Intellectual life -- 19th century;Authors, American -- Homes and haunts -- West (U.S.);Twain, Mark, 1835-1910 -- Travel -- West (U.S.)","Roughing It","Text","1313","3177","251","https://www.gutenberg.org/ebooks/3177","1835","1910","Twain, Mark","18","August 18, 2006","8","August","2006","7","image/jpeg,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","12.8","10.91","6.49","17982","9.9","65.05","11.200000000000001","8.5","3.1","0.07437028832112355","0.4775006106305633","4.81","23.0","0.04","798587","5364","7156","230879.7","166160" +"PS","en","Science fiction,War stories,Robots -- Fiction","Second Variety","Text","1308","32032","252","https://www.gutenberg.org/ebooks/32032","1928","1982","Dick, Philip K.","17","April 17, 2010","4","April","2010","7","image/jpeg,text/html; charset=utf-8,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","6.0","9.47","5.82","1772","2.5","89.75","4.800000000000001","5.0","3.1","-0.0006629284979490793","0.42875313563886014","5.02","7.0","0.13","76487","197","2021","20152.8","15237" +"","en","","Bridge Crossing","Text","1308","51241","253","https://www.gutenberg.org/ebooks/51241","1915","2003","Dryfoos, Dave","17","February 17, 2016","2","February","2016","8","image/jpeg,text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","7.9","10.66","7.16","914","5.2","77.23","6.4","5.0","3.1","0.02917997241196132","0.49870049490739166","4.97","11.0","0.08","24095","97","407","6589.8","4852" +"PJ","en","Tales -- Arab countries,Fairy tales","The Thousand and One Nights, Vol. I.: Commonly Called the Arabian Nights' Entertainments","Text","1307","34206","254","https://www.gutenberg.org/ebooks/34206","0","0","Unknown","3","November 3, 2010","11","November","2010","9","image/jpeg,text/html; charset=utf-8,text/plain; charset=us-ascii,text/plain; charset=utf-8,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","14.6","10.68","6.08","18372","11.5","60.99","12.8","17.0","3.1","0.10460990692900307","0.4489104404958306","4.77","27.0","0.04","1253534","6782","9692","358387.2","262842" +"B","en","Philosophy and religion,Happiness","The Consolation of Philosophy","Text","1306","14328","255","https://www.gutenberg.org/ebooks/14328","480","524","Boethius","11","December 11, 2004","12","December","2004","8","text/html; charset=utf-8,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","13.2","11.61","6.81","5627","9.5","66.07","10.8","7.5","3.1","0.14021301470800654","0.526351358264999","4.93","22.0","0.04","210578","1322","1877","59319.0","42688" +"CR","en","Heraldry -- Great Britain","A Complete Guide to Heraldry","Text","1306","41617","256","https://www.gutenberg.org/ebooks/41617","1871","1928","Fox-Davies, Arthur Charles","13","December 13, 2012","12","December","2012","8","application/rdf+xml,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/html; charset=iso-8859-1,text/plain","15.6","12.36","6.17","21310","11.1","62.01","12.4","7.0","8.8","0.053434836123623944","0.414526607085762","5.06","26.0","0.04","1366469","10886","10203","384529.5","270070" +"PZ,PT","de","Children's poetry, German;Practical jokes -- Juvenile poetry;Wit and humor","Max und Moritz: Eine Bubengeschichte in sieben Streichen","Text","1302","17161","257","https://www.gutenberg.org/ebooks/17161","1832","1908","Busch, Wilhelm","21","December 21, 2005","12","December","2005","7","application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/pdf,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","13.7","17.1","7.57","537","5.6","76.22","6.800000000000001","7.5","3.1","0.7333333333333333","0.6733333333333333","6.08","12.0","0.08","15431","123","196","3434.4","2540" +"PA,PN","en","Aesthetics -- Early works to 1800,Poetry -- Early works to 1800","The Poetics of Aristotle","Text","1300","1974","258","https://www.gutenberg.org/ebooks/1974","-384","-322","Aristotle","1","November, 1999","11","November","1999","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","13.0","11.67","7.14","2307","10.7","57.61","10.8","8.5","3.1","0.08152508394335642","0.4605388289541757","4.94","22.0","0.04","74594","659","676","22528.8","15111" +"PT","en","Norwegian drama -- Translations into English","Ghosts","Text","1295","8121","259","https://www.gutenberg.org/ebooks/8121","1828","1906","Ibsen, Henrik","1","May, 2005","5","May","2005","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","7.0","9.84","5.96","2807","3.7","86.71","6.0","8.0","3.1","0.08620252454020204","0.5133341453191913","4.88","10.0","0.09","118219","460","2234","31847.4","24250" +"PZ","en","Children -- Conduct of life -- Juvenile fiction;Children's stories, German -- Translations into English;Children's poetry, German -- Translations into English;Stories in rhyme;Picture books for children;Behavior -- Fiction","Struwwelpeter: Merry Stories and Funny Pictures","Text","1290","12116","260","https://www.gutenberg.org/ebooks/12116","1809","1894","Hoffmann, Heinrich","23","April 23, 2004","4","April","2004","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","9.6","9.97","6.25","265","5.2","88.06","8.8","8.0","3.1","0.0014682547368982","0.5560960579824218","4.75","17.0","0.06","11231","13","136","2847.6","2362" +"PS","en","Human-alien encounters -- Fiction,Science fiction","Youth","Text","1287","31547","261","https://www.gutenberg.org/ebooks/31547","1920","1992","Asimov, Isaac","7","March 7, 2010","3","March","2010","7","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","6.6","9.89","6.24","1376","3.3","87.72","5.6000000000000005","4.5","3.1","0.047899235076791884","0.4687500649602914","4.94","9.0","0.1","49777","323","1057","13467.6","10067" +"PR","en","India -- History -- British occupation, 1765-1947 -- Fiction;British -- India -- Fiction","Plain Tales from the Hills","Text","1284","1858","262","https://www.gutenberg.org/ebooks/1858","1865","1936","Kipling, Rudyard","1","August, 1999","8","August","1999","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","10.2","10.33","6.43","8643","7.9","70.13","9.200000000000001","28.0","3.1","0.0667783618143388","0.47963180558942303","4.76","18.0","0.05","340924","1853","3895","96805.8","71634" +"PR","en","Mentally ill -- Fiction,Science fiction,Scientists -- Fiction,Psychological fiction","The Invisible Man: A Grotesque Romance","Text","1283","5230","263","https://www.gutenberg.org/ebooks/5230","1866","1946","Wells, H. G. (Herbert George)","7","October 7, 2004","10","October","2004","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","8.1","10.26","6.21","5919","4.8","83.66","7.2","6.5","3.1","0.010355562539027576","0.4796150926675718","4.85","13.0","0.07","235353","1387","3601","65285.1","48484" +"B","en","Utilitarianism","Utilitarianism","Text","1282","11224","264","https://www.gutenberg.org/ebooks/11224","1806","1873","Mill, John Stuart","22","February 22, 2004","2","February","2004","7","application/rdf+xml,text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/epub+zip,text/html; charset=iso-8859-1,text/plain","21.6","12.37","7.53","3509","16.9","41.37","17.2","7.5","11.2","0.13449384798082775","0.4812294951931448","5.01","38.0","0.03","138340","1745","709","42696.0","27608" +"PC","pt","Portuguese language -- Dictionaries","Novo dicionário da língua portuguesa","Text","1277","31552","265","https://www.gutenberg.org/ebooks/31552","1846","1925","Figueiredo, Candido de","2","April 2, 2010","4","April","2010","7","text/html,text/plain; charset=utf-8,application/pdf,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","14.5","19.9","6.97","331402","7.2","55.91","4.800000000000001","16.5","3.1","-0.02525085152612697","0.5900803627681349","6.87","7.0","0.14","12051675","201302","243657","2952951.3","1753991" +"PR","en","Short stories, English;Humorous stories;Supernatural -- Fiction","Beasts and Super-Beasts","Text","1276","269","266","https://www.gutenberg.org/ebooks/269","1870","1916","Saki","26","December 26, 2011","12","December","2011","6","text/html,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","11.9","11.49","6.83","8800","8.3","69.11","9.600000000000001","10.5","3.1","0.07486095345227053","0.4851303000327079","4.96","19.0","0.05","305894","2222","3109","88214.4","61732" +"","en","","The History of Prostitution: Its Extent, Causes, and Effects throughout the World","Text","1267","41873","267","https://www.gutenberg.org/ebooks/41873","0","0","Sanger, William W.","19","January 19, 2013","1","January","2013","9","image/jpeg,text/html; charset=utf-8,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","15.4","13.64","6.14","24144","11.1","56.59","11.200000000000001","8.5","8.8","0.07605734599134142","0.4545027524696375","5.28","23.0","0.04","1471906","17359","11649","428318.1","278921" +"PQ","en","Science fiction;Earth (Planet) -- Core -- Fiction;Voyages, Imaginary -- Fiction;Adventure stories","A Journey to the Centre of the Earth","Text","1263","18857","268","https://www.gutenberg.org/ebooks/18857","1828","1905","Verne, Jules","18","July 18, 2006","7","July","2006","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","9.9","10.84","6.08","8965","7.2","72.16","8.4","13.0","3.1","0.09606430206735532","0.5413802061773928","4.9","16.0","0.06","419936","3084","5180","122377.5","85773" +"Z","en","Classification, Dewey decimal","A Classification and Subject Index for Cataloguing and Arranging the Books and Pamphlets of a Library","Text","1244","12513","269","https://www.gutenberg.org/ebooks/12513","1851","1931","Dewey, Melvil","4","June 4, 2004","6","June","2004","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","18.5","18.22","8.29","3518","9.5","66.07","10.8","12.0","11.2","0.06156291119883348","0.27628967891290523","6.07","22.0","0.04","94731","1577","687","22445.1","15596" +"HB","en","Sociology,Leisure class","The Theory of the Leisure Class","Text","1244","833","270","https://www.gutenberg.org/ebooks/833","1857","1929","Veblen, Thorstein","1","March, 1997","3","March","1997","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","20.2","13.94","6.51","8251","16.2","37.98","15.200000000000001","20.0","13.0","0.10655253893771062","0.4459527033941097","5.28","33.0","0.03","556401","9667","3144","173621.7","105351" +"PR","en","Great Britain -- History -- Richard I, 1189-1199 -- Fiction;Knights and knighthood -- Fiction;Normans -- Great Britain -- Fiction;Triangles (Interpersonal relations) -- Fiction;Ivanhoe, Wilfred of, Sir (Fictitious character) -- Fiction;Jews -- England -- Fiction;Anglo-Saxons -- Fiction;Historical fiction;Love stories","Ivanhoe: A Romance","Text","1241","82","271","https://www.gutenberg.org/ebooks/82","1771","1832","Scott, Walter","1","September, 1993","9","September","1993","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","15.5","11.84","6.53","18875","11.5","60.99","12.8","11.0","3.1","0.12264162039611225","0.5095732547210746","4.97","27.0","0.04","951286","5260","7062","268434.0","191430" +"PQ","en","France -- History -- Louis XI, 1461-1483 -- Fiction;Paris (France) -- History -- To 1515 -- Fiction;Historical fiction;People with disabilities -- Fiction;Clergy -- Fiction;Romances;Notre-Dame de Paris (Cathedral) -- Fiction","Notre-Dame De Paris","Text","1239","2610","272","https://www.gutenberg.org/ebooks/2610","1802","1885","Hugo, Victor","1","April, 2001","4","April","2001","8","application/rdf+xml,text/html; charset=iso-8859-1,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","10.9","11.13","6.08","18137","7.9","70.13","9.200000000000001","17.5","3.1","0.084776225813325","0.502663933543448","4.95","18.0","0.06","912590","5317","10206","258438.6","184390" +"DS","en","Rizal, José, 1861-1896","Lineage, Life and Labors of José Rizal, Philippine Patriot","Text","1239","6867","273","https://www.gutenberg.org/ebooks/6867","1872","0","Craig, Austin","18","June 18, 2004","6","June","2004","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","17.2","12.95","7.21","8484","13.4","50.5","13.600000000000001","15.5","8.8","0.11244464433621189","0.4365312973989081","5.11","29.0","0.03","320812","3307","2148","95508.9","62725" +"PR","en","Private investigators -- England -- Fiction;Detective and mystery stories;Holmes, Sherlock (Fictitious character) -- Fiction","The Valley of Fear","Text","1230","3289","274","https://www.gutenberg.org/ebooks/3289","1859","1930","Doyle, Arthur Conan","1","June, 2002","6","June","2002","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","7.4","8.98","5.91","5759","5.2","82.65","7.6000000000000005","8.0","3.1","0.08415965641929782","0.4874378667344549","4.63","14.0","0.07","266455","1051","4101","75433.5","57508" +"PR","en","Science fiction,Animal experimentation -- Fiction,Islands -- Fiction,Shipwreck survival -- Fiction","The Island of Doctor Moreau","Text","1229","159","275","https://www.gutenberg.org/ebooks/159","1866","1946","Wells, H. G. (Herbert George)","14","October 14, 2004","10","October","2004","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","8.8","9.97","6.27","5225","6.8","73.17","8.0","2.5","3.1","-0.010118738480413897","0.4619258573733183","4.75","15.0","0.06","206998","1263","2788","59257.8","43581" +"PZ,PR","en","Fantasy","Alice's Adventures in Wonderland: Illustrated by Arthur Rackham. With a Proem by Austin Dobson","Text","1229","28885","276","https://www.gutenberg.org/ebooks/28885","1832","1898","Carroll, Lewis","19","May 19, 2009","5","May","2009","9","image/jpeg,text/html; charset=iso-8859-1,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","9.5","9.74","5.95","2533","6.4","79.6","8.8","13.0","3.1","0.0367486157591331","0.49801070574772643","4.71","17.0","0.06","128331","384","1551","35064.9","27270" +"","en","","The Man Outside","Text","1218","51337","277","https://www.gutenberg.org/ebooks/51337","1922","2000","Smith, Evelyn E.","1","March 1, 2016","3","March","2016","7","image/jpeg,text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","9.1","11.19","7.0","1119","6.0","75.2","7.2","6.5","3.1","0.0943261471255169","0.5120225241611799","5.01","13.0","0.07","32572","207","469","9179.1","6497" +"PS","en","United States -- History -- French and Indian War, 1754-1763 -- Fiction;War stories;Adventure stories;Frontier and pioneer life -- Fiction;Mohegan Indians -- Fiction;Historical fiction;Bumppo, Natty (Fictitious character) -- Fiction","The Last of the Mohicans; A narrative of 1757","Text","1215","940","278","https://www.gutenberg.org/ebooks/940","1789","1851","Cooper, James Fenimore","5","February 5, 2006","2","February","2006","8","application/rdf+xml,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,text/plain","14.4","11.38","6.2","12382","10.7","63.02","12.0","15.0","3.1","0.07558948264222987","0.49052487327174726","4.89","25.0","0.04","725414","4168","5774","208991.7","148235" +"PZ,PQ","en","Fairy tales,Puppets -- Juvenile fiction,Pinocchio (Fictitious character) -- Juvenile fiction","The Adventures of Pinocchio","Text","1214","500","279","https://www.gutenberg.org/ebooks/500","1826","1890","Collodi, Carlo","12","January 12, 2006","1","January","2006","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","6.8","8.51","5.52","3129","4.8","83.66","7.2","5.0","3.1","0.06280612492679691","0.5228865898337258","4.6","13.0","0.08","183332","326","3032","50501.7","39863" +"PR","en","English essays -- 18th century -- Periodicals","The Spectator, Volumes 1, 2 and 3: With Translations and Index for the Series","Text","1207","12030","280","https://www.gutenberg.org/ebooks/12030","1672","1729","Steele, Richard, Sir","14","April 14, 2004","4","April","2004","9","text/html,text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","17.0","11.27","6.09","55817","13.0","56.93","14.4","5.5","8.8","0.15566740118694306","0.4995369247042093","4.82","31.0","0.03","4618241","31307","30491","1333590.3","957892" +"PR","en","Jungles -- Fiction;Jungle animals -- Fiction;Feral children -- Fiction;Mowgli (Fictitious character) -- Fiction;Adventure stories, English;Animals -- Fiction;Short stories;India -- Fiction","The Jungle Book","Text","1207","35997","281","https://www.gutenberg.org/ebooks/35997","1865","1936","Kipling, Rudyard","30","April 30, 2011","4","April","2011","9","image/jpeg,text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","9.3","9.28","5.99","4780","6.8","78.59","9.200000000000001","8.0","3.1","0.03561856774496861","0.45371558218819535","4.58","18.0","0.05","237540","582","2819","65060.1","51825" +"","en","","The Sense of Wonder","Text","1207","51296","282","https://www.gutenberg.org/ebooks/51296","1928","2008","Marlowe, Stephen","24","February 24, 2016","2","February","2016","8","text/plain,image/jpeg,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","7.4","9.85","6.35","792","4.4","84.68","6.800000000000001","6.5","3.1","0.03833900463090022","0.4922791244164875","4.83","12.0","0.08","28513","106","489","7807.5","5909" +"NK","en","Pottery -- Marks","China and Pottery Marks","Text","1201","40311","283","https://www.gutenberg.org/ebooks/40311","0","0","Unknown","24","July 24, 2012","7","July","2012","9","image/jpeg,text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","16.1","21.71","6.38","385","6.0","64.37","4.800000000000001","11.0","8.8","-0.02114583801435017","0.34728313785407117","7.13","7.0","0.13","18090","369","321","4016.7","2537" +"PA","en","Fables, Greek -- Translations into English","Aesop's Fables; a new translation","Text","1199","11339","284","https://www.gutenberg.org/ebooks/11339","0","0","Aesop","27","February 27, 2004","2","February","2004","8","application/rdf+xml,text/html; charset=iso-8859-1,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","12.3","8.71","6.31","3770","8.3","79.94","12.0","8.5","3.1","0.07334303530596177","0.48152178188586137","4.43","25.0","0.04","183612","414","1611","51365.7","41425" +"PS","en","Essays","Essays by Ralph Waldo Emerson","Text","1194","16643","285","https://www.gutenberg.org/ebooks/16643","1803","1882","Emerson, Ralph Waldo","4","September 4, 2005","9","September","2005","8","text/html; charset=utf-8,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","11.1","11.31","6.71","12787","7.9","70.13","9.200000000000001","12.0","3.1","0.16306423490518118","0.49218472083171266","4.98","18.0","0.06","461494","3622","5124","132345.0","92705" +"TT","en","Needlework","Encyclopedia of Needlework","Text","1194","20776","286","https://www.gutenberg.org/ebooks/20776","1846","1890","Dillmont, Therese de","8","March 8, 2007","3","March","2007","9","text/html,text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","11.4","10.33","1.59","5361","6.4","85.02","10.0","7.5","3.1","0.02161364065621227","0.31371803818752336","4.76","20.0","0.05","672756","3638","6801","170281.8","141340" +"PR","enm","Christian pilgrims and pilgrimages -- Poetry","Chaucer's Works, Volume 4 (of 7) — The Canterbury Tales","Text","1176","22120","287","https://www.gutenberg.org/ebooks/22120","1342","1400","Chaucer, Geoffrey","22","July 22, 2007","7","July","2007","7","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","10.6","9.23","5.91","18678","6.8","84.0","10.4","8.0","3.1","0.18497348414866827","0.5488428066768032","4.57","21.0","0.05","1091798","1824","11379","287482.5","239084" +"PS","en","Wolfdogs -- Fiction;Adventure stories;Canada, Northern -- Fiction","White Fang","Text","1174","910","288","https://www.gutenberg.org/ebooks/910","1876","1916","London, Jack","16","March 16, 2005","3","March","2005","7","text/html,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","8.4","9.68","5.89","6871","5.6","81.63","8.0","7.5","3.1","0.040974784782358054","0.42589159549627337","4.7","15.0","0.06","338321","1563","4671","95713.2","72017" +"PS","en","New England -- Social life and customs -- Fiction,Short stories","Mosses from an Old Manse, and Other Stories","Text","1173","512","289","https://www.gutenberg.org/ebooks/512","1804","1864","Hawthorne, Nathaniel","1","April, 1996","4","April","1996","7","text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","13.3","11.73","6.71","9154","9.5","66.07","10.8","27.5","3.1","0.11045508282054435","0.5242422135407493","4.95","22.0","0.04","361648","2522","3199","104785.2","73036" +"PR","en","Fathers and daughters -- Fiction,Psychological fiction,Wessex (England) -- Fiction,Runaway husbands -- Fiction,Atonement -- Fiction,Men -- England -- Fiction,Mayors -- Fiction","The Mayor of Casterbridge","Text","1172","143","290","https://www.gutenberg.org/ebooks/143","1840","1928","Hardy, Thomas","28","May 28, 2007","5","May","2007","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","10.5","10.67","6.17","12316","7.6","71.14","8.8","13.0","3.1","0.06879348474106606","0.46534209909513274","4.87","17.0","0.06","560649","3552","6411","158434.2","115151" +"PR","en","Shakespeare, William, 1564-1616 -- Tragedies","Shakespearean Tragedy: Lectures on Hamlet, Othello, King Lear, Macbeth","Text","1171","16966","291","https://www.gutenberg.org/ebooks/16966","1851","1935","Bradley, A. C. (Andrew Cecil)","30","October 30, 2005","10","October","2005","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","13.2","11.49","6.1","14305","9.9","65.05","11.200000000000001","3.5","3.1","0.06362006057823832","0.513339048685992","4.91","23.0","0.04","839782","6305","7435","240709.5","171017" +"PS","en","Poetry,Prose poems","The Waste Land","Text","1169","1321","292","https://www.gutenberg.org/ebooks/1321","1888","1965","Eliot, T. S. (Thomas Stearns)","1","January 1, 1922","1","January","1922","7","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","11.1","11.2","8.04","1039","6.8","78.59","9.200000000000001","10.5","3.1","0.01987178734374862","0.49213501137580956","4.91","18.0","0.05","22985","101","249","6204.6","4678" +"PS","en","Friendship -- Fiction,Married women -- Fiction,Women pioneers -- Fiction,Farmers' spouses -- Fiction,Farm life -- Fiction,Western stories,Women immigrants -- Fiction,Czech Americans -- Fiction,Frontier and pioneer life -- Nebraska -- Fiction,Nebraska -- Fiction,Domestic fiction","My Antonia","Text","1169","242","293","https://www.gutenberg.org/ebooks/242","1873","1947","Cather, Willa","8","July 8, 2008","7","July","2008","6","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","8.4","9.1","5.9","7589","6.0","80.62","8.4","5.5","3.1","0.07605388538849275","0.466176446459264","4.6","16.0","0.06","374190","1318","4997","106157.7","81320" +"PL","tl","Tagalog poetry","Florante at Laura","Text","1165","15845","294","https://www.gutenberg.org/ebooks/15845","1788","1862","Balagtas, Francisco","17","May 17, 2005","5","May","2005","6","text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","14.2","16.12","8.79","6128","9.5","55.24","8.4","10.5","8.8","0.3086806110869673","0.4090225563909774","5.81","16.0","0.06","129058","1946","1343","35552.7","22198" +"B,PA","en","Philosophy, Ancient;Classical literature;Socrates, 470 BC-399 BC","Apology","Text","1165","1656","295","https://www.gutenberg.org/ebooks/1656","-428","-348","Plato","1","February, 1999","2","February","1999","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","13.7","9.12","6.9","1963","11.5","60.99","12.8","19.5","3.1","0.10837310225616682","0.5558113494288605","4.5","27.0","0.04","72343","450","576","21857.4","16077" +"PS","en","New York (N.Y.) -- Fiction;Copyists -- Fiction;Psychological fiction;Young men -- Fiction;Wall Street (New York, N.Y.) -- Fiction","Bartleby, the Scrivener: A Story of Wall-Street","Text","1163","11231","296","https://www.gutenberg.org/ebooks/11231","1819","1891","Melville, Herman","23","February 23, 2004","2","February","2004","6","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","10.7","10.9","7.35","2562","7.9","70.13","9.200000000000001","8.5","3.1","0.05974530867100731","0.49403554766806235","4.91","18.0","0.06","70425","560","796","20652.3","14355" +"PR","en","Pastoral fiction,Wessex (England) -- Fiction,Women farmers -- Fiction,Triangles (Interpersonal relations) -- Fiction,Farm life -- Fiction,Didactic fiction,Love stories","Far from the Madding Crowd","Text","1158","27","297","https://www.gutenberg.org/ebooks/27","1840","1928","Hardy, Thomas","1","March, 1992","3","March","1992","6","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","9.6","10.26","5.95","13224","6.0","80.62","8.4","18.0","3.1","0.06816623574481934","0.4865844551989851","4.8","16.0","0.06","657644","3380","8184","184919.4","137083" +"DG","en","Rome -- History -- Empire, 30 B.C.-476 A.D.;Byzantine Empire -- History -- To 527","History of the Decline and Fall of the Roman Empire — Volume 1","Text","1156","731","298","https://www.gutenberg.org/ebooks/731","1737","1794","Gibbon, Edward","1","November, 1996","11","November","1996","6","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","15.4","13.41","6.16","22459","11.5","55.58","11.600000000000001","7.0","8.8","0.11860222130148845","0.48786011254339334","5.24","24.0","0.04","1390693","13966","10974","408169.8","265618" +"PG","en","Chekhov, Anton Pavlovich, 1860-1904 -- Translations into English;Russia -- Social life and customs -- Fiction","The Lady with the Dog and Other Stories","Text","1151","13415","299","https://www.gutenberg.org/ebooks/13415","1860","1904","Chekhov, Anton Pavlovich","9","September 9, 2004","9","September","2004","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","9.3","9.92","6.07","7396","7.2","72.16","8.4","26.0","3.1","0.05545967187335987","0.5228343797193173","4.74","16.0","0.06","338067","1872","4269","96430.5","71379" +"GR","en","Folklore -- Philippines,Tales -- Philippines","Filipino Popular Tales","Text","1151","8299","300","https://www.gutenberg.org/ebooks/8299","0","0","Unknown","1","June, 2005","6","June","2005","8","text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","8.7","9.57","5.57","14994","6.0","80.62","8.4","8.5","3.1","0.0880103108716048","0.4720872784443607","4.68","16.0","0.06","972186","4602","12825","274944.6","207843" +"DS","en","Jews -- Antiquities","Antiquities of the Jews","Text","1148","2848","301","https://www.gutenberg.org/ebooks/2848","37","0","Josephus, Flavius","1","October, 2001","10","October","2001","7","text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","24.7","10.58","2.98","20405","19.6","39.68","21.200000000000003","18.0","8.8","0.15380614620993593","0.4972428331904584","4.65","48.0","0.02","2498225","14605","11074","729858.6","536947" +"PR","en","Bombings -- Fiction,Political fiction,Conspiracies -- Fiction,Anarchists -- Fiction,London (England) -- Fiction","The Secret Agent: A Simple Tale","Text","1142","974","302","https://www.gutenberg.org/ebooks/974","1857","1924","Conrad, Joseph","24","December 24, 2010","12","December","2010","7","text/html,text/plain; charset=utf-8,text/plain; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.7","11.08","6.16","10187","6.8","73.17","8.0","5.5","3.1","0.03568356469375585","0.5063731482420389","4.94","15.0","0.06","445318","3617","5740","128408.4","90158" +"PS","en","Fantasy poetry, American","The Raven","Text","1140","17192","303","https://www.gutenberg.org/ebooks/17192","1809","1849","Poe, Edgar Allan","30","November 30, 2005","11","November","2005","9","image/jpeg,text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","14.2","12.94","8.11","1533","10.7","57.61","10.8","11.0","3.1","0.13777828630392389","0.5275976109730627","5.21","22.0","0.05","37227","231","323","10468.8","7148" +"PA","en","Classical literature;Trojan War;Achilles (Mythological character);Epic poetry, Greek -- Translations into English","The Iliad","Text","1134","2199","304","https://www.gutenberg.org/ebooks/2199","-750","-650","Homer","1","June, 2000","6","June","2000","6","text/html; charset=iso-8859-1,text/plain,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","15.2","9.24","6.05","8456","11.8","65.39","14.4","18.0","3.1","0.12809131481052888","0.519804399014607","4.47","31.0","0.03","682552","1629","4904","192713.4","152699" +"PS","en","Short stories;United States -- Social life and customs -- 19th century -- Fiction;Humorous stories, American","The Mysterious Stranger, and Other Stories","Text","1133","3186","305","https://www.gutenberg.org/ebooks/3186","1835","1910","Twain, Mark","19","August 19, 2006","8","August","2006","7","text/html; charset=iso-8859-1,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","10.1","9.17","6.38","4602","7.6","76.56","10.0","9.0","3.1","0.07524028612637071","0.5116949755219488","4.56","20.0","0.05","188854","873","2056","54099.9","41382" +"","en","","How?: or Spare Hours Made Profitable for Boys and Girls","Text","1131","51315","306","https://www.gutenberg.org/ebooks/51315","0","0","Holbrook, Kennedy","27","February 27, 2016","2","February","2016","7","image/jpeg,text/html; charset=utf-8,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","14.6","10.33","6.32","5698","10.3","69.45","12.8","9.0","3.1","0.09189102609489114","0.4404208886828862","4.71","27.0","0.04","314506","1765","2408","89484.3","66801" +"PR","en","Erotic stories","Laura Middleton; Her Brother and her Lover","Text","1129","28522","307","https://www.gutenberg.org/ebooks/28522","0","0","Anonymous","6","April 6, 2009","4","April","2009","6","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","18.8","10.17","6.86","2926","15.0","51.86","16.400000000000002","13.5","8.8","0.160562675869066","0.5318690291726138","4.63","36.0","0.03","148482","979","870","44698.5","32104" +"PR","en","Criticism;Aesthetics;Poetry;Wordsworth, William, 1770-1850. Lyrical ballads","Biographia Literaria","Text","1129","6081","308","https://www.gutenberg.org/ebooks/6081","1772","1834","Coleridge, Samuel Taylor","1","July, 2004","7","July","2004","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","18.2","12.72","7.13","17126","14.2","48.47","14.4","15.5","8.8","0.11540926757826953","0.4842520595107029","5.07","31.0","0.03","700675","7350","4385","206887.5","138336" +"E300","en","Women slaves -- United States -- Biography;Slaves -- United States -- Biography;Slaves -- United States -- Social conditions;Jacobs, Harriet A. (Harriet Ann), 1813-1897","Incidents in the Life of a Slave Girl, Written by Herself","Text","1128","11030","309","https://www.gutenberg.org/ebooks/11030","1813","1897","Jacobs, Harriet A. (Harriet Ann)","11","February 11, 2004","2","February","2004","6","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","7.8","8.47","5.71","6781","6.0","80.62","8.4","4.5","3.1","0.09729850502051798","0.5107809845694977","4.49","16.0","0.06","374348","1589","5135","108753.3","83341" +"PN","en","Authorship,Journalism","How To Write Special Feature Articles: A Handbook for Reporters, Correspondents and Free-Lance Writers Who Desire to Contribute to Popular Magazines and Magazine Sections of Newspapers","Text","1125","15718","310","https://www.gutenberg.org/ebooks/15718","1873","1935","Bleyer, Willard Grosvenor","26","April 26, 2005","4","April","2005","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","12.8","11.95","6.43","15250","10.3","58.62","10.4","19.0","3.1","0.12945763331266666","0.46347603067908005","5.04","21.0","0.05","693048","6028","6541","201474.0","137575" +"PR","en","England -- Fiction,Humorous stories,Men -- Societies and clubs -- Fiction,Male friendship -- Fiction","The Pickwick Papers","Text","1121","580","311","https://www.gutenberg.org/ebooks/580","1812","1870","Dickens, Charles","1","January 1, 1837","1","January","1837","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","10.5","11.66","5.7","24135","7.2","72.16","8.4","4.5","3.1","0.10054506751355326","0.48841086397126987","5.04","16.0","0.06","1506646","9763","18247","411440.4","299047" +"PS","en","New York (N.Y.) -- Fiction,Single women -- Fiction,Social classes -- Fiction,Psychological fiction","The House of Mirth","Text","1119","284","312","https://www.gutenberg.org/ebooks/284","1862","1937","Wharton, Edith","3","April 3, 2008","4","April","2008","6","text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","11.9","10.79","6.3","13251","9.1","67.08","10.4","13.0","3.1","0.06978121120194797","0.5056396235098439","4.84","21.0","0.05","625538","4426","6119","179807.4","129161" +"PZ,PS","en","Orphans -- Fiction,Boarding schools -- Fiction,Schools -- Fiction,London (England) -- Fiction","A Little Princess: Being the whole story of Sara Crewe now told for the first time","Text","1112","146","313","https://www.gutenberg.org/ebooks/146","1849","1924","Burnett, Frances Hodgson","19","June 19, 2008","6","June","2008","7","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","7.9","9.21","5.63","5469","5.2","82.65","7.6000000000000005","3.0","3.1","0.07477650317466629","0.5063926341433541","4.67","14.0","0.07","309635","1160","4500","86552.1","66353" +"","en","","My Lady Greensleeves","Text","1106","51310","314","https://www.gutenberg.org/ebooks/51310","1919","2013","Pohl, Frederik","27","February 27, 2016","2","February","2016","8","application/x-mobipocket-ebook,image/jpeg,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","8.2","10.66","6.58","2063","5.6","76.22","6.800000000000001","4.5","3.1","0.0404530057549288","0.46681358271358236","4.97","12.0","0.08","69042","370","1121","18801.9","13890" +"","en","","1000 Mythological Characters Briefly Described: Adapted to Private Schools, High Schools and Academies","Text","1102","42474","315","https://www.gutenberg.org/ebooks/42474","1840","1916","Ellis, Edward Sylvester","7","April 7, 2013","4","April","2013","8","image/jpeg,text/plain; charset=utf-8,text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","11.1","13.62","7.63","6551","7.2","66.74","7.2","8.0","3.1","-0.15786378686535849","0.6397977258008712","5.43","13.0","0.07","167669","1143","2213","46269.0","30889" +"PR","en","Women -- England -- Fiction,Male friendship -- Fiction,Psychological fiction,Sisters -- Fiction,Midlands (England) -- Fiction,Coal mines and mining -- Fiction,Love stories","Women in Love","Text","1098","4240","316","https://www.gutenberg.org/ebooks/4240","1885","1930","Lawrence, D. H. (David Herbert)","1","July, 2003","7","July","2003","6","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","7.7","10.25","5.61","15780","5.6","76.22","6.800000000000001","0.5","3.1","0.0718498892327872","0.5208034621532509","4.9","12.0","0.08","884117","4736","14825","245943.0","180343" +"PT","en","Springs -- Drama,Pollution -- Drama,Social conflict -- Drama,Physicians -- Drama,Norwegian drama -- Translations into English","An Enemy of the People","Text","1093","2446","317","https://www.gutenberg.org/ebooks/2446","1828","1906","Ibsen, Henrik","1","December, 2000","12","December","2000","6","text/html; charset=iso-8859-1,text/plain,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","7.3","9.9","5.86","3319","4.0","85.69","6.4","3.5","3.1","0.11729032660473698","0.512780573294827","4.89","11.0","0.09","152190","821","2712","41225.4","31150" +"BF","en","Palmistry","Palmistry for All","Text","1089","20480","318","https://www.gutenberg.org/ebooks/20480","1866","1936","Cheiro","29","January 29, 2007","1","January","2007","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","14.0","11.38","6.3","3941","10.3","64.04","11.600000000000001","14.5","8.8","0.11911904156438229","0.48233205936161605","4.89","24.0","0.04","205806","1809","1692","59923.8","42101" +"BT","en","Holy Spirit","The Person and Work of The Holy Spirit","Text","1088","30241","319","https://www.gutenberg.org/ebooks/30241","1856","1928","Torrey, R. A. (Reuben Archer)","13","October 13, 2009","10","October","2009","10","application/prs.tei,text/plain; charset=us-ascii,text/html; charset=utf-8,application/pdf,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","10.8","8.88","5.72","4617","8.3","74.53","10.8","4.5","3.1","0.1491216889532643","0.5002636852945848","4.46","22.0","0.04","327452","1551","3272","95688.9","73464" +"PG","en","Short stories, Russian -- Translations into English","Best Russian Short Stories","Text","1085","13437","320","https://www.gutenberg.org/ebooks/13437","0","0","Unknown","11","September 11, 2004","9","September","2004","6","text/html,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","9.1","10.44","6.1","10383","6.8","73.17","8.0","2.5","3.1","0.06874954584662465","0.5018998142095353","4.83","15.0","0.06","459617","2724","6133","130599.9","95148" +"PT","de","German poetry;Magicians -- Drama;Legends -- Germany -- Drama;Faust, -approximately 1540 -- Drama","Faust: Der Tragödie erster Teil","Text","1085","2229","321","https://www.gutenberg.org/ebooks/2229","1749","1832","Goethe, Johann Wolfgang von","1","June 2000","6","June","2000","7","text/html,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","10.6","13.96","6.87","5225","4.0","85.69","6.4","5.0","3.1","0.5609761143348707","0.7354651162790696","5.54","11.0","0.08","169792","747","2570","39503.7","30669" +"PR","en","Hannay, Richard (Fictitious character) -- Fiction;Intelligence service -- Great Britain -- Fiction;World War, 1914-1918 -- Fiction;Spy stories","The Thirty-Nine Steps","Text","1082","558","322","https://www.gutenberg.org/ebooks/558","1875","1940","Buchan, John","1","June, 1996","6","June","1996","6","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","7.4","8.12","6.12","4507","5.6","81.63","8.0","18.0","3.1","0.06759001817661223","0.44900228466331626","4.43","15.0","0.06","181287","647","2568","52222.5","40956" +"PE","en","English language -- Dictionaries","Webster's Unabridged Dictionary","Text","1076","29765","323","https://www.gutenberg.org/ebooks/29765","0","0","Various","22","August 22, 2009","8","August","2009","5","text/plain,application/rdf+xml,text/plain; charset=iso-8859-1,text/html,application/octet-stream","10.0","13.78","5.84","483557","6.0","69.79","6.0","9.0","3.1","-0.08536189058590178","0.5424716649048584","5.61","10.0","0.1","25029704","250291","443390","6532614.0","4462031" +"QA","en","Fourth dimension","Flatland: A Romance of Many Dimensions (Illustrated)","Text","1075","201","324","https://www.gutenberg.org/ebooks/201","1838","1926","Abbott, Edwin Abbott","10","March 10, 2008","3","March","2008","7","text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","15.8","11.9","7.33","5089","12.6","52.53","12.8","9.0","8.8","0.08774661716507914","0.46856625114593187","4.98","27.0","0.04","170145","1669","1243","49953.6","34135" +"PS","en","American essays","What Is Man? and Other Essays","Text","1073","70","325","https://www.gutenberg.org/ebooks/70","1835","1910","Twain, Mark","1","June, 1993","6","June","1993","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","10.7","10.73","6.51","11842","7.9","70.13","9.200000000000001","5.5","3.1","0.11194481365337598","0.48196108532252663","4.83","18.0","0.05","456403","3394","5013","132125.4","94409" +"PQ","en","Picaresque literature,Spain -- Social life and customs -- 16th century -- Fiction,Knights and knighthood -- Spain -- Fiction,Romances","The History of Don Quixote, Volume 1, Complete","Text","1071","5921","326","https://www.gutenberg.org/ebooks/5921","1547","1616","Cervantes Saavedra, Miguel de","19","July 19, 2004","7","July","2004","9","image/jpeg,text/html; charset=iso-8859-1,text/plain,application/octet-stream,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","24.9","10.0","7.13","14507","18.9","47.12","21.6","11.0","3.1","0.13778346735398547","0.522827214545546","4.55","49.0","0.02","981016","4194","4334","286760.7","215835" +"PR","en","Humorous stories;Valets -- Fiction;Jeeves (Fictitious character) -- Fiction;Wooster, Bertie (Fictitious character) -- Fiction;England -- Fiction;Single men -- Fiction","Right Ho, Jeeves","Text","1068","10554","327","https://www.gutenberg.org/ebooks/10554","1881","1975","Wodehouse, P. G. (Pelham Grenville)","29","June 29, 2007","6","June","2007","8","application/rdf+xml,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,text/plain","7.5","9.27","5.91","7596","4.8","83.66","7.2","4.0","3.1","0.09258285944731819","0.5062026787677315","4.73","13.0","0.08","349241","1540","5578","97176.6","73797" +"","en","","Dr. Kometevsky's Day","Text","1066","51353","328","https://www.gutenberg.org/ebooks/51353","1910","1992","Leiber, Fritz","5","March 5, 2016","3","March","2016","7","application/x-mobipocket-ebook,image/jpeg,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","9.6","12.0","7.49","1367","6.0","75.2","7.2","4.5","3.1","0.038589073041804166","0.4696161662800317","5.15","13.0","0.07","34655","235","497","9725.4","6735" +"PS","en","Short stories, American","The Best American Humorous Short Stories","Text","1064","10947","329","https://www.gutenberg.org/ebooks/10947","0","0","Unknown","5","February 5, 2004","2","February","2004","7","text/html,text/plain; charset=us-ascii,text/plain,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","10.9","11.02","6.53","13272","7.9","70.13","9.200000000000001","15.0","3.1","0.11279698175414732","0.4890597461538432","4.93","18.0","0.06","515461","3175","5766","144854.1","104548" +"PR","en","Fathers and daughters -- Fiction,Foundlings -- Fiction,Adopted children -- Fiction,England -- Fiction,Domestic fiction,Weavers -- Fiction","Silas Marner","Text","1064","550","330","https://www.gutenberg.org/ebooks/550","1819","1880","Eliot, George","1","June, 1996","6","June","1996","7","text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","13.7","10.39","6.53","7423","9.5","71.48","12.0","27.5","3.1","0.08373678519650052","0.5023458398971745","4.72","25.0","0.04","334752","1745","2741","94788.0","70933" +"PR","en","Vampires -- Fiction,Horror tales,Gothic fiction (Literary genre)","The Vampyre; a Tale","Text","1060","6087","331","https://www.gutenberg.org/ebooks/6087","1795","1821","Polidori, John William","1","July, 2004","7","July","2004","8","application/rdf+xml,text/plain; charset=us-ascii,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","18.8","12.08","8.12","2278","13.8","54.9","15.200000000000001","11.0","8.8","0.08831472274831635","0.4516386596620959","4.96","33.0","0.03","62700","402","374","18044.1","12630" +"QC","en","Relativity (Physics)","Relativity : the Special and General Theory","Text","1053","5001","332","https://www.gutenberg.org/ebooks/5001","1879","1955","Einstein, Albert","1","February, 2004","2","February","2004","9","text/plain; charset=us-ascii,text/plain,application/prs.tex,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/msword","15.2","12.89","6.32","2945","11.5","55.58","11.600000000000001","7.0","8.8","0.09639077525351036","0.4325514590953004","5.15","24.0","0.04","160050","2331","1255","48009.6","31082" +"N","en","Bible -- Illustrations","The Doré Bible Gallery, Complete: Containing One Hundred Superb Illustrations, and a Page of Explanatory Letter-press Facing Each","Text","1052","8710","333","https://www.gutenberg.org/ebooks/8710","0","0","Unknown","29","July 29, 2004","7","July","2004","8","image/jpeg,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","11.2","9.12","6.16","3233","8.3","74.53","10.8","21.0","3.1","0.12545744620978788","0.4967385245078443","4.5","22.0","0.04","159818","471","1550","44600.4","35550" +"PE","en","Readers","The Literary World Seventh Reader","Text","1047","19721","334","https://www.gutenberg.org/ebooks/19721","0","0","Unknown","5","November 5, 2006","11","November","2006","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","10.3","10.38","6.35","11980","6.8","78.59","9.200000000000001","7.5","3.1","0.09076966665634571","0.49300255005484767","4.82","18.0","0.06","500270","2166","5752","139997.7","103797" +"PR","en","Brown, Father (Fictitious character) -- Fiction;Clergy -- Fiction;Detective and mystery stories, English;Catholics -- Fiction;England -- Fiction","The Innocence of Father Brown","Text","1045","204","335","https://www.gutenberg.org/ebooks/204","1874","1936","Chesterton, G. K. (Gilbert Keith)","6","July 6, 2008","7","July","2008","8","text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","10.1","10.09","6.26","8649","7.9","70.13","9.200000000000001","26.5","3.1","0.029712275917699444","0.4726520962278449","4.77","18.0","0.06","376454","1817","4360","106863.3","78911" +"","en","","Electricity in Locomotion: An Account of its Mechanism, its Achievements, and its Prospects","Text","1039","51242","336","https://www.gutenberg.org/ebooks/51242","0","0","Whyte, Adam Gowens","17","February 17, 2016","2","February","2016","9","image/jpeg,text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","15.9","13.64","6.86","3664","12.7","47.12","11.600000000000001","6.0","8.8","0.11069298469972555","0.437124009701383","5.28","24.0","0.04","150549","1815","1147","44599.5","28499" +"PR","en","Irish -- India -- Fiction,Orphans -- Fiction,Lamas -- Fiction,Spy stories,Adventure stories,India -- Fiction,Boys -- Fiction","Kim","Text","1038","2226","337","https://www.gutenberg.org/ebooks/2226","1865","1936","Kipling, Rudyard","1","June, 2000","6","June","2000","7","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","7.7","9.62","6.11","12129","4.8","83.66","7.2","8.0","3.1","0.08105523087833792","0.4738148455612688","4.74","13.0","0.07","495285","2302","7728","138516.3","104478" +"PR,PZ","en","Tales -- Ireland,Fairy tales -- Ireland,Folklore -- Ireland","Irish Fairy Tales","Text","1036","2892","338","https://www.gutenberg.org/ebooks/2892","1882","1950","Stephens, James","1","November, 2001","11","November","2001","8","image/jpeg,text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.7","8.99","5.96","5780","7.2","77.57","9.600000000000001","25.5","3.1","0.1080084190387074","0.5144038148594674","4.53","19.0","0.05","299402","818","3358","82687.5","66088" +"E300","en","African American abolitionists -- Biography;Abolitionists -- United States -- Biography;Slaves -- Maryland -- Social conditions -- 19th century;Douglass, Frederick, 1818-1895;Antislavery movements -- United States -- History -- 19th century;Fugitive slaves -- Maryland -- Biography;Plantation life -- Maryland -- History -- 19th century","My Bondage and My Freedom","Text","1034","202","339","https://www.gutenberg.org/ebooks/202","1818","1895","Douglass, Frederick","1","July 1, 2008","7","July","2008","6","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","13.2","11.2","6.45","14212","9.9","65.05","11.200000000000001","29.5","3.1","0.09943919395504423","0.5011155288961125","4.86","23.0","0.04","652807","5092","5720","190790.1","134341" +"G","en","Oceania -- Discovery and exploration -- Early works to 1800,Voyages around the world -- Early works to 1800","Captain Cook's Journal During His First Voyage Round the World: Made in H. M. Bark ""Endeavour"", 1768-71","Text","1020","8106","340","https://www.gutenberg.org/ebooks/8106","1728","1779","Cook, James","1","May, 2005","5","May","2005","7","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","12.7","10.1","5.63","11861","9.1","72.5","11.600000000000001","4.0","3.1","0.10351838588014078","0.44706436750864664","4.67","24.0","0.04","1090534","3906","9610","301006.8","233349" +"PR,PZ","en","Great Britain -- History -- 19th century -- Juvenile fiction,Horses -- Juvenile fiction,Historical fiction","Black Beauty","Text","1015","271","341","https://www.gutenberg.org/ebooks/271","1820","1878","Sewell, Anna","16","January 16, 2006","1","January","2006","6","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","10.7","7.61","5.81","3729","7.9","80.96","11.600000000000001","8.0","3.1","0.10701407224946122","0.5192875159176481","4.24","24.0","0.04","254175","393","2472","72267.3","59959" +"PR","en","Grief;Wilde, Oscar, 1854-1900;Suffering;Imprisonment","De Profundis","Text","1012","921","342","https://www.gutenberg.org/ebooks/921","1854","1900","Wilde, Oscar","13","April 13, 2007","4","April","2007","7","text/html,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","11.3","8.83","6.75","2212","8.7","73.51","11.200000000000001","4.5","3.1","0.10788883181705405","0.546237951501623","4.45","23.0","0.04","78829","419","754","23687.1","17718" +"JC","en","Natural law,Equality,Political science","A Discourse Upon the Origin and the Foundation of the Inequality Among Mankind","Text","1008","11136","343","https://www.gutenberg.org/ebooks/11136","1712","1778","Rousseau, Jean-Jacques","17","February 17, 2004","2","February","2004","6","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","28.2","12.14","8.36","3560","22.8","26.14","23.200000000000003","14.5","11.2","0.10339204645113866","0.48365546047002494","4.92","53.0","0.02","131967","1203","506","39888.9","26821" +"PQ","en","Middle class -- France -- Drama,French drama,Comedies,France -- Social life and customs -- 17th century -- Drama","The Middle-Class Gentleman","Text","1007","2992","344","https://www.gutenberg.org/ebooks/2992","1622","1673","Moliere","1","October, 2001","10","October","2001","7","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","8.2","11.01","5.85","1929","5.2","77.23","6.4","5.0","3.1","0.18433399020363925","0.581906865513003","5.03","11.0","0.08","91982","406","1544","25334.1","18301" +"PR","en","London (England) -- Drama,English drama (Comedy),City and town life -- Drama,Alchemists -- Drama,English drama -- 17th century","The Alchemist","Text","1002","4081","345","https://www.gutenberg.org/ebooks/4081","0","1637","Jonson, Ben","1","May, 2003","5","May","2003","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","9.3","12.16","7.13","9000","5.2","77.23","6.4","18.5","3.1","0.14598318410409508","0.4970559963001308","5.28","11.0","0.09","254512","1273","4121","66674.7","48213" +"PQ","en","Hugo, Victor, 1802-1885 -- Translations into English;French poetry -- Translations into English","Poems","Text","1002","8775","346","https://www.gutenberg.org/ebooks/8775","1802","1885","Hugo, Victor","1","August, 2005","8","August","2005","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","12.2","12.42","7.0","10693","7.2","77.57","9.600000000000001","6.5","3.1","0.10597983125329782","0.5263552883380023","5.12","19.0","0.05","357199","885","3660","91592.1","69815" +"PR","en","English poetry -- 18th century","The Rape of the Lock and Other Poems","Text","999","9800","347","https://www.gutenberg.org/ebooks/9800","1688","1744","Pope, Alexander","1","January, 2006","1","January","2006","7","application/rdf+xml,text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/epub+zip,text/html; charset=iso-8859-1,text/plain","12.9","11.66","6.87","7778","9.1","67.08","10.4","14.0","3.1","0.13586331878703498","0.5031111105525902","4.99","21.0","0.05","280108","1385","2586","76016.7","56089" +"PZ,PA","en","Aesop's fables -- Translations into English;Fables, Greek -- Translations into English","Aesop's Fables: Translated by George Fyler Townsend","Text","997","21","348","https://www.gutenberg.org/ebooks/21","0","0","Aesop","30","September 30, 1991","9","September","1991","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","11.7","9.99","6.6","4853","8.3","74.53","10.8","7.5","3.1","0.11750359171036515","0.4975892471337252","4.65","22.0","0.04","189827","786","1819","53886.6","40858" +"JK","en","United States -- Social conditions,Democracy -- United States,United States -- Politics and government","Democracy in America — Volume 2","Text","993","816","349","https://www.gutenberg.org/ebooks/816","1805","1859","Tocqueville, Alexis de","21","January 21, 2006","1","January","2006","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","19.1","12.78","6.55","11376","15.0","46.44","15.200000000000001","16.0","11.2","0.11175851938104533","0.46452644022193973","5.08","33.0","0.03","717199","9387","4258","218592.9","141230" +"HV","en","Deafblind women -- United States -- Biography;Keller, Helen, 1880-1968","The Story of My Life: With her letters (1887-1901) and a supplementary account of her education, including passages from the reports and letters of her teacher, Anne Mansfield Sullivan, by John Albert Macy","Text","989","2397","350","https://www.gutenberg.org/ebooks/2397","1880","1968","Keller, Helen","1","November, 2000","11","November","2000","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","10.0","9.57","5.84","10771","7.2","77.57","9.600000000000001","18.0","3.1","0.17538995591267553","0.5396989069219378","4.63","19.0","0.05","624528","3527","6994","180720.0","134869" +"PR","en","Comedies","She Stoops to Conquer; Or, The Mistakes of a Night: A Comedy","Text","988","383","351","https://www.gutenberg.org/ebooks/383","0","1774","Goldsmith, Oliver","1","December, 1995","12","December","1995","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","7.4","9.85","6.13","2737","4.4","84.68","6.800000000000001","8.0","3.1","0.14565000541542986","0.5317945397538879","4.83","12.0","0.08","110171","376","1871","30429.0","22805" +"PR","en","Historical fiction;France -- History -- Revolution, 1789-1799 -- Fiction;Nobility -- Fiction;Adventure stories;Blakeney, Percy, Sir (Fictitious character) -- Fiction;British -- France -- Fiction","The Scarlet Pimpernel","Text","988","60","352","https://www.gutenberg.org/ebooks/60","1865","1947","Orczy, Emmuska Orczy, Baroness","7","March 7, 2006","3","March","2006","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","11.6","11.49","6.16","8425","8.3","69.11","9.600000000000001","1.5","3.1","0.09233666280237579","0.5176193894861666","4.96","19.0","0.05","416695","2214","4353","116586.9","84030" +"PQ","en","Prose poems,French poetry -- Translations into English","The Poems and Prose Poems of Charles Baudelaire: with an Introductory Preface by James Huneker","Text","987","36287","353","https://www.gutenberg.org/ebooks/36287","1821","1867","Baudelaire, Charles","31","May 31, 2011","5","May","2011","8","text/plain; charset=utf-8,text/plain; charset=us-ascii,text/html; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","13.6","12.36","7.75","5382","9.5","66.07","10.8","19.0","3.1","0.08681012712056248","0.5483732467413325","5.06","22.0","0.04","142096","956","1254","40036.5","28092" +"PR","en","Poetry","The Rime of the Ancient Mariner","Text","985","151","354","https://www.gutenberg.org/ebooks/151","1772","1834","Coleridge, Samuel Taylor","11","March 11, 2006","3","March","2006","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.0","9.51","6.26","448","4.8","89.08","8.4","5.0","3.1","0.096550649947479","0.4777228057889828","4.67","16.0","0.06","17990","10","229","4604.4","3856" +"E151","en","Frontier and pioneer life -- United States,Frontier thesis,United States -- History,United States -- Territorial expansion","The Frontier in American History","Text","985","22994","355","https://www.gutenberg.org/ebooks/22994","1861","1932","Turner, Frederick Jackson","14","October 14, 2007","10","October","2007","9","image/jpeg,text/html; charset=iso-8859-1,text/plain,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","16.8","13.76","6.49","11574","12.3","53.55","12.4","5.0","8.8","0.12087840782587586","0.3900528202990615","5.3","26.0","0.04","620157","7611","4418","176262.3","116906" +"PS","en","Ship captains -- Fiction;Whaling ships -- Fiction;Psychological fiction;Whaling -- Fiction;Whales -- Fiction;Mentally ill -- Fiction;Sea stories;Adventure stories;Ahab, Captain (Fictitious character) -- Fiction","Moby Dick","Text","984","15","356","https://www.gutenberg.org/ebooks/15","1819","1891","Melville, Herman","1","May, 1991","5","May","1991","7","text/html,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","10.0","13.84","9.25","498","4.4","79.26","5.6000000000000005","7.5","3.1","0.10639526710403","0.42057258892310434","5.62","9.0","0.1","8565","36","154","2185.2","1523" +"PT","de","Germany -- Fiction,Domestic fiction,Families -- Fiction","Buddenbrooks: Verfall einer Familie","Text","984","34811","357","https://www.gutenberg.org/ebooks/34811","1875","1955","Mann, Thomas","1","January 1, 2011","1","January","2011","8","image/jpeg,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/octet-stream,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","14.7","16.12","6.55","30165","8.7","62.68","8.8","6.0","3.1","0.1653038137971359","0.3603634443763195","5.81","17.0","0.06","1336902","9677","13140","346267.8","230016" +"PS","en","Older women -- Fiction,Short stories,Space flight -- Fiction,Swindlers and swindling -- Fiction,Science fiction","A Little Journey","Text","984","51171","358","https://www.gutenberg.org/ebooks/51171","1920","2012","Bradbury, Ray","10","February 10, 2016","2","February","2016","8","application/x-mobipocket-ebook,image/jpeg,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","8.0","10.31","6.95","441","4.4","84.68","6.800000000000001","5.0","3.1","0.04430359885508848","0.47773891911197613","4.91","12.0","0.08","12577","54","204","3389.4","2561" +"PR","en","Married women -- Fiction;Social classes -- Fiction;Satire;Waterloo, Battle of, Waterloo, Belgium, 1815 -- Fiction;England -- Fiction;Female friendship -- Fiction;British -- Europe -- Fiction","Vanity Fair","Text","984","599","359","https://www.gutenberg.org/ebooks/599","1811","1863","Thackeray, William Makepeace","1","July, 1996","7","July","1996","7","text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","12.1","10.79","5.93","23910","9.1","67.08","10.4","17.5","3.1","0.12641028548623423","0.5107735916392266","4.84","21.0","0.05","1462802","8015","14050","415761.3","302346" +"","en","","Birds of a Feather","Text","979","51361","360","https://www.gutenberg.org/ebooks/51361","1935","0","Silverberg, Robert","5","March 5, 2016","3","March","2016","8","image/jpeg,text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","8.0","10.25","6.99","1343","5.6","76.22","6.800000000000001","8.0","3.1","0.053715225023818786","0.47401990993337134","4.9","12.0","0.08","37623","206","605","10596.6","7678" +"BP","en","Yogananda, Paramahansa, 1893-1952;Yogis -- India -- Biography","Autobiography of a Yogi","Text","975","7452","361","https://www.gutenberg.org/ebooks/7452","1893","1952","Yogananda, Paramahansa","1","February, 2005","2","February","2005","7","text/html; charset=utf-8,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","10.8","12.35","6.36","19407","8.0","64.71","8.0","4.0","3.1","0.12057506131074744","0.4782454061984216","5.21","15.0","0.07","808031","7872","10140","235272.6","155018" +"","en","","Nine Thousand Miles On A Pullman Train: An Account of a Tour of Railroad Conductors From; Philadelphia to the Pacific Coast an Return","Text","969","51341","362","https://www.gutenberg.org/ebooks/51341","0","0","Shaw, Milton","2","March 2, 2016","3","March","2016","7","image/jpeg,text/html; charset=utf-8,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","10.5","10.39","6.21","6754","7.9","70.13","9.200000000000001","7.0","3.1","0.18467489934959888","0.4962734764046626","4.77","18.0","0.05","302305","1822","3356","85837.5","63347" +"BF","en","Psychoanalysis,Dreams","Dream Psychology: Psychoanalysis for Beginners","Text","957","15489","363","https://www.gutenberg.org/ebooks/15489","1856","1939","Freud, Sigmund","28","March 28, 2005","3","March","2005","8","application/rdf+xml,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,text/plain","15.5","12.77","6.69","6155","11.9","54.56","12.0","5.0","8.8","0.0828051457866595","0.48447739343337887","5.13","25.0","0.04","275214","3444","2110","81594.9","53679" +"","en","","The Pilot and the Bushman","Text","957","51297","364","https://www.gutenberg.org/ebooks/51297","0","0","Jacobs, Sylvia","1","March 1, 2016","3","March","2016","8","text/plain,image/jpeg,text/html; charset=us-ascii,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","10.4","12.0","7.43","1769","8.0","64.71","8.0","9.0","3.1","0.11002100816045149","0.5149654990201206","5.15","15.0","0.07","47170","494","608","13597.2","9164" +"PZ","en","Shakespeare, William, 1564-1616 -- Stories, plots, etc. -- Juvenile literature;Children's literature","Beautiful Stories from Shakespeare","Text","951","1430","365","https://www.gutenberg.org/ebooks/1430","1564","1616","Shakespeare, William","1","August, 1998","8","August","1998","7","text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","10.3","10.61","6.27","5450","6.4","79.6","8.8","8.0","3.1","0.1375968550168044","0.546973536601522","4.86","17.0","0.06","233490","681","2715","63808.2","48038" +"PS","en","Fantasy fiction;American fiction -- 19th century;Horror tales, American","The Works of Edgar Allan Poe — Volume 3","Text","951","2149","366","https://www.gutenberg.org/ebooks/2149","1809","1849","Poe, Edgar Allan","19","May 19, 2008","5","May","2008","7","text/html; charset=iso-8859-1,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","14.7","11.32","6.62","10702","11.1","62.01","12.4","13.0","8.8","0.08848121633989088","0.5002761118763605","4.88","26.0","0.04","485441","3867","3796","143368.2","99566" +"PS","en","Psychological fiction,Europe -- Fiction,Young women -- Fiction,Americans -- Europe -- Fiction","Daisy Miller: A Study","Text","949","208","367","https://www.gutenberg.org/ebooks/208","1843","1916","James, Henry","3","July 3, 2008","7","July","2008","6","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","8.4","10.54","6.34","2777","6.0","75.2","7.2","14.5","3.1","0.13000783947752403","0.5202650994091933","4.95","13.0","0.08","105557","676","1623","29865.6","21312" +"PR,PZ","en","Fantasy,Peter Pan (Fictitious character) -- Fiction,Never-Never Land (Imaginary place) -- Fiction,Fairies -- Juvenile fiction,Pirates -- Juvenile fiction","Peter and Wendy","Text","949","26654","368","https://www.gutenberg.org/ebooks/26654","1860","1937","Barrie, J. M. (James Matthew)","18","September 18, 2008","9","September","2008","8","application/rdf+xml,image/jpeg,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,text/plain","8.2","9.34","5.9","4545","5.6","81.63","8.0","11.0","3.1","0.08954772333414131","0.5240553094751901","4.64","15.0","0.06","219593","692","3047","60228.9","47325" +"E660","en","Grant, Ulysses S. (Ulysses Simpson), 1822-1885;Presidents -- United States -- Biography;Generals -- United States -- Biography;United States. Army -- Biography;United States -- History -- Civil War, 1861-1865 -- Campaigns;Mexican War, 1846-1848 -- Personal narratives","Personal Memoirs of U. S. Grant, Complete","Text","949","4367","369","https://www.gutenberg.org/ebooks/4367","1822","1885","Grant, Ulysses S. (Ulysses Simpson)","16","August 16, 2006","8","August","2006","9","text/plain,image/jpeg,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/pdf","13.0","11.44","5.53","14223","9.5","66.07","10.8","6.0","3.1","0.07878164089272072","0.4273312007153737","4.9","22.0","0.04","1376193","9894","12346","402946.2","280935" +"","en","","Trial of the Major War Criminals Before the International Military Tribunal, Vol. I: Nuremburg 14 November 1945-1 October 1946: Vol. I","Text","949","51292","370","https://www.gutenberg.org/ebooks/51292","0","0","Various","24","February 24, 2016","2","February","2016","7","image/jpeg,text/plain; charset=utf-8,text/html; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","17.6","14.28","6.24","11158","13.8","44.07","12.8","31.0","8.8","0.031518454567897196","0.3765081430269629","5.39","27.0","0.04","753801","10012","5107","219529.8","139743" +"BS","en","Blacks in the Bible;Theological anthropology;Civilization, Ancient","The Black Man, the Father of Civilization, Proven by Biblical History","Text","947","39509","371","https://www.gutenberg.org/ebooks/39509","0","0","Webb, James Morris","22","April 22, 2012","4","April","2012","6","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","15.3","11.49","7.78","1658","11.5","60.99","12.8","7.0","8.8","0.13208033947724665","0.4554124226289178","4.91","27.0","0.04","45911","348","344","13203.0","9348" +"","en","","The Autobiography of a Super-Tramp","Text","947","51425","372","https://www.gutenberg.org/ebooks/51425","1871","1940","Davies, W. H. (William Henry)","11","March 11, 2016","3","March","2016","8","image/jpeg,text/html; charset=iso-8859-1,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","13.8","9.93","6.3","7548","11.1","62.01","12.4","14.5","3.1","0.07802459050248126","0.4474442367001751","4.64","26.0","0.04","402904","1987","3241","117391.5","86874" +"","en","","The Enchiridion","Text","944","45109","373","https://www.gutenberg.org/ebooks/45109","55","135","Epictetus","10","March 10, 2014","3","March","2014","9","image/jpeg,text/plain; charset=utf-8,text/plain; charset=us-ascii,text/html; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","11.3","11.6","7.45","2041","7.9","70.13","9.200000000000001","15.0","3.1","0.10928208162517802","0.5158004331016884","5.03","18.0","0.06","55597","542","610","15549.3","11053" +"D501","en","World War, 1914-1918","History of the World War: An Authentic Narrative of the World's Greatest War","Text","935","18993","374","https://www.gutenberg.org/ebooks/18993","1863","1928","March, Francis Andrew","6","August 6, 2006","8","August","2006","9","text/plain,text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,application/pdf,application/msword","13.9","13.17","6.0","19904","10.3","58.62","10.4","7.0","8.8","0.09454928377038428","0.38935255097737964","5.25","21.0","0.05","1245446","11880","11208","359290.8","237058" +"","en","","Confidence Game","Text","932","51305","375","https://www.gutenberg.org/ebooks/51305","1933","2010","Harmon, Jim","26","February 26, 2016","2","February","2016","8","application/x-mobipocket-ebook,image/jpeg,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","6.6","9.03","6.75","846","4.0","85.69","6.4","6.5","3.1","0.02670779532967033","0.4648615308302809","4.74","11.0","0.09","24701","116","460","6845.4","5210" +"PR","en","De Quincey, Thomas, 1785-1859;Drug addicts -- Great Britain -- Biography;Authors, English -- 19th century -- Biography;Opium abuse -- England","Confessions of an English Opium-Eater","Text","929","2040","376","https://www.gutenberg.org/ebooks/2040","1785","1859","De Quincey, Thomas","20","April 20, 2005","4","April","2005","7","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","18.6","11.21","7.69","5782","14.2","53.89","15.600000000000001","11.5","8.8","0.09752289806846351","0.48110214997086537","4.81","34.0","0.03","185922","1670","1115","55575.9","38637" +"B","en","Philosophy, German;Christianity -- Controversial literature","The Antichrist","Text","928","19322","377","https://www.gutenberg.org/ebooks/19322","1844","1900","Nietzsche, Friedrich Wilhelm","18","September 18, 2006","9","September","2006","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","15.2","13.23","7.61","5939","11.5","55.58","11.600000000000001","5.5","8.8","0.10424381463443942","0.5129496238116953","5.21","24.0","0.04","175159","2041","1394","50769.9","33638" +"D","en","World history","A Short History of the World","Text","928","35461","378","https://www.gutenberg.org/ebooks/35461","1866","1946","Wells, H. G. (Herbert George)","2","March 2, 2011","3","March","2011","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","14.4","13.41","6.54","13485","10.7","57.61","10.8","8.5","8.8","0.11795228016868387","0.43259997777739395","5.24","22.0","0.04","616160","6262","5260","174207.6","117534" +"PQ","en","Musical fiction,Paris (France) -- Fiction,Opera -- Fiction,Phantom of the Opera (Fictitious character) -- Fiction,French fiction -- Translations into English,Composers -- Fiction,Horror tales","The Phantom of the Opera","Text","926","175","379","https://www.gutenberg.org/ebooks/175","1868","1927","Leroux, Gaston","9","June 9, 2008","6","June","2008","7","text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","8.3","9.79","5.76","7684","5.2","82.65","7.6000000000000005","26.5","3.1","0.05682078068982149","0.5060762199923734","4.77","14.0","0.07","403759","1921","5871","113266.8","84705" +"HQ","en","Sex","Three Contributions to the Theory of Sex","Text","924","14969","380","https://www.gutenberg.org/ebooks/14969","1856","1939","Freud, Sigmund","8","February 8, 2005","2","February","2005","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","19.0","15.21","7.09","5373","14.6","42.04","13.600000000000001","4.5","11.2","0.15904700838120972","0.5382599164868461","5.5","29.0","0.03","231813","3974","1453","69130.8","42156" +"BL","en","Religion;Conversion;Experience (Religion);Philosophy and religion;Psychology, Religious","The Varieties of Religious Experience: A Study in Human Nature","Text","923","621","381","https://www.gutenberg.org/ebooks/621","1842","1910","James, William","17","October 17, 2014","10","October","2014","12","application/x-mobipocket-ebook,image/jpeg,application/prs.tei,text/plain; charset=us-ascii,application/octet-stream,text/plain,text/html; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/pdf","14.0","11.96","6.34","18412","11.1","56.59","11.200000000000001","4.0","8.8","0.10975933930564875","0.4921263871651123","4.99","23.0","0.04","929918","9535","7780","273070.8","186250" +"PR","en","Africa -- Fiction,Women -- Africa -- Fiction,Fantasy fiction,Immortalism -- Fiction,Adventure stories,Reincarnation -- Fiction,Ayesha (Fictitious character : Haggard) -- Fiction,Love stories","She","Text","922","3155","382","https://www.gutenberg.org/ebooks/3155","1856","1925","Haggard, H. Rider (Henry Rider)","4","April 4, 2006","4","April","2006","8","text/html; charset=utf-8,text/plain; charset=us-ascii,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","15.9","12.02","6.22","9959","11.5","60.99","12.8","11.0","3.1","0.012533442298978128","0.47879558784886855","5.0","27.0","0.04","631201","3592","4590","176938.2","126264" +"PE","en","English language -- Slang -- Dictionaries","1811 Dictionary of the Vulgar Tongue","Text","921","5402","383","https://www.gutenberg.org/ebooks/5402","0","1791","Grose, Francis","1","April, 2004","4","April","2004","6","text/html,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.1","11.42","6.83","13046","6.0","75.2","7.2","5.5","3.1","0.018355114945802303","0.4714487429287797","5.05","13.0","0.07","408958","2100","5967","112461.3","80975" +"PS","en","American poetry","Poems by Emily Dickinson, Three Series, Complete","Text","920","12242","384","https://www.gutenberg.org/ebooks/12242","1830","1886","Dickinson, Emily","3","May 3, 2004","5","May","2004","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","12.7","12.82","7.05","4825","7.2","77.57","9.600000000000001","11.5","3.1","0.09212924390536957","0.49638022990566893","5.19","19.0","0.05","159828","580","1588","40637.7","30811" +"PS","en","Poetry","Poems","Text","920","1567","385","https://www.gutenberg.org/ebooks/1567","1888","1965","Eliot, T. S. (Thomas Stearns)","1","December, 1998","12","December","1998","6","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","12.3","12.18","8.02","1430","8.3","69.11","9.600000000000001","8.0","3.1","0.018114352122972802","0.47051130861475693","5.08","19.0","0.05","33384","151","335","8972.1","6569" +"PR","en","Heroes,Hero worship","On Heroes, Hero-Worship, and the Heroic in History","Text","919","1091","386","https://www.gutenberg.org/ebooks/1091","1795","1881","Carlyle, Thomas","1","November, 1997","11","November","1997","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","12.4","10.79","6.72","11147","9.5","66.07","10.8","7.5","3.1","0.14599610857126588","0.5269256460099341","4.84","22.0","0.05","428353","3510","4005","124110.9","88521" +"DS,PL","tl","Rizal, José, 1861-1896 -- Correspondence","Ang Liham ni Dr. Jose Rizal sa mga Kadalagahan sa Malolos, Bulakan","Text","918","17116","387","https://www.gutenberg.org/ebooks/17116","1861","1896","Rizal, Jose","20","November 20, 2005","11","November","2005","7","image/jpeg,text/html; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","17.3","13.52","10.67","1218","13.8","44.07","12.8","12.0","11.2","-0.25673076923076926","0.38076923076923075","5.26","27.0","0.04","17765","330","121","5565.6","3377" +"","en","","Patty's Fortune","Text","918","51354","388","https://www.gutenberg.org/ebooks/51354","1862","1942","Wells, Carolyn","4","March 4, 2016","3","March","2016","7","text/html,image/jpeg,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","6.5","8.97","5.87","5657","4.0","85.69","6.4","6.0","3.1","0.14845810901638637","0.527567462207476","4.73","11.0","0.09","251106","956","4715","68863.5","53071" +"DS","en","Jews -- History","The Wars of the Jews; Or, The History of the Destruction of Jerusalem","Text","917","2850","389","https://www.gutenberg.org/ebooks/2850","37","0","Josephus, Flavius","10","January 10, 2009","1","January","2009","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","25.0","10.75","6.82","12009","19.6","39.68","21.200000000000003","52.0","8.8","0.14264952997661032","0.4997430052126347","4.68","48.0","0.02","1103961","6028","4837","323544.6","235699" +"QH","en","Evolution (Biology),Natural selection","The Origin of Species by Means of Natural Selection: Or, the Preservation of Favoured Races in the Struggle for Life, 6th Edition","Text","916","2009","390","https://www.gutenberg.org/ebooks/2009","1809","1882","Darwin, Charles","1","December, 1999","12","December","1999","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","20.1","13.7","6.29","13343","16.2","37.98","15.200000000000001","7.0","11.2","0.1001579626284994","0.4379923931781869","5.24","33.0","0.03","1082757","12943","6119","324245.7","206725" +"PR","en","Political refugees -- Drama,Shipwreck victims -- Drama,Islands -- Drama,Tragicomedy,Spirits -- Drama,Fathers and daughters -- Drama,Magicians -- Drama","The Tempest: The Works of William Shakespeare [Cambridge Edition] [9 vols.]","Text","915","23042","391","https://www.gutenberg.org/ebooks/23042","1564","1616","Shakespeare, William","26","October 26, 2007","10","October","2007","6","text/html; charset=utf-8,text/plain; charset=us-ascii,text/plain; charset=utf-8,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","7.8","10.3","6.42","3314","2.9","94.15","6.4","7.0","3.1","0.15207933794379674","0.5202515771265763","4.96","11.0","0.09","115771","226","1985","28371.6","23337" +"","en","","The Ignoble Savages","Text","915","51413","392","https://www.gutenberg.org/ebooks/51413","1922","2000","Smith, Evelyn E.","10","March 10, 2016","3","March","2016","9","application/x-mobipocket-ebook,image/jpeg,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/html; charset=us-ascii","10.4","12.17","7.26","2079","7.6","65.73","7.6000000000000005","5.0","3.1","0.10393162165363647","0.5299331014480265","5.18","14.0","0.07","57952","464","758","16343.1","11197" +"PA","en","Philosophy, Ancient -- Poetry;Didactic poetry, Latin -- Translations into English","On the Nature of Things","Text","915","785","393","https://www.gutenberg.org/ebooks/785","-95","-55","Lucretius Carus, Titus","1","January, 1997","1","January","1997","6","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","21.6","11.73","7.26","7878","15.0","57.27","17.6","52.0","3.1","0.11009990000047365","0.48680392366302794","4.9","39.0","0.03","361744","1068","1851","98707.5","73789" +"Q","en","Science","The Outline of Science, Vol. 1 (of 4): A Plain Story Simply Told","Text","913","20417","394","https://www.gutenberg.org/ebooks/20417","1861","1933","Thomson, J. Arthur (John Arthur)","22","January 22, 2007","1","January","2007","8","text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","13.8","12.71","6.53","12147","10.7","57.61","10.8","14.5","8.8","0.12240422809589871","0.47813488103403884","5.12","22.0","0.04","545976","5791","4779","159942.6","106620" +"PR","en","Sisters -- Fiction,Courtship -- Fiction,Social classes -- Fiction,England -- Fiction,Domestic fiction,Young women -- Fiction,Love stories","Pride and Prejudice","Text","912","42671","395","https://www.gutenberg.org/ebooks/42671","1775","1817","Austen, Jane","9","May 9, 2013","5","May","2013","8","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","10.7","10.79","5.72","9170","7.9","70.13","9.200000000000001","3.5","3.1","0.1360934732442258","0.522053784736605","4.84","18.0","0.05","590445","4548","6563","171244.8","121919" +"PA","en","Medea, consort of Aegeus, King of Athens (Mythological character) -- Drama","Medea of Euripides","Text","910","35451","396","https://www.gutenberg.org/ebooks/35451","0","-406","Euripides","2","March 2, 2011","3","March","2011","7","text/html; charset=utf-8,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","8.6","9.85","6.47","2699","5.6","81.63","8.0","19.5","3.1","0.07936398118228856","0.5303330854658286","4.78","15.0","0.07","97465","288","1359","25731.0","20400" +"PR","en","Venice (Italy) -- Drama;Satire, English;Extortion -- Drama;Inheritance and succession -- Drama;English drama -- 17th century;English drama (Comedy)","Volpone; Or, The Fox","Text","905","4039","397","https://www.gutenberg.org/ebooks/4039","0","1637","Jonson, Ben","1","May, 2003","5","May","2003","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.8","12.4","7.22","9298","5.6","76.22","6.800000000000001","28.0","3.1","0.1337532318362266","0.5251933482988376","5.27","12.0","0.08","258773","1378","3833","68290.2","49071" +"","en","Midhat Pasa, 1822-1884;Statesmen -- Turkey -- Biography","The life of Midhat Pasha; a record of his services, political reforms, banishment, and judicial murder","Text","902","51243","398","https://www.gutenberg.org/ebooks/51243","1872","1950","Ali Haydar Mithat","17","February 17, 2016","2","February","2016","6","image/jpeg,text/plain; charset=utf-8,text/html; charset=utf-8,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","18.2","13.59","6.84","10754","13.8","49.49","14.0","14.0","8.8","0.10595072364491392","0.46180602189907394","5.22","30.0","0.03","517455","5891","3294","152673.3","99112" +"PR","en","Venice (Italy) -- Drama,Othello (Fictitious character) -- Drama,Tragedies,Muslims -- Drama,Interracial marriage -- Drama,Jealousy -- Drama","Othello","Text","896","2267","399","https://www.gutenberg.org/ebooks/2267","1564","1616","Shakespeare, William","1","January 1, 1622","1","January","1622","7","text/html,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","7.8","9.5","6.16","3341","4.8","83.66","7.2","13.5","3.1","0.1682967389507401","0.5715932376515467","4.72","13.0","0.07","132501","303","2011","36225.0","28085" +"","en","","The Pride of Jennico: Being a Memoir of Captain Basil Jennico","Text","896","51238","400","https://www.gutenberg.org/ebooks/51238","1858","1920","Castle, Egerton","17","February 17, 2016","2","February","2016","7","text/html,image/jpeg,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","12.4","10.28","6.66","8892","9.9","65.05","11.200000000000001","6.0","3.1","0.09980531545340751","0.4913910364217397","4.7","23.0","0.04","351110","1904","3204","101256.3","74659" +"","en","","Make Me An Offer","Text","894","51311","401","https://www.gutenberg.org/ebooks/51311","0","0","Blomberg, Con","27","February 27, 2016","2","February","2016","8","image/jpeg,text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","8.3","9.45","6.57","369","5.6","81.63","8.0","6.5","3.1","0.09548686473344006","0.44570420447132786","4.66","15.0","0.06","12414","54","172","3474.0","2664" +"","en","","People Soup","Text","894","51397","402","https://www.gutenberg.org/ebooks/51397","1934","0","Arkin, Alan","8","March 8, 2016","3","March","2016","8","application/x-mobipocket-ebook,image/jpeg,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","6.6","9.37","6.51","308","3.7","86.71","6.0","6.5","3.1","-0.0424694264069264","0.5020832044939189","4.85","10.0","0.1","9906","30","196","2637.9","2044" +"PG","en","Gogol, Nikolai Vasilevich, 1809-1852 -- Translations into English;Russia -- Social life and customs -- Fiction;Short stories, Russian -- Translations into English","The Mantle, and Other Stories","Text","892","36238","403","https://www.gutenberg.org/ebooks/36238","1809","1852","Gogol, Nikolai Vasilevich","27","May 27, 2011","5","May","2011","9","image/jpeg,text/html; charset=utf-8,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","9.4","10.15","6.23","6270","7.2","72.16","8.4","6.0","3.1","0.0725343333753251","0.49633346379121646","4.78","16.0","0.06","263365","1615","3294","75495.6","55097" +"B,PA","en","Classical literature,Political science -- Early works to 1800,Ethics -- Early works to 1800","Gorgias","Text","891","1672","404","https://www.gutenberg.org/ebooks/1672","-428","-348","Plato","1","March, 1999","3","March","1999","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","13.2","10.51","6.32","5614","10.3","64.04","11.600000000000001","14.0","3.1","0.13930847664982415","0.5555531570531568","4.74","24.0","0.04","280841","1731","2411","82976.4","59287" +"PR","en","Ireland -- Drama","The Playboy of the Western World: A Comedy in Three Acts","Text","887","1240","405","https://www.gutenberg.org/ebooks/1240","1871","1909","Synge, J. M. (John Millington)","1","March, 1998","3","March","1998","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","7.2","9.16","5.84","2031","3.6","92.12","7.2","17.5","3.1","0.09242725700831564","0.5002595952486775","4.66","13.0","0.07","95664","144","1527","25218.9","20521" +"","en","","Sea Legs","Text","887","51407","406","https://www.gutenberg.org/ebooks/51407","0","0","Quattrocchi, Frank","9","March 9, 2016","3","March","2016","8","text/plain,image/jpeg,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","6.9","10.01","6.62","2189","4.8","78.25","6.0","6.0","3.1","0.07452684031555484","0.4931669711305334","4.96","10.0","0.1","68820","426","1384","18977.4","13876" +"B,PA","en","Classical literature,Immortality (Philosophy) -- Early works to 1800","Phaedo","Text","885","1658","407","https://www.gutenberg.org/ebooks/1658","-428","-348","Plato","1","March, 1999","3","March","1999","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","14.3","9.87","6.54","4244","11.5","60.99","12.8","11.5","3.1","0.12682288288647267","0.5092090640534725","4.63","27.0","0.04","198125","1336","1536","59043.6","42773" +"PT","de","Authors -- Fiction,Munich (Germany) -- Fiction,Venice (Italy) -- Fiction","Der Tod in Venedig","Text","879","12108","408","https://www.gutenberg.org/ebooks/12108","1875","1955","Mann, Thomas","22","April 22, 2004","4","April","2004","8","text/html,text/plain; charset=us-ascii,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","19.9","18.63","9.42","7253","12.7","47.12","11.600000000000001","21.0","8.8","0.1250135904947917","0.4471428571428572","6.14","24.0","0.04","153092","1497","1006","41146.2","24952" +"PR","en","Social classes -- Fiction,Poor families -- Fiction,Satire,Deception -- Fiction,London (England) -- Fiction,Inheritance and succession -- Fiction,Love stories","Our Mutual Friend","Text","879","883","409","https://www.gutenberg.org/ebooks/883","1812","1870","Dickens, Charles","27","April 27, 2006","4","April","2006","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.7","10.15","5.62","23511","6.4","79.6","8.8","2.0","3.1","0.09167049870945343","0.5019324467486109","4.78","17.0","0.06","1555005","8187","18804","434332.8","325137" +"","en","","The Spicy Sound of Success","Text","878","51351","410","https://www.gutenberg.org/ebooks/51351","1933","2010","Harmon, Jim","3","March 3, 2016","3","March","2016","7","text/plain,image/jpeg,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","7.4","10.42","6.96","999","4.8","78.25","6.0","5.5","3.1","0.06736126194383256","0.5137072974677578","4.98","10.0","0.09","27775","152","516","7746.3","5579" +"HS","en","Boy Scouts of America -- Handbooks, manuals, etc.;Boy Scouts -- United States -- Handbooks, manuals, etc.","Boy Scouts Handbook: The First Edition, 1911","Text","877","29558","411","https://www.gutenberg.org/ebooks/29558","0","0","Boy Scouts of America","1","August 1, 2009","8","August","2009","8","image/jpeg,text/html; charset=iso-8859-1,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","11.0","11.43","6.14","12975","7.9","70.13","9.200000000000001","6.5","3.1","0.11267245739028409","0.4493683159511486","4.95","18.0","0.05","628536","3812","6954","171567.0","126921" +"B,PA","en","Ethics","The Ethics of Aristotle","Text","877","8438","412","https://www.gutenberg.org/ebooks/8438","-384","-322","Aristotle","1","July, 2005","7","July","2005","6","text/html,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","21.1","11.15","6.79","8749","16.1","48.81","17.6","12.0","8.8","0.13710532713531806","0.4799738175984163","4.8","39.0","0.03","542999","4594","2840","160633.8","113184" +"PR","en","Paranormal fiction,Horror tales","The Great God Pan","Text","876","389","413","https://www.gutenberg.org/ebooks/389","1863","1947","Machen, Arthur","1","January, 1996","1","January","1996","7","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","10.4","9.52","6.6","2699","7.6","76.56","10.0","7.0","3.1","0.049536836485273975","0.48118718997052373","4.62","20.0","0.05","100144","474","1079","28710.9","21671" +"BL,JC","en","Rationalism,Philosophy and religion,Political science","The Writings of Thomas Paine — Volume 4 (1794-1796): The Age of Reason","Text","871","3743","414","https://www.gutenberg.org/ebooks/3743","1737","1809","Paine, Thomas","1","February, 2003","2","February","2003","6","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","17.1","10.92","6.79","7180","13.4","55.92","14.8","28.5","8.8","0.0772943516431888","0.44674067884865276","4.76","32.0","0.03","344702","2819","2248","102130.2","72456" +"DA","en","Great Britain -- Politics and government -- 1760-1820,Political science -- Early works to 1800","The Works of the Right Honourable Edmund Burke, Vol. 01 (of 12)","Text","869","15043","415","https://www.gutenberg.org/ebooks/15043","1729","1797","Burke, Edmund","27","March 27, 2005","3","March","2005","8","text/html; charset=utf-8,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","16.3","12.02","6.42","13701","13.0","51.52","13.200000000000001","7.5","8.8","0.11933029057632888","0.5034657195220524","4.95","28.0","0.03","765346","7287","5365","228743.1","154577" +"B","en","Pragmatism","Pragmatism: A New Name for Some Old Ways of Thinking","Text","869","5116","416","https://www.gutenberg.org/ebooks/5116","1842","1910","James, William","1","February, 2004","2","February","2004","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","12.7","12.07","6.81","7174","9.9","59.64","10.0","14.0","8.8","0.10552511963550727","0.4984448892292672","5.06","20.0","0.05","262817","3165","2532","78679.8","51956" +"","en","","Angel's Egg","Text","868","51408","417","https://www.gutenberg.org/ebooks/51408","1909","1976","Pangborn, Edgar","9","March 9, 2016","3","March","2016","8","image/jpeg,text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.5","10.09","6.93","2203","7.2","72.16","8.4","6.5","3.1","0.0963893876735302","0.4950340866349975","4.77","16.0","0.06","66288","428","824","19305.0","13897" +"PR","en","Allegories,Detective and mystery stories,Anarchists -- Fiction,Police -- Fiction,London (England) -- Fiction,Fantasy fiction","The Man Who Was Thursday: A Nightmare","Text","867","1695","418","https://www.gutenberg.org/ebooks/1695","1874","1936","Chesterton, G. K. (Gilbert Keith)","1","April, 1999","4","April","1999","6","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/rdf+xml,application/epub+zip,text/plain","9.2","9.92","6.17","6400","7.2","72.16","8.4","10.5","3.1","0.03172420960594664","0.4951721084253454","4.74","16.0","0.06","275028","1554","3499","78940.8","58081" +"PR","en","English drama,Man-woman relationships -- Drama","A Woman of No Importance","Text","866","854","419","https://www.gutenberg.org/ebooks/854","1854","1900","Wilde, Oscar","16","September 16, 2014","9","September","2014","5","text/plain; charset=utf-8,application/rdf+xml,application/epub+zip,text/html,application/x-mobipocket-ebook","6.6","9.43","5.62","2118","4.8","78.25","6.0","7.5","3.1","0.13515503458785239","0.5585171098569135","4.86","10.0","0.1","108881","375","2167","30342.6","22413" +"PA,D","en","History, Ancient;Greece -- History -- To 146 B.C.","The History of Herodotus — Volume 1","Text","864","2707","420","https://www.gutenberg.org/ebooks/2707","-484","-430","Herodotus","1","July, 2001","7","July","2001","8","application/rdf+xml,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/html; charset=iso-8859-1,text/plain","21.7","10.35","6.78","10826","16.1","54.23","18.8","6.5","3.1","0.11259940516573567","0.45914813846862873","4.61","42.0","0.02","746202","3046","3769","214278.3","161693" +"PR","en","Bulgaria -- Drama;Soldiers -- Bulgaria -- Drama;Italians -- Bulgaria -- Drama;Serbo-Bulgarian War, 1885 -- Drama;War -- Drama;Love -- Drama;Man-woman relationships -- Drama","Arms and the Man","Text","864","3618","421","https://www.gutenberg.org/ebooks/3618","1856","1950","Shaw, Bernard","1","January, 2003","1","January","2003","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","7.3","10.07","6.36","3389","5.2","77.23","6.4","11.5","3.1","0.08122478225266004","0.514015707787348","4.92","11.0","0.09","121073","647","2195","33669.9","24592" +"JC","en","Justice -- Early works to 1800,Utopias -- Early works to 1800,Political science -- Early works to 1800","The Republic","Text","863","150","422","https://www.gutenberg.org/ebooks/150","-428","-348","Plato","22","May 22, 2008","5","May","2008","6","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","13.7","10.16","6.15","9659","11.1","62.01","12.4","14.0","3.1","0.15102850485774583","0.5455151988484466","4.68","26.0","0.04","581468","3744","4752","170006.4","124348" +"PG","en","Russian drama -- Translations into English;Chekhov, Anton Pavlovich, 1860-1904 -- Translations into English","Plays by Anton Chekhov, Second Series","Text","863","7986","423","https://www.gutenberg.org/ebooks/7986","1860","1904","Chekhov, Anton Pavlovich","1","April, 2005","4","April","2005","8","application/rdf+xml,text/html; charset=iso-8859-1,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","6.9","9.83","5.71","6687","4.8","78.25","6.0","29.0","3.1","0.06362912506606506","0.5337061856474271","4.93","10.0","0.1","330496","1576","6628","90916.2","67081" +"PR","en","Brothers and sisters -- Drama,Retribution -- Drama,Tragedies,English drama -- 17th century","The Duchess of Malfi","Text","862","2232","424","https://www.gutenberg.org/ebooks/2232","0","0","Webster, John","1","June, 2000","6","June","2000","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","8.9","11.07","6.37","3513","4.8","83.66","7.2","14.5","3.1","0.13144304296519546","0.548490996424959","4.99","13.0","0.07","132336","426","1951","35449.2","26516" +"","en","","Submarines, Mines and Torpedoes in the War","Text","862","51347","425","https://www.gutenberg.org/ebooks/51347","0","0","Domville-Fife, Charles William","3","March 3, 2016","3","March","2016","6","image/jpeg,text/html; charset=utf-8,text/plain; charset=utf-8,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","14.2","13.92","6.52","3158","9.9","59.64","10.0","4.0","8.8","0.07198360968068457","0.44343809182059113","5.38","20.0","0.05","141680","1376","1275","39383.1","26355" +"","en","","Survival Type","Text","859","51395","426","https://www.gutenberg.org/ebooks/51395","1916","2006","Bone, Jesse F. (Jesse Franklin)","8","March 8, 2016","3","March","2016","8","application/x-mobipocket-ebook,image/jpeg,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","10.3","12.06","7.45","1632","7.6","65.73","7.6000000000000005","5.0","3.1","0.02653566217071577","0.5320101762997201","5.16","14.0","0.07","42639","350","558","12103.2","8266" +"","en","","A Touch of E Flat","Text","851","51304","427","https://www.gutenberg.org/ebooks/51304","0","0","Gibson, Joe","26","February 26, 2016","2","February","2016","8","image/jpeg,text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.7","11.19","7.56","1412","6.8","73.17","8.0","10.5","3.1","0.019494962849945795","0.4558858593611576","5.01","15.0","0.07","35118","231","464","9891.9","7015" +"","en","","Fresh Air Fiend","Text","851","51335","428","https://www.gutenberg.org/ebooks/51335","1925","1980","Neville, Kris","1","March 1, 2016","3","March","2016","8","application/x-mobipocket-ebook,image/jpeg,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","7.2","9.21","6.71","719","4.4","84.68","6.800000000000001","4.5","3.1","-0.038113249668900354","0.5225552491648384","4.72","12.0","0.08","21618","113","360","6039.9","4582" +"PS","en","Science fiction,Humorous stories,Short stories","The Eyes Have It","Text","846","31516","429","https://www.gutenberg.org/ebooks/31516","1928","1982","Dick, Philip K.","6","March 6, 2010","3","March","2010","7","text/html; charset=utf-8,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","6.7","9.83","7.58","251","4.4","79.26","5.6000000000000005","5.0","3.1","0.07472142055475388","0.4439714606381272","4.98","9.0","0.11","5637","42","121","1593.9","1133" +"PR","en","Africa -- Fiction;Missing persons -- Fiction;Hunting guides -- Fiction;Treasure troves -- Fiction;Adventure stories;Quatermain, Allan (Fictitious character) -- Fiction;Diamond mines and mining -- Fiction","King Solomon's Mines","Text","840","2166","430","https://www.gutenberg.org/ebooks/2166","1856","1925","Haggard, H. Rider (Henry Rider)","11","October 11, 2005","10","October","2005","8","application/rdf+xml,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/html; charset=iso-8859-1,text/plain","10.8","9.4","6.1","7403","7.9","75.54","10.4","11.0","3.1","0.08883109706486544","0.4924664483244004","4.6","21.0","0.05","377979","1423","3897","107452.8","82197" +"PS","en","Fantasy,Short stories","Beyond the Door","Text","840","28644","431","https://www.gutenberg.org/ebooks/28644","1928","1982","Dick, Philip K.","30","April 30, 2009","4","April","2009","7","text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","5.3","8.15","6.13","321","3.3","87.72","5.6000000000000005","7.5","3.1","0.12390966315966312","0.5126664836664837","4.69","9.0","0.11","11601","30","265","3154.5","2474" +"PG","en","Russia -- Fiction,Peasants -- Russia -- Fiction","What Men Live By, and Other Tales","Text","836","6157","432","https://www.gutenberg.org/ebooks/6157","1828","1910","Tolstoy, Leo, graf","1","July, 2004","7","July","2004","6","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","7.5","8.18","5.9","1756","4.8","89.08","8.4","7.5","3.1","0.11281383844913243","0.493398313233607","4.44","16.0","0.06","83393","150","1175","23346.0","18800" +"PZ,PT","de","Children -- Conduct of life -- Juvenile fiction;Children's poetry, German;Stories in rhyme;Children's stories, German;Picture books for children;Behavior -- Fiction","Der Struwwelpeter: oder lustige Geschichten und drollige Bilder","Text","835","24571","433","https://www.gutenberg.org/ebooks/24571","1809","1894","Hoffmann, Heinrich","11","February 11, 2008","2","February","2008","7","text/plain; charset=utf-8,text/html; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","12.5","14.84","7.82","678","5.2","82.65","7.6000000000000005","11.0","3.1","0.6546875","0.7600000000000001","5.64","14.0","0.07","17290","116","209","4097.7","3066" +"PZ","en","Fables,Aesop's fables -- Adaptations,Folklore","The Aesop for Children: With pictures by Milo Winter","Text","834","19994","434","https://www.gutenberg.org/ebooks/19994","0","0","Aesop","2","December 2, 2006","12","December","2006","8","text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","8.0","8.64","5.86","2493","4.8","89.08","8.4","26.5","3.1","0.12423749871160501","0.5132730851159423","4.52","16.0","0.06","124215","316","1685","33919.2","27468" +"PG","en","Terrorists -- Russia -- Fiction,Russia -- Fiction,Nihilism -- Fiction,Russia -- Social life and customs -- 1533-1917 -- Fiction","The Possessed (The Devils)","Text","834","8117","435","https://www.gutenberg.org/ebooks/8117","1821","1881","Dostoyevsky, Fyodor","1","May, 2005","5","May","2005","8","application/rdf+xml,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/html; charset=iso-8859-1,text/plain","9.0","10.26","5.49","17885","6.8","73.17","8.0","3.5","3.1","0.06583135866934663","0.5134849466463745","4.85","15.0","0.07","1231093","9059","16792","354404.7","253678" +"PZ,PQ","en","Fairy tales","The Fairy Tales of Charles Perrault","Text","832","29021","436","https://www.gutenberg.org/ebooks/29021","1628","1703","Perrault, Charles","1","June 1, 2009","6","June","2009","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","14.5","10.28","6.77","3215","10.3","69.45","12.8","6.0","3.1","0.15996372332475914","0.5430563044451342","4.7","27.0","0.04","132804","571","1021","37099.8","28250" +"PZ,PS","en","People with disabilities -- Fiction,Gardens -- Fiction,Orphans -- Fiction,Yorkshire (England) -- Fiction","The Secret Garden","Text","830","17396","437","https://www.gutenberg.org/ebooks/17396","1849","1924","Burnett, Frances Hodgson","26","December 26, 2005","12","December","2005","9","application/rdf+xml,image/jpeg,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,text/plain","7.0","8.4","5.33","5127","5.2","82.65","7.6000000000000005","11.0","3.1","0.0864604234944442","0.5012077523864371","4.53","14.0","0.07","366551","886","5686","101291.4","80957" +"","en","","The National Geographic Magazine, Vol. II., No. 2, May, 1890","Text","829","51382","438","https://www.gutenberg.org/ebooks/51382","0","0","Various","6","March 6, 2016","3","March","2016","7","image/jpeg,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","15.4","12.94","6.75","4555","10.3","64.04","11.600000000000001","5.0","8.8","0.08158090194855415","0.41786602058437605","5.16","24.0","0.04","192438","1765","1495","53539.2","37316" +"F590.3","en","Lewis and Clark Expedition (1804-1806);Columbia River -- Description and travel;Clark, William, 1770-1838;Missouri River -- Description and travel;West (U.S.) -- History -- To 1848;West (U.S.) -- Description and travel;Lewis, Meriwether, 1774-1809","The Journals of Lewis and Clark, 1804-1806","Text","829","8419","439","https://www.gutenberg.org/ebooks/8419","1770","1838","Clark, William","1","July, 2005","7","July","2005","8","application/rdf+xml,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/html; charset=iso-8859-1,text/plain","13.8","9.23","1.89","23356","10.3","69.45","12.8","8.0","3.1","0.05017642814133908","0.3991338703097391","4.52","27.0","0.04","3002163","11931","23808","862051.5","664165" +"BJ","en","Ethics,Conduct of life","An Enquiry Concerning the Principles of Morals","Text","828","4320","440","https://www.gutenberg.org/ebooks/4320","1711","1776","Hume, David","12","January 12, 2010","1","January","2010","6","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","19.2","13.76","7.33","6573","15.4","40.01","14.4","14.5","11.2","0.11947739983835431","0.4712208981857288","5.25","31.0","0.03","253234","3047","1518","77575.5","48210" +"PS","en","Revolutions -- Fiction,Oligarchy -- Fiction,Science fiction,Socialism -- Fiction,Political fiction,Revolutionaries -- Fiction,Dystopias -- Fiction","The Iron Heel","Text","827","1164","441","https://www.gutenberg.org/ebooks/1164","1876","1916","London, Jack","3","May 3, 2006","5","May","2006","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","8.9","10.43","6.13","9994","6.4","74.19","7.6000000000000005","2.0","3.1","0.07614165919247295","0.4930927333860423","4.88","14.0","0.07","428593","3501","6015","123803.1","87796" +"PR","en","Plague -- Fiction;London (England) -- History -- 17th century -- Fiction;Historical fiction;Great Fire, London, England, 1666 -- Fiction","A Journal of the Plague Year: Written by a Citizen Who Continued All the While in London","Text","826","376","442","https://www.gutenberg.org/ebooks/376","0","1731","Defoe, Daniel","16","January 16, 2006","1","January","2006","6","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","24.2","10.29","7.06","6261","18.5","48.14","21.200000000000003","19.0","8.8","0.05046834446630697","0.49924318144256036","4.6","48.0","0.02","434954","2282","1971","126729.9","94619" +"BR","en","England -- Church history -- 449-1066","Bede's Ecclesiastical History of England","Text","825","38326","443","https://www.gutenberg.org/ebooks/38326","673","735","Bede, the Venerable, Saint","17","December 17, 2011","12","December","2011","11","application/prs.tei,text/plain; charset=us-ascii,text/html; charset=utf-8,application/pdf,text/plain; charset=utf-8,application/octet-stream,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","12.5","11.2","5.88","13699","7.9","75.54","10.4","11.0","3.1","0.13528461079154885","0.447471054031561","4.91","21.0","0.05","884434","5281","8294","238061.7","179997" +"BF","en","New Thought","As a Man Thinketh","Text","825","4507","444","https://www.gutenberg.org/ebooks/4507","1864","1912","Allen, James","1","October, 2003","10","October","2003","7","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","16.1","12.83","7.9","1423","12.3","53.55","12.4","28.5","8.8","0.14965412924554714","0.5732626208782915","5.14","26.0","0.04","38850","352","283","11082.6","7560" +"","en","","Inside Earth","Text","825","51184","445","https://www.gutenberg.org/ebooks/51184","1926","2001","Anderson, Poul","11","February 11, 2016","2","February","2016","8","image/jpeg,text/html; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","8.6","10.49","6.95","2841","6.4","74.19","7.6000000000000005","5.5","3.1","0.06132339073519972","0.49788761552283217","4.89","14.0","0.07","83833","592","1218","23903.1","17132" +"CR,BJ","en","Japan -- Social life and customs;Bushido;Ethics -- Japan;Samurai -- History;Japan -- Civilization;Philosophy, Japanese","Bushido, the Soul of Japan","Text","821","12096","446","https://www.gutenberg.org/ebooks/12096","1862","1933","Nitobe, Inazo","21","April 21, 2004","4","April","2004","8","application/rdf+xml,text/plain; charset=utf-8,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","14.8","12.42","7.71","6104","11.5","55.58","11.600000000000001","18.0","8.8","0.10958462330536184","0.4596885443852122","5.07","24.0","0.04","169432","1645","1359","50247.0","33447" +"PR","en","Short stories","The Red Room","Text","821","23218","447","https://www.gutenberg.org/ebooks/23218","1866","1946","Wells, H. G. (Herbert George)","27","October 27, 2007","10","October","2007","6","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","10.3","9.75","7.18","646","8.3","69.11","9.600000000000001","6.5","3.1","0.02372586903836903","0.4389396945646948","4.66","19.0","0.05","18292","89","200","5308.2","3924" +"PZ","en","Fairy tales,Folklore","The Blue Fairy Book","Text","821","503","448","https://www.gutenberg.org/ebooks/503","1844","1912","Lang, Andrew","1","April, 1996","4","April","1996","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","12.4","8.83","5.78","7879","9.5","71.48","12.0","27.0","3.1","0.11950838439576578","0.5258849973851106","4.45","25.0","0.04","615928","1538","5375","174079.8","138437" +"","en","","Citizen Jell","Text","821","51342","449","https://www.gutenberg.org/ebooks/51342","1928","1988","Shaara, Michael","2","March 2, 2016","3","March","2016","8","image/jpeg,text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","8.7","9.39","6.77","487","6.0","80.62","8.4","4.0","3.1","0.10864544546362734","0.4919855901674084","4.65","16.0","0.06","15310","84","200","4349.7","3293" +"JC","en","Nationalism","Nationalism","Text","820","40766","450","https://www.gutenberg.org/ebooks/40766","1861","1941","Tagore, Rabindranath","15","September 15, 2012","9","September","2012","9","image/jpeg,text/html; charset=iso-8859-1,text/plain,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","14.8","11.61","7.13","3809","11.9","54.56","12.0","5.0","8.8","0.09737948510903106","0.5031867848075041","4.93","25.0","0.04","131561","1385","1028","39361.5","26694" +"PZ","en","Universities and colleges -- Fiction;Self-perception -- Fiction;Canada -- History -- 1914-1945 -- Fiction;Orphans -- Fiction;Prince Edward Island -- History -- 20th century -- Fiction;Nova Scotia -- History -- 20th century -- Fiction;Interpersonal relations -- Fiction;Shirley, Anne (Fictitious character) -- Fiction","Anne of the Island","Text","819","51","451","https://www.gutenberg.org/ebooks/51","1874","1942","Montgomery, L. M. (Lucy Maud)","7","March 7, 2006","3","March","2006","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","7.6","9.5","5.92","7966","4.8","83.66","7.2","13.0","3.1","0.09772471948161861","0.5184044251176035","4.77","13.0","0.08","364866","1564","5870","102546.0","76565" +"PR","en","Autobiographical fiction,British -- Belgium -- Fiction,Brussels (Belgium) -- Fiction,Women teachers -- Fiction,Love stories","Villette","Text","819","9182","452","https://www.gutenberg.org/ebooks/9182","1816","1855","Bronte, Charlotte","1","October, 2005","10","October","2005","8","text/html,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","11.3","11.08","6.4","22213","8.3","69.11","9.600000000000001","1.0","3.1","0.10195900081678519","0.5032952540793808","4.89","19.0","0.05","941477","5862","9917","268078.5","192542" +"PR","en","English poetry -- 18th century,English poetry -- 19th century","The Poetical Works of William Wordsworth — Volume 3","Text","814","12383","453","https://www.gutenberg.org/ebooks/12383","1770","1850","Wordsworth, William","19","May 19, 2004","5","May","2004","9","application/rdf+xml,text/html,text/html; charset=iso-8859-1,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","16.5","12.31","6.99","15310","10.7","68.44","13.200000000000001","27.0","3.1","0.12950098926893996","0.48782081488232465","5.05","28.0","0.04","619927","2955","4329","165046.5","122801" +"PQ","en","Islands of the Pacific -- Fiction,Science fiction,Castaways -- Fiction,Adventure stories","The Mysterious Island","Text","813","1268","454","https://www.gutenberg.org/ebooks/1268","1828","1905","Verne, Jules","1","April, 1998","4","April","1998","6","text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","11.4","11.55","5.59","12951","7.9","70.13","9.200000000000001","3.0","3.1","0.09447586484955386","0.48653587350661903","4.97","18.0","0.05","959926","5524","10220","271143.0","193330" +"PR","en","England -- Fiction,Ghosts -- Fiction","The Canterville Ghost","Text","812","14522","455","https://www.gutenberg.org/ebooks/14522","1854","1900","Wilde, Oscar","30","December 30, 2004","12","December","2004","8","application/rdf+xml,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/html; charset=iso-8859-1,text/plain","13.5","10.97","7.26","1797","10.3","64.04","11.600000000000001","7.5","3.1","0.05970843680325472","0.49762155505365935","4.82","24.0","0.04","56107","368","476","16000.2","11650" +"","en","","Prime Difference","Text","810","51321","456","https://www.gutenberg.org/ebooks/51321","1928","1992","Nourse, Alan Edward","28","February 28, 2016","2","February","2016","8","image/jpeg,text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","7.0","9.32","6.6","750","4.4","84.68","6.800000000000001","5.0","3.1","0.07986939736059459","0.47394250311503816","4.74","12.0","0.08","23692","135","407","6703.2","4998" +"","en","","Adventures of Sherlock Holmes: Illustrated","Text","809","48320","457","https://www.gutenberg.org/ebooks/48320","1859","1930","Doyle, Arthur Conan","20","February 20, 2015","2","February","2015","7","image/jpeg,text/plain; charset=utf-8,text/html; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","8.0","9.1","5.82","9685","5.6","81.63","8.0","3.0","3.1","0.06606279369936886","0.48910213886815573","4.6","15.0","0.06","489706","2134","6888","139879.8","106348" +"PQ","en","France -- History -- Louis XIV, 1643-1715 -- Fiction;Adventure and adventurers -- Fiction;Swordsmen -- Fiction;Historical fiction;Man in the Iron Mask -- Fiction;Romances","The Man in the Iron Mask","Text","808","2759","458","https://www.gutenberg.org/ebooks/2759","1802","1870","Dumas, Alexandre","1","August, 2001","8","August","2001","6","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","10.1","11.13","5.79","15002","7.2","72.16","8.4","26.0","3.1","0.10082532877097997","0.5046136623139329","4.95","16.0","0.06","859847","4268","10614","239931.0","173624" +"PR","en","Songs, Scots -- Scotland -- Texts;Scotland -- Poetry","Poems and Songs of Robert Burns","Text","807","1279","459","https://www.gutenberg.org/ebooks/1279","1759","1796","Burns, Robert","25","January 25, 2005","1","January","2005","6","text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","12.0","11.89","6.54","15835","7.2","77.57","9.600000000000001","53.0","3.1","0.12203986895544769","0.5337468050618565","5.03","19.0","0.05","640138","1272","6514","161552.7","127342" +"","en","","Man in a Quandary","Text","804","51421","460","https://www.gutenberg.org/ebooks/51421","0","0","Wesley, Joseph","11","March 11, 2016","3","March","2016","7","application/x-mobipocket-ebook,image/jpeg,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","8.9","10.03","7.11","544","6.8","73.17","8.0","5.0","3.1","0.13120009520547155","0.46159384621750194","4.76","15.0","0.06","14989","128","198","4436.1","3150" +"QC","en","Optics -- Early works to 1800","Opticks: Or, A Treatise of the Reflections, Refractions, Inflections, and Colours of Light","Text","802","33504","461","https://www.gutenberg.org/ebooks/33504","1642","1727","Newton, Isaac, Sir","23","August 23, 2010","8","August","2010","8","text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","21.8","11.27","2.82","5002","16.9","46.78","18.400000000000002","11.0","8.8","0.09064661593902053","0.37706824790179017","4.77","41.0","0.02","478682","3208","2411","137179.8","100267" +"PS","en","Political corruption -- Fiction,Political fiction,Satire,Legislators -- Fiction,Speculation -- Fiction,Washington (D.C.) -- Fiction,Businessmen -- Fiction","The Gilded Age: A Tale of Today","Text","800","3178","462","https://www.gutenberg.org/ebooks/3178","1835","1910","Twain, Mark","1","January 1, 1873","1","January","1873","8","image/jpeg,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","10.4","10.62","6.07","15466","7.9","70.13","9.200000000000001","14.0","3.1","0.11789798177258652","0.5155528052503684","4.81","18.0","0.05","760584","4547","8599","216863.1","158279" +"AZ","en","Investments -- Psychological aspects,Common fallacies,Impostors and imposture,Hallucinations and illusions,Occultism -- Early works to 1900,Stock exchanges -- Psychological aspects,Alchemy,Delusions,Swindlers and swindling,Social psychology","Memoirs of Extraordinary Popular Delusions and the Madness of Crowds","Text","799","24518","463","https://www.gutenberg.org/ebooks/24518","1814","1889","Mackay, Charles","5","February 5, 2008","2","February","2008","9","text/html,text/plain; charset=utf-8,text/plain; charset=us-ascii,text/html; charset=utf-8,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","14.2","12.07","6.2","24196","11.5","55.58","11.600000000000001","5.0","3.1","0.10603763290511387","0.4988011377608628","5.01","24.0","0.04","1396288","11274","11609","404958.6","278850" +"PS","en","Paranormal fiction,Domestic fiction,Haunted houses -- Fiction,Historical fiction,Salem (Mass.) -- Fiction","The House of the Seven Gables","Text","798","77","464","https://www.gutenberg.org/ebooks/77","1804","1864","Hawthorne, Nathaniel","17","June 17, 2008","6","June","2008","7","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","13.8","12.19","6.64","12383","11.1","56.59","11.200000000000001","1.0","3.1","0.09436506818949193","0.5022182675385541","5.03","23.0","0.04","527575","4143","4527","152637.3","104875" +"UH","en","Sabotage","Simple Sabotage Field Manual","Text","797","26184","465","https://www.gutenberg.org/ebooks/26184","0","0","United States. Office of Strategic Services","4","August 4, 2008","8","August","2008","8","text/html,application/pdf,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","12.4","12.53","7.54","1715","9.5","60.65","9.600000000000001","14.0","3.1","0.013924175817661762","0.4908192958580281","5.14","19.0","0.05","47115","452","477","13646.7","9160" +"PS","en","Women iron and steel workers -- Fiction,Feminism -- Fiction","Life in the Iron-Mills; Or, The Korl Woman","Text","796","876","466","https://www.gutenberg.org/ebooks/876","1831","1910","Davis, Rebecca Harding","1","April 1997","4","April","1997","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","8.1","9.74","6.72","2222","5.2","82.65","7.6000000000000005","4.5","3.1","0.033002989415098806","0.5072631272631274","4.76","14.0","0.07","69916","245","1030","19215.9","14703" +"","en","","Time In the Round","Text","794","51380","467","https://www.gutenberg.org/ebooks/51380","1910","1992","Leiber, Fritz","6","March 6, 2016","3","March","2016","7","application/x-mobipocket-ebook,image/jpeg,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","9.0","11.82","7.38","1062","5.6","76.22","6.800000000000001","8.0","3.1","0.005346097555123672","0.4832693408465385","5.17","12.0","0.08","27588","194","440","7623.0","5334" +"PZ","en","Canada -- History -- 1914-1945 -- Fiction;Orphans -- Fiction;Prince Edward Island -- History -- 20th century -- Fiction;Shirley, Anne (Fictitious character) -- Fiction;Teachers -- Fiction;Islands -- Fiction","Anne of Avonlea","Text","793","47","468","https://www.gutenberg.org/ebooks/47","1874","1942","Montgomery, L. M. (Lucy Maud)","7","March 7, 2006","3","March","2006","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","7.5","9.16","5.67","7557","5.2","82.65","7.6000000000000005","10.5","3.1","0.09417784997218863","0.5085609030219368","4.66","14.0","0.07","413885","1475","6346","116844.3","88845" +"PZ","en","Folklore -- Japan,Fairy tales -- Japan,Fairy tales","Japanese Fairy Tales","Text","792","4018","469","https://www.gutenberg.org/ebooks/4018","0","0","Ozaki, Yei Theodora","1","May, 2003","5","May","2003","7","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","10.0","8.59","5.79","5193","7.6","76.56","10.0","11.0","3.1","0.12710011244547","0.4986328665761302","4.46","20.0","0.05","314871","1078","3375","90556.2","70603" +"PR","en","Monks -- Fiction,Gothic fiction (Literary genre),Madrid (Spain) -- Fiction,Horror tales","The Monk: A Romance","Text","791","601","470","https://www.gutenberg.org/ebooks/601","1775","1818","Lewis, M. G. (Matthew Gregory)","1","July, 1996","7","July","1996","7","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","11.1","11.31","5.98","12602","7.9","70.13","9.200000000000001","8.0","3.1","0.07487564396112127","0.5166978347351985","4.93","18.0","0.05","675505","4272","7345","196511.4","136959" +"PZ","en","Fairy tales -- India,Folklore -- India,Fairy tales","Indian Fairy Tales","Text","791","7128","471","https://www.gutenberg.org/ebooks/7128","0","0","Unknown","13","March 13, 2003","3","March","2003","8","text/plain; charset=utf-8,text/plain; charset=us-ascii,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","9.6","9.4","5.91","6204","6.8","78.59","9.200000000000001","7.0","3.1","0.11396176618726775","0.4896782963095673","4.6","18.0","0.05","327132","1222","3798","91932.3","71142" +"F2301","es","Venezuela -- History -- 1556-1810,Venezuela -- History -- To 1556","Historia de Venezuela, Tomo I","Text","789","39947","472","https://www.gutenberg.org/ebooks/39947","0","0","Aguado, Pedro de, active 16th century","8","June 8, 2012","6","June","2012","8","image/jpeg,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","29.9","11.74","8.15","21812","25.1","14.64","24.400000000000002","16.5","13.0","0.09511154855643043","0.5507295963004639","4.85","56.0","0.02","962119","13540","3484","326816.1","198454" +"","en","","Public School Life: Boys Masters Parents","Text","789","51409","473","https://www.gutenberg.org/ebooks/51409","1898","1981","Waugh, Alec","9","March 9, 2016","3","March","2016","9","image/jpeg,text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","9.5","9.86","6.08","7480","7.6","71.14","8.8","6.5","3.1","0.08253731828001133","0.477186276897706","4.73","17.0","0.06","348622","2728","4264","103139.1","73661" +"","en","","The Campaign in Russian Poland","Text","789","51411","474","https://www.gutenberg.org/ebooks/51411","0","0","Standing, Percy Cross","9","March 9, 2016","3","March","2016","7","text/html,image/jpeg,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","15.6","13.23","7.39","3940","11.9","54.56","12.0","7.5","8.8","0.10117432002512645","0.40825024679863403","5.21","25.0","0.04","129078","1087","989","37323.9","24791" +"B","de","Philosophy, German;Superman (Philosophical concept)","Also sprach Zarathustra: Ein Buch für Alle und Keinen","Text","789","7205","475","https://www.gutenberg.org/ebooks/7205","1844","1900","Nietzsche, Friedrich Wilhelm","1","January, 2005","1","January","2005","6","text/html,text/plain,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","11.7","13.91","6.31","10511","6.4","74.19","7.6000000000000005","58.0","3.1","0.22789224115165393","0.41418322295805765","5.48","14.0","0.07","459296","1898","5717","113239.8","83753" +"","en","","Double Standard","Text","788","51363","476","https://www.gutenberg.org/ebooks/51363","1921","2004","Coppel, Alfred","5","March 5, 2016","3","March","2016","8","image/jpeg,text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","6.5","9.66","6.99","459","3.3","87.72","5.6000000000000005","7.0","3.1","0.04863623552899122","0.46173024891774933","4.9","9.0","0.1","12222","74","255","3307.5","2492" +"HV","en","Lynching -- United States,Lynching -- United States -- Statistics,African Americans -- History -- 1877-1964","The Red Record: Tabulated Statistics and Alleged Causes of Lynching in the United States","Text","786","14977","477","https://www.gutenberg.org/ebooks/14977","1862","1931","Wells-Barnett, Ida B.","8","February 8, 2005","2","February","2005","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","12.4","11.26","6.79","4576","9.1","67.08","10.4","11.5","3.1","0.01836182332561978","0.41745001845295354","4.92","21.0","0.05","168129","1138","1597","48411.0","34195" +"GN","en","Religion -- Philosophy,Religion,Cults,Totemism,Rites and ceremonies","The Elementary Forms of the Religious Life","Text","786","41360","478","https://www.gutenberg.org/ebooks/41360","1858","1917","Durkheim, Emile","13","November 13, 2012","11","November","2012","7","text/plain; charset=us-ascii,text/plain,text/plain; charset=iso-8859-1,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","13.6","12.25","5.73","13926","10.7","57.61","10.8","11.0","8.8","0.08385886102173148","0.4543397418270334","5.04","22.0","0.04","1104702","12794","9668","324092.7","219215" +"PS","en","Fantasy fiction;American fiction -- 19th century;Horror tales, American;American poetry","The Works of Edgar Allan Poe — Volume 5","Text","784","2151","479","https://www.gutenberg.org/ebooks/2151","1809","1849","Poe, Edgar Allan","19","May 19, 2008","5","May","2008","8","text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","13.5","12.07","7.17","11202","9.5","66.07","10.8","27.5","3.1","0.11159292904526778","0.5088978297089701","5.01","22.0","0.04","362481","2752","3194","102180.6","72342" +"PR","en","Eve (Biblical figure) -- Poetry,Bible. Genesis -- History of Biblical events -- Poetry,Fall of man -- Poetry,Adam (Biblical figure) -- Poetry","Paradise Lost","Text","784","26","480","https://www.gutenberg.org/ebooks/26","1608","1674","Milton, John","1","February, 1992","2","February","1992","6","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","23.7","12.55","7.91","10866","17.7","44.75","19.200000000000003","10.5","3.1","0.13604753333888717","0.5239110844968548","4.99","43.0","0.02","400345","1276","1859","108386.1","80255" +"PA","en","Sublime, The;Rhetoric, Ancient","On the Sublime","Text","782","17957","481","https://www.gutenberg.org/ebooks/17957","0","0","Longinus, 1st cent.","10","March 10, 2006","3","March","2006","8","text/plain; charset=utf-8,text/plain; charset=us-ascii,text/html; charset=utf-8,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","13.9","12.48","7.51","5294","10.7","57.61","10.8","7.0","8.8","0.11984179723277923","0.5048637163476272","5.08","22.0","0.04","152599","1367","1319","43649.1","30044" +"","en","","Break a Leg","Text","782","51320","482","https://www.gutenberg.org/ebooks/51320","1933","2010","Harmon, Jim","28","February 28, 2016","2","February","2016","8","image/jpeg,text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","8.5","9.97","6.88","1277","6.4","74.19","7.6000000000000005","5.5","3.1","0.05666082067466804","0.486713089804407","4.8","14.0","0.07","37941","211","541","10952.1","7898" +"PG","en","Christian fiction,Jesus Christ -- Fiction","The Grand Inquisitor","Text","782","8578","483","https://www.gutenberg.org/ebooks/8578","1821","1881","Dostoyevsky, Fyodor","1","July, 2005","7","July","2005","8","text/html; charset=iso-8859-1,text/plain,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","13.4","11.15","7.41","1609","9.9","65.05","11.200000000000001","8.5","3.1","0.12071208067377177","0.5387089354711372","4.85","23.0","0.04","46747","290","402","13360.5","9640" +"TT","en","Woodwork,Carpentry","Woodwork Joints: How they are Set Out, How Made and Where Used.","Text","781","21531","484","https://www.gutenberg.org/ebooks/21531","0","0","Fairham, William","19","May 19, 2007","5","May","2007","8","application/rdf+xml,text/plain; charset=us-ascii,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","10.8","11.31","5.91","3336","6.4","79.6","8.8","4.5","3.1","0.05103031824806009","0.42151491418527676","4.98","17.0","0.06","183815","1401","2106","49685.4","36923" +"","en","","To The Fore With the Tanks!","Text","781","51332","485","https://www.gutenberg.org/ebooks/51332","1876","1959","Westerman, Percy F. (Percy Francis)","29","February 29, 2016","2","February","2016","7","image/jpeg,text/plain; charset=utf-8,text/html; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","10.4","12.0","6.51","6433","6.8","73.17","8.0","4.5","3.1","0.034912348405188594","0.44025777427125296","5.15","15.0","0.07","245929","1535","3145","68553.0","47762" +"","en","","Memories of the Kaiser's Court","Text","780","51290","486","https://www.gutenberg.org/ebooks/51290","0","0","Topham, Anne","24","February 24, 2016","2","February","2016","7","image/jpeg,text/html; charset=utf-8,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","15.5","13.47","7.01","12811","11.5","55.58","11.600000000000001","11.0","8.8","0.08861141116088038","0.42468917942089424","5.25","24.0","0.04","487495","4023","3815","134752.5","92768" +"","en","","I Am A Nucleus","Text","778","51330","487","https://www.gutenberg.org/ebooks/51330","0","0","Barr, Stephen","29","February 29, 2016","2","February","2016","8","image/jpeg,text/html; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","7.1","9.09","6.48","1630","4.4","84.68","6.800000000000001","7.0","3.1","0.03324478763492181","0.46879378365962127","4.7","12.0","0.08","53745","269","890","15057.0","11446" +"","en","","Turkey; the Awakening of Turkey; the Turkish Revolution of 1908","Text","777","51329","488","https://www.gutenberg.org/ebooks/51329","1852","1925","Knight, E. F. (Edward Frederick)","29","February 29, 2016","2","February","2016","6","text/html,image/jpeg,text/plain; charset=utf-8,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","19.6","13.24","6.9","8257","15.0","46.44","15.200000000000001","5.5","8.8","0.10029971584643746","0.4652350273335504","5.16","33.0","0.03","413277","4419","2389","121644.9","80089" +"","en","","Not a Creature Was Stirring","Text","777","51396","489","https://www.gutenberg.org/ebooks/51396","0","0","Evans, Dean","8","March 8, 2016","3","March","2016","7","image/jpeg,text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","7.5","9.39","6.72","806","4.8","83.66","7.2","6.5","3.1","0.036320863748602106","0.45769263641474583","4.7","13.0","0.07","24512","105","385","6847.2","5212" +"HD","en","Businesspeople -- United States -- Biography;Automobiles -- History;Ford Motor Company -- History;Industrialists -- United States -- Biography;Automobile industry and trade -- United States -- History;Ford, Henry, 1863-1947","My Life and Work","Text","776","7213","490","https://www.gutenberg.org/ebooks/7213","1863","1947","Ford, Henry","1","January, 2005","1","January","2005","6","text/html,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","10.3","10.33","5.92","8199","7.9","70.13","9.200000000000001","2.5","3.1","0.11906428817276578","0.471239023143641","4.76","18.0","0.05","443582","3868","5018","132825.6","93205" +"PT","de","Buddhist philosophy -- Fiction,Religious fiction,Buddhism -- Fiction,India -- Fiction,Gautama Buddha -- Fiction","Siddhartha: eine indische Dichtung","Text","770","2499","491","https://www.gutenberg.org/ebooks/2499","1877","1962","Hesse, Hermann","1","February, 2001","2","February","2001","7","text/html,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","13.3","13.92","6.85","5057","7.9","70.13","9.200000000000001","8.0","3.1","0.16666552569415113","0.6202702702702705","5.38","18.0","0.05","185055","735","1828","48660.3","34391" +"PS","en","Fathers and daughters -- Fiction;Americans -- Italy -- Fiction;Married women -- Fiction;Italy -- Fiction;Triangles (Interpersonal relations) -- Fiction;Psychological fiction;Inheritance and succession -- Fiction;Archer, Isabel (Fictitious character) -- Fiction;Love stories","The Portrait of a Lady — Volume 1","Text","769","2833","492","https://www.gutenberg.org/ebooks/2833","1843","1916","James, Henry","1","September, 2001","9","September","2001","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","9.5","10.38","5.91","10961","7.2","72.16","8.4","19.0","3.1","0.14175661068015075","0.5158716017191702","4.82","16.0","0.06","563153","3677","7107","161989.2","116826" +"PR","en","Science fiction,Second Advent -- Fiction","Lord of the World","Text","767","14021","493","https://www.gutenberg.org/ebooks/14021","1871","1914","Benson, Robert Hugh","11","November 11, 2004","11","November","2004","7","text/html,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","10.8","11.02","6.2","10498","7.9","70.13","9.200000000000001","14.0","3.1","0.07071893277975196","0.4724000723925543","4.88","18.0","0.05","485539","3025","5407","137738.7","99477" +"PS","en","Philosophy, American;Nature","Nature","Text","766","29433","494","https://www.gutenberg.org/ebooks/29433","1803","1882","Emerson, Ralph Waldo","17","July 17, 2009","7","July","2009","8","text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","11.4","10.91","7.4","2742","8.3","69.11","9.600000000000001","7.5","3.1","0.1648097319835015","0.5093548733047848","4.86","19.0","0.05","74572","570","775","21948.3","15335" +"B","en","Philosophy, German;Ethics","Fundamental Principles of the Metaphysic of Morals","Text","766","5682","495","https://www.gutenberg.org/ebooks/5682","1724","1804","Kant, Immanuel","1","May, 2004","5","May","2004","7","text/html,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","22.3","12.14","7.08","2749","18.1","38.32","18.400000000000002","19.0","11.2","0.10948005550159794","0.4792892756999772","4.92","41.0","0.02","151363","1948","747","46692.9","30759" +"PS","en","Horror tales, American;Haunted houses -- Fiction","The Shunned House","Text","764","31469","496","https://www.gutenberg.org/ebooks/31469","1890","1937","Lovecraft, H. P. (Howard Phillips)","2","March 2, 2010","3","March","2010","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","17.8","12.66","8.5","2315","13.8","49.49","14.0","14.0","8.8","0.025546147966118277","0.49969151496009734","5.06","30.0","0.03","54824","491","351","16094.7","10832" +"E151","en","Washington, Booker T., 1856-1915;African Americans -- Biography;Tuskegee Institute;Educators -- United States -- Biography","Up from Slavery: An Autobiography","Text","763","2376","497","https://www.gutenberg.org/ebooks/2376","1856","1915","Washington, Booker T.","1","October, 2000","10","October","2000","6","text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","12.9","9.99","6.06","5999","10.3","64.04","11.600000000000001","11.0","3.1","0.1367327312604272","0.4493854093057073","4.65","24.0","0.04","356613","2342","3087","106313.4","76625" +"D","en","Europe -- History -- 18th century -- Biography;Casanova, Giacomo, 1725-1798","The Memoirs of Jacques Casanova de Seingalt, 1725-1798. Complete","Text","763","2981","498","https://www.gutenberg.org/ebooks/2981","1725","1798","Casanova, Giacomo","2","November 2, 2006","11","November","2006","8","text/plain,image/jpeg,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","10.0","8.18","1.57","42425","7.9","75.54","10.4","18.5","3.1","0.15815849218298605","0.5384640433750152","4.39","21.0","0.05","5512413","28825","58389","1674954.0","1256752" +"PS","en","Walking -- Fiction,Humorous stories,Europe -- Fiction,Americans -- Europe -- Fiction","A Tramp Abroad","Text","762","119","499","https://www.gutenberg.org/ebooks/119","1835","1910","Twain, Mark","1","June 2004","6","June","2004","8","image/jpeg,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","12.1","10.62","6.42","17178","9.1","67.08","10.4","1.0","3.1","0.09660184565345213","0.4763224268840547","4.81","21.0","0.05","751486","4815","7162","215898.3","156139" +"PA","en","Latin letters -- Translations into English;Lawyers -- Rome -- Correspondence;Pliny, the Younger -- Correspondence;Authors, Latin -- Rome -- Correspondence","Letters of Pliny","Text","760","2811","500","https://www.gutenberg.org/ebooks/2811","61","0","Pliny, the Younger","1","September, 2001","9","September","2001","8","application/rdf+xml,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/html; charset=iso-8859-1,text/plain","17.5","11.56","6.93","9797","13.4","55.92","14.8","10.5","8.8","0.13580304853976982","0.4889603033526516","4.87","32.0","0.03","441595","3287","2835","131226.3","90738" +"PA","en","Latin language -- Readers","Helps to Latin Translation at Sight","Text","760","28890","501","https://www.gutenberg.org/ebooks/28890","0","0","Luce, Edmund","20","May 20, 2009","5","May","2009","7","text/plain; charset=utf-8,text/html; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","13.1","16.06","8.38","30964","8.4","58.28","7.2","11.5","3.1","0.12438536424622833","0.44460256226149053","5.85","13.0","0.07","697584","7392","8553","193163.4","119325" +"PT","en","German poetry -- Translations into English","Erotica Romana","Text","760","7889","502","https://www.gutenberg.org/ebooks/7889","1749","1832","Goethe, Johann Wolfgang von","1","April, 2005","4","April","2005","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","10.8","11.95","7.99","1516","7.2","72.16","8.4","11.0","3.1","0.1629299493766707","0.573497380124429","5.09","16.0","0.06","34257","136","405","9413.1","6726" +"","en","","Voyage to Far N'jurd","Text","759","51344","503","https://www.gutenberg.org/ebooks/51344","1925","1980","Neville, Kris","2","March 2, 2016","3","March","2016","8","application/x-mobipocket-ebook,image/jpeg,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","6.5","9.6","6.11","1581","3.3","87.72","5.6000000000000005","4.5","3.1","0.09234263110824058","0.46495284623437877","4.89","9.0","0.1","60102","178","1257","15825.6","12297" +"PR","en","Humorous stories,Foundlings -- Fiction,Bildungsromans,Identity (Psychology) -- Fiction,England -- Fiction,Young men -- Fiction","History of Tom Jones, a Foundling","Text","758","6593","504","https://www.gutenberg.org/ebooks/6593","1707","1754","Fielding, Henry","1","September, 2004","9","September","2004","8","text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","16.0","10.98","5.95","19407","12.2","58.96","13.600000000000001","11.0","3.1","0.1310567621002875","0.5200272776474321","4.77","29.0","0.03","1672513","9755","11701","487581.3","350346" +"QH","en","Microscopy -- Early works to 1800,Magnifying glasses -- Early works to 1800,Natural history -- Pre-Linnean works","Micrographia: Some Physiological Descriptions of Minute Bodies Made by Magnifying Glasses with Observations and Inquiries Thereupon","Text","757","15491","505","https://www.gutenberg.org/ebooks/15491","1635","1703","Hooke, Robert","29","March 29, 2005","3","March","2005","8","application/rdf+xml,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,text/plain","30.9","11.45","7.78","11893","23.9","28.51","25.6","8.0","8.8","0.10917004633413949","0.4381462192523331","4.8","59.0","0.02","742341","5020","2599","215468.1","154574" +"","en","","...So They Baked a Cake","Text","757","51414","506","https://www.gutenberg.org/ebooks/51414","1915","1979","Marks, Winston K.","10","March 10, 2016","3","March","2016","8","text/plain,image/jpeg,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.5","10.95","7.69","886","6.4","74.19","7.6000000000000005","8.0","3.1","0.046387063140111935","0.5043714633755287","4.97","14.0","0.07","20670","163","278","5870.7","4161" +"PR","en","Fathers and daughters -- Fiction;London (England) -- Fiction;Children of prisoners -- Fiction;Debt, Imprisonment for -- Fiction;Inheritance and succession -- Fiction;Domestic fiction;Love stories;Marshalsea Prison (Southwark, London, England) -- Fiction","Little Dorrit","Text","757","963","507","https://www.gutenberg.org/ebooks/963","1812","1870","Dickens, Charles","1","July, 1997","7","July","1997","8","image/jpeg,text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","11.0","10.39","5.68","23486","8.3","69.11","9.600000000000001","1.5","3.1","0.09840652753558704","0.49970642543609906","4.77","19.0","0.05","1608982","9258","16950","456670.8","337359" +"PR,PZ","en","England -- Fiction,Brothers and sisters -- Fiction,Country life -- England -- Fiction,Family life -- Fiction,Railroads -- Fiction","The Railway Children","Text","756","1874","508","https://www.gutenberg.org/ebooks/1874","1858","1924","Nesbit, E. (Edith)","1","August, 1999","8","August","1999","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","7.8","9.45","5.65","4962","5.2","82.65","7.6000000000000005","2.5","3.1","0.06549923844397323","0.5006044720634757","4.71","14.0","0.07","279395","633","4235","74823.3","59291" +"PS","en","Conduct of life -- Fiction,Egoism -- Fiction,Man-woman relationships -- Fiction,Fate and fatalism -- Fiction","The Beast in the Jungle","Text","755","1093","509","https://www.gutenberg.org/ebooks/1093","1843","1916","James, Henry","6","February 6, 2005","2","February","2005","7","text/html,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","11.0","9.63","6.64","2309","7.9","75.54","10.4","18.0","3.1","0.07474334581879288","0.5154066496252067","4.64","21.0","0.05","86054","449","877","24635.7","18565" +"E300","en","Statesmen -- United States -- Biography;Franklin, Benjamin, 1706-1790","The Autobiography of Benjamin Franklin","Text","755","148","510","https://www.gutenberg.org/ebooks/148","1706","1790","Franklin, Benjamin","22","May 22, 2008","5","May","2008","7","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","16.9","11.27","6.92","7321","13.0","56.93","14.4","13.5","8.8","0.14727735759944593","0.4768185158753315","4.82","31.0","0.03","318812","2428","2116","93075.3","66189" +"PA,JC","en","Political science -- Early works to 1800","Politics: A Treatise on Government","Text","749","6762","511","https://www.gutenberg.org/ebooks/6762","-384","-322","Aristotle","1","October, 2004","10","October","2004","6","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","30.0","11.33","7.52","6815","23.2","30.54","24.8","8.0","11.2","0.13134042852935468","0.49212470420499255","4.78","57.0","0.02","488832","4555","1768","148254.3","102328" +"PZ","en","India -- Juvenile fiction,Pride and vanity -- Juvenile fiction,Tiger -- Juvenile fiction,Boys -- Juvenile fiction,Children's stories","Little Black Sambo","Text","748","17824","512","https://www.gutenberg.org/ebooks/17824","1862","1946","Bannerman, Helen","22","February 22, 2006","2","February","2006","7","text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","11.0","11.95","5.88","107","6.0","80.62","8.4","6.0","3.1","0.0835477633477634","0.584110137085137","5.09","16.0","0.06","5940","35","69","1504.8","1166" +"PA","en","Classical literature;Mythology, Classical -- Poetry;Latin poetry -- Translations into English;Metamorphosis -- Mythology -- Poetry;Fables, Latin -- Translations into English","The Metamorphoses of Ovid, Books I-VII","Text","748","21765","513","https://www.gutenberg.org/ebooks/21765","-43","17","Ovid","8","June 8, 2007","6","June","2007","11","image/png,text/html,image/jpeg,text/html; charset=utf-8,text/plain; charset=us-ascii,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","13.6","11.9","6.55","14053","9.9","65.05","11.200000000000001","6.0","3.1","0.09367783133876323","0.47626123465595904","4.98","23.0","0.04","623738","3149","5429","173099.7","125286" +"PQ","en","Maxims","Reflections; or Sentences and Moral Maxims","Text","746","9105","514","https://www.gutenberg.org/ebooks/9105","1613","1680","La Rochefoucauld, Francois duc de","1","October, 2005","10","October","2005","7","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","11.6","12.18","6.7","4859","7.9","70.13","9.200000000000001","5.5","3.1","0.16301954413952185","0.5411425384221891","5.08","18.0","0.05","179394","1270","1936","49356.9","35317" +"PS","en","United States -- Social life and customs -- 19th century -- Fiction;Humorous stories, American","The Man That Corrupted Hadleyburg","Text","744","1213","515","https://www.gutenberg.org/ebooks/1213","1835","1910","Twain, Mark","1","April 1, 2005","4","April","2005","7","text/html,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.9","10.67","6.85","2705","7.2","72.16","8.4","8.0","3.1","0.09274477611102043","0.5208829284962013","4.87","16.0","0.06","85953","524","1046","24031.8","17638" +"DA","en","Great Britain -- History -- Anglo-Saxon period, 449-1066 -- Sources;Anglo-Saxons -- Early works to 1800","The Anglo-Saxon Chronicle","Text","743","657","516","https://www.gutenberg.org/ebooks/657","0","0","Unknown","1","September, 1996","9","September","1996","6","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","13.4","11.26","6.17","8350","8.7","73.51","11.200000000000001","6.5","3.1","0.16515052260401172","0.4461526575504723","4.87","23.0","0.04","461915","1958","3985","127634.4","94777" +"QA","en","Puzzles,Mathematical recreations","Amusements in Mathematics","Text","742","16713","517","https://www.gutenberg.org/ebooks/16713","1857","1930","Dudeney, Henry Ernest","17","September 17, 2005","9","September","2005","8","text/html; charset=iso-8859-1,text/plain,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","10.2","10.32","5.51","10048","6.8","78.59","9.200000000000001","8.0","3.1","0.07520533517934337","0.43513806583933134","4.81","18.0","0.06","779152","4359","8984","205561.8","162112" +"G","en","Voyages and travels;Polo, Marco, 1254-1323?;Mongols -- History;Asia -- Description and travel -- Early works to 1800","The Travels of Marco Polo — Volume 1","Text","741","10636","518","https://www.gutenberg.org/ebooks/10636","0","0","Rustichello of Pisa","8","January 8, 2004","1","January","2004","8","text/html,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","12.4","11.66","6.37","37016","8.7","68.1","10.0","14.5","3.1","0.1420976648832381","0.442754173461787","4.99","20.0","0.05","1673904","11217","16218","469475.1","335271" +"PS","en","Women -- Fiction,Black humor,Utopian fiction,Utopias -- Fiction","Herland","Text","740","32","519","https://www.gutenberg.org/ebooks/32","1860","1935","Gilman, Charlotte Perkins","10","May 10, 1992","5","May","1992","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.8","10.84","6.52","6916","7.2","72.16","8.4","7.0","3.1","0.1729446879344882","0.53168394027086","4.9","16.0","0.06","255637","1794","3179","73086.3","52145" +"BJ","en","Etiquette","Etiquette","Text","739","14314","520","https://www.gutenberg.org/ebooks/14314","1873","1960","Post, Emily","10","December 10, 2004","12","December","2004","7","application/rdf+xml,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,text/plain","12.8","11.26","6.03","16796","9.5","66.07","10.8","13.5","3.1","0.10854365285369118","0.477334221352446","4.87","22.0","0.04","994302","7025","9006","286976.7","204276" +"E151","en","United States -- Race relations,African Americans","Darkwater: Voices from Within the Veil","Text","738","15210","521","https://www.gutenberg.org/ebooks/15210","1868","1963","Du Bois, W. E. B. (William Edward Burghardt)","28","February 28, 2005","2","February","2005","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","11.9","11.49","6.82","9331","8.7","68.1","10.0","9.0","3.1","0.06572445072951862","0.467190156986487","4.96","20.0","0.05","333620","2447","3357","94956.3","67209" +"PZ,PN","en","English poetry,American poetry","Poems Every Child Should Know: The What-Every-Child-Should-Know-Library","Text","736","16436","522","https://www.gutenberg.org/ebooks/16436","0","0","Unknown","4","August 4, 2005","8","August","2005","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","11.6","10.79","6.54","8057","7.6","76.56","10.0","4.5","3.1","0.1399639267053682","0.5040799761073192","4.84","20.0","0.05","322257","595","3264","83416.5","66584" +"","en","Highlands (Scotland) -- History,Land tenure -- Scotland Highlands","The History of the Highland Clearances: Second Edition, Altered and Revised","Text","736","51271","523","https://www.gutenberg.org/ebooks/51271","1838","1898","Mackenzie, Alexander","21","February 21, 2016","2","February","2016","6","text/html,image/jpeg,text/plain; charset=utf-8,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","17.8","12.43","6.9","10965","13.0","56.93","14.4","5.0","8.8","0.07718098142281746","0.4697218894808295","5.02","31.0","0.03","503206","4009","3214","144071.1","100172" +"","en","","Prisoner of the Mill: or, Captain Hayward's ""Body Guard""","Text","736","51318","524","https://www.gutenberg.org/ebooks/51318","0","0","Hazelton, Harry","28","February 28, 2016","2","February","2016","6","image/jpeg,text/html,text/plain; charset=utf-8,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","8.9","10.32","6.25","4129","6.4","74.19","7.6000000000000005","4.0","3.1","0.06397118079196154","0.49771101014603114","4.86","14.0","0.07","165015","661","2295","46069.2","33968" +"","en","","Lex","Text","736","51362","525","https://www.gutenberg.org/ebooks/51362","0","0","Haggert, W. T.","5","March 5, 2016","3","March","2016","7","image/jpeg,text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","9.1","10.43","6.96","1248","6.8","73.17","8.0","5.5","3.1","0.04187106287432377","0.4851006495919539","4.88","15.0","0.07","37267","214","506","10641.6","7637" +"PK","en","Rama (Hindu deity) -- Poetry;Epic poetry, Sanskrit -- Translations into English;Folklore -- India","The Rámáyan of Válmíki, translated into English verse","Text","735","24869","526","https://www.gutenberg.org/ebooks/24869","0","0","Valmiki","18","March 18, 2008","3","March","2008","10","text/plain; charset=utf-8,text/plain; charset=us-ascii,text/html; charset=utf-8,application/x-mobipocket-ebook,application/prs.tei,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/pdf","12.7","11.43","5.6","23394","7.9","75.54","10.4","5.5","3.1","0.16962008289702457","0.5743996160292576","4.95","21.0","0.05","1980031","5132","18440","518013.9","400089" +"B","en","Human beings","Human, All Too Human: A Book for Free Spirits","Text","735","38145","527","https://www.gutenberg.org/ebooks/38145","1844","1900","Nietzsche, Friedrich Wilhelm","26","November 26, 2011","11","November","2011","8","text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","16.4","13.06","7.39","5734","12.3","53.55","12.4","13.5","8.8","0.10212548122666182","0.5061505394861239","5.18","26.0","0.04","190232","2476","1362","56838.6","36696" +"","en","","The Girls From Earth","Text","735","51268","528","https://www.gutenberg.org/ebooks/51268","1926","2014","Robinson, Frank M.","22","February 22, 2016","2","February","2016","8","application/x-mobipocket-ebook,image/jpeg,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","8.1","10.19","6.81","1190","5.6","76.22","6.800000000000001","5.5","3.1","0.08263482339701855","0.4569451411280676","4.89","12.0","0.08","35694","196","564","9911.7","7294" +"PQ","en","Paris (France) -- Fiction;Older men -- Fiction;French fiction -- Translations into English;France -- History -- Louis XVIII, 1814-1824 -- Fiction;Fathers and daughters -- Fiction","Father Goriot","Text","734","1237","529","https://www.gutenberg.org/ebooks/1237","1799","1850","Balzac, Honore de","1","March, 1998","3","March","1998","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","9.3","9.63","6.01","10038","6.4","79.6","8.8","13.5","3.1","0.11147353474674829","0.5082681997197646","4.69","17.0","0.06","485775","2170","6027","138978.0","103583" +"PR","en","Arthur, King -- Legends;Arthurian romances","Le Morte d'Arthur: Volume 2","Text","732","1252","530","https://www.gutenberg.org/ebooks/1252","0","1471","Malory, Thomas, Sir","1","March, 1998","3","March","1998","8","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","12.7","8.36","1.9","6708","9.1","77.91","12.8","9.0","3.1","0.23133317189072047","0.5263660373177697","4.37","27.0","0.04","819850","2020","6924","231940.8","187720" +"BF","en","Knowledge, Theory of;Consciousness;Psychology","The Analysis of Mind","Text","730","2529","531","https://www.gutenberg.org/ebooks/2529","1872","1970","Russell, Bertrand","1","February, 2001","2","February","2001","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","14.8","12.13","6.16","7222","11.9","54.56","12.0","21.0","8.8","0.05305598524344662","0.44625089660986567","5.02","25.0","0.04","446852","5231","3539","135676.8","89040" +"PR","en","Erotic stories","The Power of Mesmerism: A Highly Erotic Narrative of Voluptuous Facts and Fancies","Text","729","28521","532","https://www.gutenberg.org/ebooks/28521","0","0","Anonymous","6","April 6, 2009","4","April","2009","8","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","14.6","11.15","6.87","3106","11.1","62.01","12.4","8.0","3.1","0.11653633829791384","0.5140237350737827","4.85","26.0","0.04","121976","622","955","34313.4","25173" +"","en","","No Substitutions","Text","729","51350","533","https://www.gutenberg.org/ebooks/51350","1933","2010","Harmon, Jim","3","March 3, 2016","3","March","2016","8","application/x-mobipocket-ebook,image/jpeg,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","7.2","9.56","6.8","970","5.6","76.22","6.800000000000001","5.5","3.1","0.06887373964469769","0.49780888439571125","4.78","12.0","0.08","28500","157","484","8065.8","5959" +"","en","","Growing Up On Big Muddy","Text","729","51398","534","https://www.gutenberg.org/ebooks/51398","1911","1997","De Vet, Charles V. (Charles Vincent)","8","March 8, 2016","3","March","2016","8","application/x-mobipocket-ebook,image/jpeg,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","8.7","10.78","7.41","1100","6.0","75.2","7.2","5.0","3.1","0.08411922989235132","0.44097029923619513","4.94","13.0","0.07","27406","184","405","7785.0","5553" +"BF","en","Folklore -- India;Occultism -- India, South;Omens;Dravidians -- Folklore;Superstition -- India, South","Omens and Superstitions of Southern India","Text","724","35690","535","https://www.gutenberg.org/ebooks/35690","1855","1935","Thurston, Edgar","26","March 26, 2011","3","March","2011","9","text/plain,image/jpeg,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/html; charset=us-ascii","12.8","11.03","6.44","10354","9.5","66.07","10.8","11.5","3.1","0.033284695446397256","0.4320990663296517","4.83","22.0","0.04","461876","3261","4163","134550.0","95608" +"PR","en","Mothers and daughters -- Drama,Aristocracy (Social class) -- Drama,Marriage -- Drama","Lady Windermere's Fan","Text","724","790","536","https://www.gutenberg.org/ebooks/790","1854","1900","Wilde, Oscar","26","October 26, 2014","10","October","2014","6","text/html,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","6.4","9.54","5.68","2009","4.4","79.26","5.6000000000000005","3.5","3.1","0.05425811352354649","0.550640450750721","4.93","9.0","0.11","97694","289","2167","26986.5","19823" +"PR","en","Sonnets, English;English poetry","Shakespeare's Sonnets","Text","723","1041","537","https://www.gutenberg.org/ebooks/1041","1564","1616","Shakespeare, William","1","September, 1997","9","September","1997","7","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","17.9","10.34","7.19","2091","11.8","70.81","15.600000000000001","26.5","3.1","0.1657473171273164","0.5568314774114779","4.66","34.0","0.03","82358","98","509","21980.7","17682" +"","en","","The Mentor: The Metropolitan Museum of Art, Vol. 6, Num. 9, Serial No. 157, June 15, 1918","Text","723","51340","538","https://www.gutenberg.org/ebooks/51340","0","0","Noe, Sydney P.","1","March 1, 2016","3","March","2016","7","image/jpeg,text/plain; charset=utf-8,text/html; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","11.8","12.58","7.71","1955","8.7","62.68","8.8","5.5","3.1","0.21513039640612275","0.4769510308765758","5.2","17.0","0.06","49637","446","544","14044.5","9545" +"PS","en","Prose poems","Tender Buttons: Objects—Food—Rooms","Text","722","15396","539","https://www.gutenberg.org/ebooks/15396","1874","1946","Stein, Gertrude","17","March 17, 2005","3","March","2005","8","text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","8.4","8.87","6.61","2068","7.2","72.16","8.4","4.5","3.1","0.08657355694555331","0.47177428000902977","4.56","16.0","0.06","68339","370","891","20475.0","14971" +"E300","en","Fugitive slaves -- United States -- Biography,Fugitive slaves -- United States -- History -- 19th century,Underground Railroad,Antislavery movements -- United States -- History -- 19th century,Abolitionists -- United States -- Biography","The Underground Railroad: A Record of Facts, Authentic Narratives, Letters, &c., Narrating the Hardships, Hair-Breadth Escapes and Death Struggles of the Slaves in Their Efforts for Freedom, As Related by Themselves and Others, or Witnessed by the Author.","Text","721","15263","540","https://www.gutenberg.org/ebooks/15263","1821","1902","Still, William","5","March 5, 2005","3","March","2005","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","12.2","11.02","5.68","25467","9.1","67.08","10.4","11.0","3.1","0.1177308434640337","0.4812606738549223","4.88","21.0","0.05","1969355","13163","18936","564976.8","403272" +"PR","en","England -- Social life and customs -- 19th century -- Fiction,Theatrical companies -- Fiction,Poor families -- Fiction,Bildungsromans,Picaresque literature,England -- Fiction,Boarding schools -- Fiction,Young men -- Fiction","Nicholas Nickleby","Text","721","967","541","https://www.gutenberg.org/ebooks/967","1812","1870","Dickens, Charles","27","April 27, 2006","4","April","2006","8","application/x-mobipocket-ebook,image/jpeg,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","11.8","11.37","5.7","22937","8.3","69.11","9.600000000000001","14.0","3.1","0.10045983794722292","0.5053049590767626","4.94","19.0","0.05","1592784","9785","16183","443869.2","322303" +"PR","en","Unmarried couples -- Fiction,Wessex (England) -- Fiction,Illegitimate children -- Fiction,Love stories,Children -- Death -- Fiction,Didactic fiction,Stonemasons -- Fiction,Adultery -- Fiction","Jude the Obscure","Text","720","153","542","https://www.gutenberg.org/ebooks/153","1840","1928","Hardy, Thomas","1","August, 1994","8","August","1994","8","application/rdf+xml,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,text/plain","9.2","10.09","5.96","13910","6.0","80.62","8.4","9.0","3.1","0.054030616478408136","0.4779028737010099","4.77","16.0","0.06","686001","4085","8767","194140.8","143965" +"PZ,PS","en","Universities and colleges -- Fiction,Schools -- Fiction,Philanthropists -- Fiction,Epistolary fiction,Orphans -- Fiction,Bildungsromans,Women college students -- Fiction,Letters -- Fiction,Boarding schools -- Fiction,Women authors -- Fiction,Young women -- Fiction,Love stories","Daddy-Long-Legs","Text","718","157","543","https://www.gutenberg.org/ebooks/157","1876","1916","Webster, Jean","9","June 9, 2008","6","June","2008","6","text/html,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","8.1","9.45","6.24","4473","5.2","82.65","7.6000000000000005","13.5","3.1","0.10867507730210725","0.5058662420528458","4.71","14.0","0.07","174193","1025","2513","49631.4","36951" +"PR","en","Married women -- Fiction,Landlord and tenant -- Fiction,Alcoholics -- Fiction,England -- Social life and customs -- 19th century -- Fiction,England -- Fiction,Domestic fiction","The Tenant of Wildfell Hall","Text","718","969","544","https://www.gutenberg.org/ebooks/969","1820","1849","Bronte, Anne","2","February 2, 2010","2","February","2010","7","text/html,text/plain; charset=utf-8,text/plain; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","12.4","10.51","6.14","14540","9.9","65.05","11.200000000000001","11.0","3.1","0.09122811176435702","0.5195436739863183","4.74","23.0","0.04","798839","4785","7296","229651.2","168520" +"PE","en","English language -- Terms and phrases","Fifteen Thousand Useful Phrases: A Practical Handbook Of Pertinent Expressions, Striking Similes, Literary, Commercial, Conversational, And Oratorical Terms, For The Embellishment Of Speech And Literature, And The Improvement Of The Vocabulary Of Those Persons Who Read, Write, And Speak English","Text","717","18362","545","https://www.gutenberg.org/ebooks/18362","1868","1953","Kleiser, Grenville","10","May 10, 2006","5","May","2006","7","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","125.1","19.46","17.9","13477","96.1","-175.51","96.0","6.0","28.7","0.09818513553187844","0.5986855126987548","6.08","235.0","0.0","496119","7003","346","137055.6","81607" +"","en","","Plain Living: A Bush Idyll","Text","717","51404","546","https://www.gutenberg.org/ebooks/51404","1826","1915","Boldrewood, Rolf","8","March 8, 2016","3","March","2016","7","image/jpeg,text/plain; charset=utf-8,text/html; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","10.2","11.25","6.46","9840","7.2","72.16","8.4","7.0","3.1","0.15058088323746835","0.5134756703226394","4.97","16.0","0.06","381201","2619","4644","108207.0","76638" +"PS,HM","en","Government, Resistance to;Civil disobedience","On the Duty of Civil Disobedience","Text","717","71","547","https://www.gutenberg.org/ebooks/71","1817","1862","Thoreau, Henry David","12","12 June 2004","6","June","2004","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","13.9","10.16","7.44","1487","11.1","62.01","12.4","14.0","8.8","0.11175798117407713","0.5096676466607967","4.68","26.0","0.04","43665","390","352","13063.5","9333" +"PR","en","Political fiction,Kings and rulers -- Fiction,British -- Afghanistan -- Fiction,Afghanistan -- Fiction","The Man Who Would Be King","Text","714","8147","548","https://www.gutenberg.org/ebooks/8147","1865","1936","Kipling, Rudyard","1","May, 2005","5","May","2005","8","text/html; charset=utf-8,text/plain; charset=us-ascii,text/plain; charset=utf-8,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","8.7","8.93","6.45","1767","6.4","79.6","8.8","13.0","3.1","0.06080768825544365","0.43278862233970516","4.57","17.0","0.06","64923","227","822","18047.7","14194" +"BR","en","Christianity -- Essence, genius, nature;Apologetics;Chesterton, G. K. (Gilbert Keith), 1874-1936","Orthodoxy","Text","713","130","549","https://www.gutenberg.org/ebooks/130","1874","1936","Chesterton, G. K. (Gilbert Keith)","1","May, 1994","5","May","1994","6","text/html,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","10.8","10.1","6.37","7018","8.7","68.1","10.0","7.5","3.1","0.07512382502204813","0.5124968840825791","4.72","20.0","0.05","300901","2760","3186","90873.0","63809" +"PR","en","Scotland -- Kings and rulers -- Drama;Tragedies;Macbeth, King of Scotland, active 11th century -- Drama;Regicides -- Drama","The Tragedy of Macbeth","Text","712","1129","550","https://www.gutenberg.org/ebooks/1129","1564","1616","Shakespeare, William","1","January 1, 1623","1","January","1623","7","text/html,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","8.2","10.19","6.39","2439","4.8","83.66","7.2","52.0","3.1","0.12241477342081762","0.5054136483579605","4.89","13.0","0.08","89223","165","1392","23570.1","18248" +"PR,CT","en","Johnson, Samuel, 1709-1784;Critics -- Great Britain -- Biography;Lexicographers -- Great Britain -- Biography;Authors, English -- 18th century -- Biography","Boswell's Life of Johnson: Abridged and edited, with an introduction by Charles Grosvenor Osgood","Text","712","1564","551","https://www.gutenberg.org/ebooks/1564","1740","1795","Boswell, James","12","May 12, 2006","5","May","2006","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","11.4","10.44","5.89","17347","8.7","68.1","10.0","27.5","3.1","0.1573372142556024","0.5129203690654986","4.78","20.0","0.05","1037653","7302","10561","300604.5","217186" +"","en","","License to Steal","Text","710","51420","552","https://www.gutenberg.org/ebooks/51420","0","0","Newman, Louis","11","March 11, 2016","3","March","2016","8","application/x-mobipocket-ebook,image/jpeg,text/html; charset=us-ascii,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","16.2","13.52","8.49","774","11.9","54.56","12.0","6.5","8.8","0.09092825334760814","0.5078942005823726","5.26","25.0","0.04","17803","191","132","5143.5","3383" +"","en","","A Queen of Tears, vol. 1 of 2: Caroline Matilda, Queen of Denmark and Norway and Princess; of Great Britain and Ireland","Text","709","51368","553","https://www.gutenberg.org/ebooks/51368","1860","1905","Wilkins, W. H. (William Henry)","5","March 5, 2016","3","March","2016","8","image/jpeg,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","14.3","12.48","6.46","9697","11.1","56.59","11.200000000000001","3.5","8.8","0.1211743733310452","0.4714989594417424","5.08","23.0","0.04","462143","3881","3837","132806.7","90906" +"","en","","The Music Master of Babylon","Text","704","51379","554","https://www.gutenberg.org/ebooks/51379","1909","1976","Pangborn, Edgar","6","March 6, 2016","3","March","2016","8","text/plain,image/jpeg,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.5","10.96","7.2","1893","6.8","73.17","8.0","5.5","3.1","0.0700478233664075","0.46413268093208915","4.92","15.0","0.06","52077","313","683","14535.9","10584" +"PR","en","Sonnets, English;Love poetry, English","Sonnets from the Portuguese","Text","696","2002","555","https://www.gutenberg.org/ebooks/2002","1806","1861","Browning, Elizabeth Barrett","14","September 14, 2004","9","September","2004","8","image/jpeg,text/plain; charset=utf-8,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","11.6","9.98","6.85","753","7.9","75.54","10.4","13.0","3.1","0.20130448624464584","0.5383949280624811","4.7","21.0","0.05","25781","58","251","6855.3","5482" +"B","en","Philosophy, German","Essays of Schopenhauer","Text","693","11945","556","https://www.gutenberg.org/ebooks/11945","1788","1860","Schopenhauer, Arthur","7","April 7, 2004","4","April","2004","8","text/html,text/plain; charset=utf-8,text/plain; charset=us-ascii,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","17.4","12.14","7.02","8738","13.8","49.49","14.0","12.0","8.8","0.11044216250082563","0.5084777271500645","4.97","30.0","0.03","362987","4025","2373","109003.5","72966" +"PR","en","Athens (Greece) -- Drama,Courtship -- Drama,Fairy plays,Comedies","A Midsummer Night's Dream","Text","692","2242","557","https://www.gutenberg.org/ebooks/2242","1564","1616","Shakespeare, William","1","January 1, 1600","1","January","1600","7","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","9.2","9.74","6.41","2214","6.0","80.62","8.4","13.5","3.1","0.1603930965695396","0.5228017219083708","4.71","16.0","0.06","83258","124","1051","22693.5","17672" +"","en","","The Principles of Chemistry Volume I (of 2)","Text","691","51326","558","https://www.gutenberg.org/ebooks/51326","0","0","Mendeleyev, Dmitry Ivanovich","29","February 29, 2016","2","February","2016","7","image/jpeg,text/html,text/plain,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","16.7","14.05","2.02","17861","13.0","46.1","12.0","4.0","8.8","0.08867939154873662","0.4493949833867777","5.35","25.0","0.04","1932265","22826","14008","560575.8","361074" +"PR","en","Caesar, Julius -- Assassination -- Drama;Tragedies;Conspiracies -- Drama;Rome -- History -- Civil War, 43-31 B.C. -- Drama;Brutus, Marcus Junius, 85 B.C.?-42 B.C. -- Drama;Assassins -- Drama","The Tragedy of Julius Caesar","Text","689","1120","559","https://www.gutenberg.org/ebooks/1120","1564","1616","Shakespeare, William","1","January 1, 1623","1","January","1623","7","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","7.5","9.38","6.03","2311","4.8","83.66","7.2","55.0","3.1","0.14157692795929","0.5329884396891823","4.75","13.0","0.08","99045","146","1582","27023.4","20842" +"PZ","en","Fairy tales,Fairy tales -- Germany","Grimm's Fairy Stories","Text","688","11027","560","https://www.gutenberg.org/ebooks/11027","1785","1863","Grimm, Jacob","10","February 10, 2004","2","February","2004","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","11.4","8.71","5.84","3417","7.5","81.97","11.200000000000001","13.5","3.1","0.0975629574094278","0.49605440956183594","4.43","23.0","0.04","224364","333","2110","62066.7","50621" +"DC","en","Private secretaries -- France -- Biography;Napoleon I, Emperor of the French, 1769-1821 -- Contemporaries;Napoleon I, Emperor of the French, 1769-1821;Bourrienne, Louis Antoine Fauvelet de, 1769-1834;Napoleon I, Emperor of the French, 1769-1821 -- Relations with private secretaries","Memoirs of Napoleon Bonaparte — Complete","Text","688","3567","561","https://www.gutenberg.org/ebooks/3567","1769","1834","Bourrienne, Louis Antoine Fauvelet de","3","September 3, 2006","9","September","2006","8","image/jpeg,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","13.5","12.07","5.67","29300","10.7","57.61","10.8","5.0","8.8","0.10415693730414262","0.47444771092204024","5.01","22.0","0.04","2454011","22188","21668","727113.6","489658" +"D","en","Sea-power;Naval history, Modern","The Influence of Sea Power Upon History, 1660-1783","Text","687","13529","562","https://www.gutenberg.org/ebooks/13529","1840","1914","Mahan, A. T. (Alfred Thayer)","26","September 26, 2004","9","September","2004","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","17.6","12.89","6.15","14364","13.4","50.5","13.600000000000001","5.5","8.8","0.09620600195469764","0.4010396072321673","5.1","29.0","0.03","1076282","8739","7045","307634.4","211227" +"PR","en","Horror tales","The Wendigo","Text","686","10897","563","https://www.gutenberg.org/ebooks/10897","1869","1951","Blackwood, Algernon","31","January 31, 2004","1","January","2004","8","application/rdf+xml,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/html; charset=iso-8859-1,text/plain","12.3","11.6","7.06","2826","8.7","68.1","10.0","14.0","3.1","0.03528779211642385","0.5132073150848138","4.98","20.0","0.05","91490","558","892","25988.4","18383" +"","en","","Swenson, Dispatcher","Text","686","51331","564","https://www.gutenberg.org/ebooks/51331","1910","1958","Miller, R. DeWitt","29","February 29, 2016","2","February","2016","8","image/jpeg,text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","8.3","11.63","6.91","1351","4.8","78.25","6.0","5.0","3.1","0.08252213820808464","0.42540750358628","5.24","10.0","0.1","40224","252","759","10917.9","7673" +"","en","","A Dog Day: or The Angel in the House","Text","685","51306","565","https://www.gutenberg.org/ebooks/51306","0","0","Emanuel, Walter","26","February 26, 2016","2","February","2016","7","image/jpeg,text/html,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","8.8","12.21","7.07","341","3.7","86.71","6.0","4.0","3.1","0.09915719381628478","0.5096466160102526","5.34","10.0","0.1","9778","66","180","2414.7","1830" +"PA","en","Folly -- Early works to 1800","In Praise of Folly: Illustrated with Many Curious Cuts","Text","684","30201","566","https://www.gutenberg.org/ebooks/30201","1469","1536","Erasmus, Desiderius","6","October 6, 2009","10","October","2009","8","image/jpeg,text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","26.3","11.85","8.4","6630","20.0","38.66","21.6","11.0","8.8","0.14424891195495612","0.5096972490411023","4.87","49.0","0.02","218530","1621","906","64078.2","44850" +"PZ,PR","en","Conduct of life -- Juvenile poetry;Children's poetry, English","Cautionary Tales for Children","Text","681","27424","567","https://www.gutenberg.org/ebooks/27424","1870","1953","Belloc, Hilaire","5","December 5, 2008","12","December","2008","8","image/jpeg,text/html; charset=iso-8859-1,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","13.3","14.73","7.62","541","7.2","72.16","8.4","8.5","3.1","-0.014003615269761098","0.5638203783870455","5.57","16.0","0.06","14885","129","158","3732.3","2674" +"TX","en","Cookbooks;Cooking, Roman -- Early works to 1800","Cookery and Dining in Imperial Rome","Text","681","29728","568","https://www.gutenberg.org/ebooks/29728","0","0","Apicius","19","August 19, 2009","8","August","2009","8","text/plain; charset=utf-8,text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","12.9","13.92","6.93","16425","7.6","71.14","8.8","7.0","3.1","0.08625868877096335","0.4656141962394462","5.43","17.0","0.06","573945","4909","6028","152045.1","105698" +"PN","en","Ghost stories,Short stories","Famous Modern Ghost Stories","Text","680","15143","569","https://www.gutenberg.org/ebooks/15143","0","0","Unknown","22","February 22, 2005","2","February","2005","8","text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","9.3","10.09","6.18","10505","7.2","72.16","8.4","7.5","3.1","0.05030376235146195","0.48915132130049793","4.77","16.0","0.06","451838","2254","5719","128006.1","94666" +"TX","en","Cooking, English;Home economics","The Book of Household Management","Text","679","10136","570","https://www.gutenberg.org/ebooks/10136","1836","1865","Beeton, Mrs. (Isabella Mary)","19","November 19, 2003","11","November","2003","7","text/html,text/plain; charset=us-ascii,text/plain,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","12.4","11.66","5.52","29035","8.7","68.1","10.0","7.5","3.1","0.09035044687865713","0.47927716458676545","4.99","20.0","0.05","2569503","16590","25007","704001.6","514564" +"HC","en","Economic history -- 1918-1945;Treaty of Versailles (1919);World War, 1914-1918 -- Economic aspects","The Economic Consequences of the Peace","Text","679","15776","571","https://www.gutenberg.org/ebooks/15776","1883","1946","Keynes, John Maynard","6","May 6, 2005","5","May","2005","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","16.9","13.23","6.66","7434","12.6","52.53","12.8","14.5","8.8","0.0835230092715872","0.4234098546333508","5.21","27.0","0.04","362587","4237","2520","106057.8","69597" +"F2155,G","en","Pirates -- Early works to 1800","A General History of the Pyrates:: from their first rise and settlement in the island of Providence, to the present time","Text","677","40580","572","https://www.gutenberg.org/ebooks/40580","0","1731","Defoe, Daniel","25","August 25, 2012","8","August","2012","9","image/jpeg,text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","21.9","12.03","7.05","11651","16.5","47.8","18.0","27.0","3.1","0.09163085063890603","0.4504905915531333","4.9","40.0","0.02","633069","3051","3189","175989.6","129089" +"","en","","Stories from The Arabian Nights","Text","676","51432","573","https://www.gutenberg.org/ebooks/51432","1865","1959","Housman, Laurence","13","March 13, 2016","3","March","2016","7","image/jpeg,text/plain; charset=utf-8,text/html; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","15.3","10.4","6.89","3297","12.2","58.96","13.600000000000001","15.0","3.1","0.1210483564936724","0.5207339267240131","4.67","29.0","0.03","134089","655","973","38831.4","28729" +"PZ","en","Fantasy,Animals -- Juvenile fiction","The Story of Doctor Dolittle","Text","675","501","574","https://www.gutenberg.org/ebooks/501","1886","1947","Lofting, Hugh","1","April, 1996","4","April","1996","7","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","7.7","8.75","5.8","2330","5.6","81.63","8.0","18.5","3.1","0.07234424898134213","0.4811182162579015","4.59","15.0","0.07","119068","364","1718","32674.5","25955" +"GT,D","en","Renaissance,Manners and customs,Clothing and dress,Middle Ages","Manners, Customs, and Dress During the Middle Ages and During the Renaissance Period","Text","674","10940","575","https://www.gutenberg.org/ebooks/10940","1806","1884","Jacob, P. L.","4","February 4, 2004","2","February","2004","9","text/html,text/html; charset=utf-8,text/plain; charset=us-ascii,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","16.3","13.23","6.6","16719","12.3","53.55","12.4","9.0","8.8","0.1057691741822772","0.46464848085663535","5.21","26.0","0.04","820838","7707","5989","236169.9","157577" +"PA","en","Rome -- Politics and government -- 265-30 B.C.;Happiness -- Early works to 1800;Theology -- Early works to 1800;Gods, Roman -- Early works to 1800;State, The -- Early works to 1800;Political science -- Early works to 1800","Cicero's Tusculan Disputations: Also, Treatises On The Nature Of The Gods, And On The Commonwealth","Text","674","14988","576","https://www.gutenberg.org/ebooks/14988","-106","-43","Cicero, Marcus Tullius","9","February 9, 2005","2","February","2005","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","16.7","11.33","6.45","15201","12.6","57.95","14.0","4.0","8.8","0.15112411087265473","0.5267051723938848","4.83","30.0","0.03","876187","7118","5909","259235.1","181274" +"ML","en","Operas -- Librettos","The Complete Plays of Gilbert and Sullivan","Text","671","808","577","https://www.gutenberg.org/ebooks/808","1836","1911","Gilbert, W. S. (William Schwenck)","1","February, 1997","2","February","1997","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","8.6","11.12","5.98","17882","5.6","76.22","6.800000000000001","6.5","3.1","0.14168640370359223","0.5610648141683724","5.05","12.0","0.08","814526","4355","12962","219984.3","161243" +"PR","en,enm","Arthurian romances,Gawain (Legendary character) -- Romances","Sir Gawayne and the Green Knight: An Alliterative Romance-Poem (c. 1360 A.D.)","Text","669","14568","578","https://www.gutenberg.org/ebooks/14568","0","0","Unknown","3","January 3, 2005","1","January","2005","9","application/rdf+xml,text/html,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,text/plain","12.3","9.81","6.85","5026","9.1","72.5","11.600000000000001","5.0","3.1","0.18795819038122688","0.5003169234342478","4.62","24.0","0.04","181520","150","1635","49804.2","39281" +"PJ","en","Tales -- Arab countries,Fairy tales","The Book of the Thousand Nights and a Night — Volume 01","Text","667","3435","579","https://www.gutenberg.org/ebooks/3435","0","0","Unknown","1","September, 2003","9","September","2003","8","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","13.5","9.81","6.37","15885","9.9","70.47","12.4","6.5","3.1","0.11274214559939183","0.46722544023700285","4.62","26.0","0.04","802408","2464","6625","224472.6","173812" +"","en","","Composition","Text","667","45410","580","https://www.gutenberg.org/ebooks/45410","1857","1922","Dow, Arthur Wesley","15","April 15, 2014","4","April","2014","11","application/prs.tei,text/plain; charset=us-ascii,text/html; charset=utf-8,application/pdf,text/plain; charset=utf-8,application/octet-stream,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","12.5","13.17","6.97","3662","9.1","61.67","9.200000000000001","12.0","3.1","0.12775809839298488","0.42871286206311815","5.25","18.0","0.05","124599","1192","1287","36196.2","23734" +"PR","en","Christian poetry;Historical poetry;Great Britain -- History -- Alfred, 871-899 -- Poetry;Epic poetry;Alfred, King of England, 849-899 -- Poetry;White Horse, Vale of (England) -- Poetry","The Ballad of the White Horse","Text","666","1719","581","https://www.gutenberg.org/ebooks/1719","1874","1936","Chesterton, G. K. (Gilbert Keith)","1","April, 1999","4","April","1999","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","15.8","9.99","6.81","1805","10.7","73.85","14.4","10.5","3.1","0.049162844144531856","0.46346588902958197","4.6","31.0","0.03","80392","58","562","20994.3","17475" +"PQ","en","Phaedra (Greek mythology) -- Drama,Tragedies","Phaedra","Text","665","1977","582","https://www.gutenberg.org/ebooks/1977","1639","1699","Racine, Jean","1","November, 1999","11","November","1999","6","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.0","10.32","6.63","2035","5.2","82.65","7.6000000000000005","14.5","3.1","0.049413822217696454","0.5453539517498501","4.86","14.0","0.07","67979","239","934","18495.9","14001" +"","en","","Man of Distinction","Text","665","51288","583","https://www.gutenberg.org/ebooks/51288","1928","1988","Shaara, Michael","23","February 23, 2016","2","February","2016","8","image/jpeg,text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.9","11.36","7.61","437","8.0","64.71","8.0","7.5","3.1","0.12559537295518608","0.541908116545967","5.04","15.0","0.07","10770","113","141","3135.6","2139" +"PR","en","Conflict of generations -- Fiction,England -- Fiction,Water mills -- Fiction,Young women -- Fiction,Vendetta -- Fiction,Brothers and sisters -- Fiction,Loss (Psychology) -- Fiction,Domestic fiction,Psychological fiction,Love stories","The Mill on the Floss","Text","663","6688","584","https://www.gutenberg.org/ebooks/6688","1819","1880","Eliot, George","1","October, 2004","10","October","2004","8","application/rdf+xml,text/plain; charset=utf-8,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","11.5","10.15","5.91","16055","7.9","75.54","10.4","3.0","3.1","0.08803533471396734","0.5127243496035157","4.73","21.0","0.05","977083","5313","9664","275125.5","206412" +"PR","en","Psychological fiction,Indonesia -- Fiction,British -- Indonesia -- Fiction,Atonement -- Fiction,Merchant marine -- Officers -- Fiction,Cowardice -- Fiction","Lord Jim","Text","662","5658","585","https://www.gutenberg.org/ebooks/5658","1857","1924","Conrad, Joseph","9","January 9, 2006","1","January","2006","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.5","9.51","6.08","13071","6.4","79.6","8.8","6.5","3.1","0.05015819805352269","0.49929600697964704","4.67","17.0","0.06","601440","3357","7197","173457.0","128708" +"PS","en","Manners and customs -- Fiction,Short stories","The Piazza Tales","Text","659","15859","586","https://www.gutenberg.org/ebooks/15859","1819","1891","Melville, Herman","18","May 18, 2005","5","May","2005","8","text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","14.3","12.42","7.1","11661","11.1","56.59","11.200000000000001","8.0","3.1","0.06015229859691268","0.46058494879198003","5.07","23.0","0.04","401166","2848","3345","114809.4","79165" +"ND","en","Drawing -- Technique -- Early works to 1800;Painting -- Technique -- Early works to 1800;Leonardo, da Vinci, 1452-1519","A Treatise on Painting","Text","659","46915","587","https://www.gutenberg.org/ebooks/46915","1452","1519","Leonardo, da Vinci","20","September 20, 2014","9","September","2014","8","image/jpeg,text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","13.8","11.84","6.22","6606","9.9","65.05","11.200000000000001","8.5","3.1","0.10959426990796454","0.43628368910019993","4.97","23.0","0.04","359364","2048","3061","100051.2","72270" +"PR","en","Ghost stories;Scrooge, Ebenezer (Fictitious character) -- Fiction;Poor families -- Fiction;Christmas stories;London (England) -- Fiction;Misers -- Fiction;Sick children -- Fiction","A Christmas Carol","Text","658","19337","588","https://www.gutenberg.org/ebooks/19337","1812","1870","Dickens, Charles","20","September 20, 2006","9","September","2006","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","9.3","10.09","6.47","3783","6.0","80.62","8.4","14.0","3.1","0.10650348721093597","0.500442453622125","4.77","16.0","0.06","139805","480","1763","38523.6","29282" +"PR","en","Shropshire (England) -- Poetry","A Shropshire Lad","Text","658","5720","589","https://www.gutenberg.org/ebooks/5720","1859","1936","Housman, A. E. (Alfred Edward)","1","May, 2004","5","May","2004","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","13.3","10.33","6.78","1091","8.3","79.94","12.0","14.0","3.1","0.09023451194592126","0.5356573258955803","4.71","25.0","0.04","42616","66","360","10955.7","9046" +"B","en","Essays,Philosophy,Belief and doubt","The Will to Believe, and Other Essays in Popular Philosophy","Text","655","26659","590","https://www.gutenberg.org/ebooks/26659","1842","1910","James, William","8","May 8, 2009","5","May","2009","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","14.6","12.07","6.67","11823","11.5","55.58","11.600000000000001","14.0","8.8","0.09670421986202918","0.49484731476420246","5.01","24.0","0.04","507099","5910","4068","150146.1","101183" +"PR","en","Epistolary fiction,Essays,England -- Social life and customs -- 18th century -- Fiction","Love and Freindship [sic]","Text","654","1212","591","https://www.gutenberg.org/ebooks/1212","1775","1817","Austen, Jane","1","February, 1998","2","February","1998","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","14.1","10.57","7.0","4366","11.1","62.01","12.4","13.0","3.1","0.14207000337454678","0.5470071157829467","4.75","26.0","0.04","157906","1091","1263","47058.3","33252" +"","en","","Slaveholding: Weighed in the Balance of Truth","Text","654","51371","592","https://www.gutenberg.org/ebooks/51371","0","0","Fitch, Charles","5","March 5, 2016","3","March","2016","8","image/jpeg,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","14.0","9.75","7.16","1455","10.3","69.45","12.8","8.5","3.1","0.07508725096805852","0.4943570703305219","4.61","27.0","0.04","48382","276","382","14118.3","10497" +"PA","en","Tragedies,Oedipus (Greek mythological figure) -- Drama","Oedipus King of Thebes: Translated into English Rhyming Verse with Explanatory Notes","Text","652","27673","593","https://www.gutenberg.org/ebooks/27673","-496","-406","Sophocles","31","December 31, 2008","12","December","2008","8","text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","8.5","10.49","6.1","2105","4.8","83.66","7.2","11.0","3.1","0.09358342241262729","0.5260043572658768","4.89","13.0","0.07","89076","193","1317","22861.8","18226" +"","en","","Bullet With His Name","Text","652","51436","594","https://www.gutenberg.org/ebooks/51436","1910","1992","Leiber, Fritz","13","March 13, 2016","3","March","2016","8","application/x-mobipocket-ebook,image/jpeg,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","10.7","11.42","7.26","2084","7.6","71.14","8.8","8.5","3.1","0.04765270901259916","0.45165860133104424","5.0","17.0","0.06","59235","402","692","16668.0","11842" +"LB","en","Education -- Early works to 1800","Emile","Text","652","5427","595","https://www.gutenberg.org/ebooks/5427","1712","1778","Rousseau, Jean-Jacques","1","April, 2004","4","April","2004","6","text/html,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","13.1","9.75","5.82","15129","10.7","63.02","12.0","18.0","3.1","0.12216112199522268","0.5309887705453191","4.61","25.0","0.04","1160348","6504","9816","344070.9","251964" +"BL","en","Mythology, Norse","Myths of the Norsemen: From the Eddas and Sagas","Text","650","28497","596","https://www.gutenberg.org/ebooks/28497","1859","1929","Guerber, H. A. (Helene Adeline)","4","April 4, 2009","4","April","2009","8","image/jpeg,text/html,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","17.6","12.43","6.85","10943","12.6","57.95","14.0","1.0","3.1","0.12295946051883852","0.5301598179628938","5.02","30.0","0.03","503971","2478","3269","139669.2","100347" +"BL","en","Religion,Mythology,Magic,Superstition","The Golden Bough: A Study of Magic and Religion","Text","650","3623","597","https://www.gutenberg.org/ebooks/3623","1854","1941","Frazer, James George","1","January, 2003","1","January","2003","7","text/html,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","15.6","10.69","6.03","24787","12.2","58.96","13.600000000000001","2.0","3.1","0.07326131844501996","0.4439321757729526","4.72","29.0","0.03","1933100","12904","13814","569884.5","409963" +"","en","","How the Other Half Lives: Studies Among the Tenements of New York","Text","649","45502","598","https://www.gutenberg.org/ebooks/45502","1849","1914","Riis, Jacob A. (Jacob August)","26","April 26, 2014","4","April","2014","9","image/jpeg,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","12.9","11.03","6.59","9369","9.9","65.05","11.200000000000001","13.5","3.1","0.05609847117458665","0.4583627448136485","4.83","23.0","0.04","394043","2610","3522","113366.7","81588" +"PR","en","Romeo (Fictitious character) -- Drama,Verona (Italy) -- Drama,Conflict of generations -- Drama,Juliet (Fictitious character) -- Drama,Vendetta -- Drama,Youth -- Drama","Romeo and Juliet","Text","648","1513","599","https://www.gutenberg.org/ebooks/1513","1564","1616","Shakespeare, William","1","January 1, 1597","1","January","1597","7","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","9.3","10.66","6.25","3014","5.6","81.63","8.0","2.5","3.1","0.1485039781881601","0.5385342332159231","4.92","15.0","0.07","125550","233","1687","32728.5","25512" +"PS","en","Speeches, addresses, etc., American","Mark Twain's Speeches","Text","648","3188","600","https://www.gutenberg.org/ebooks/3188","1835","1910","Twain, Mark","19","August 19, 2006","8","August","2006","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","9.5","9.46","6.2","9777","6.8","78.59","9.200000000000001","61.0","3.1","0.14786012455254366","0.4859673876281139","4.61","18.0","0.05","425130","2919","4988","124439.4","92182" +"PR","en","Humorous stories, English;Short stories","The Man with Two Left Feet, and Other Stories","Text","648","7471","601","https://www.gutenberg.org/ebooks/7471","1881","1975","Wodehouse, P. G. (Pelham Grenville)","1","February, 2005","2","February","2005","7","text/html,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","7.0","8.87","5.87","7123","4.8","83.66","7.2","11.0","3.1","0.09005865583848871","0.48179573921903723","4.61","13.0","0.07","327280","1542","5308","92072.7","70979" +"PT","de","Fairy tales -- Denmark","Märchen für Kinder","Text","645","19163","602","https://www.gutenberg.org/ebooks/19163","1805","1875","Andersen, H. C. (Hans Christian)","3","September 3, 2006","9","September","2006","8","image/jpeg,text/html; charset=utf-8,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","11.3","13.16","6.4","7195","6.8","73.17","8.0","5.5","3.1","0.4421593834655454","0.6949494949494951","5.35","15.0","0.07","301721","1129","3736","77601.6","56394" +"PR","en","Gentry -- England -- Fiction,Sisters -- Fiction,Social classes -- Fiction,England -- Social life and customs -- 19th century -- Fiction,England -- Fiction,Mate selection -- Fiction,Regency fiction,Inheritance and succession -- Fiction,Domestic fiction,Young women -- Fiction,Love stories","Sense and Sensibility","Text","645","21839","603","https://www.gutenberg.org/ebooks/21839","1775","1817","Austen, Jane","15","June 15, 2007","6","June","2007","7","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","12.4","10.85","5.89","9350","9.1","67.08","10.4","9.0","3.1","0.13173331368006805","0.5320798001348899","4.85","21.0","0.05","591337","4047","5566","171572.4","121839" +"PZ","en","Fairy tales -- Denmark;Fairy tales;Short stories;Children's stories, Danish -- Translations into English","Fairy Tales of Hans Christian Andersen","Text","645","27200","604","https://www.gutenberg.org/ebooks/27200","1805","1875","Andersen, H. C. (Hans Christian)","8","November 8, 2008","11","November","2008","7","text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","10.3","9.17","5.47","19702","7.6","76.56","10.0","52.0","3.1","0.13896985451154165","0.5087539073792912","4.56","20.0","0.05","1692906","4307","18021","473450.4","371292" +"NK","en","Furniture -- History","Illustrated History of Furniture: From the Earliest to the Present Time","Text","644","12254","605","https://www.gutenberg.org/ebooks/12254","1850","1930","Litchfield, Frederick","4","May 4, 2004","5","May","2004","8","text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","15.4","14.28","6.77","9840","10.7","57.61","10.8","6.0","8.8","0.14622413765851122","0.4216046514969629","5.39","22.0","0.04","410770","3900","3317","117376.2","76222" +"","en","","End as a Hero","Text","644","51267","606","https://www.gutenberg.org/ebooks/51267","1925","1993","Laumer, Keith","22","February 22, 2016","2","February","2016","8","text/plain,image/jpeg,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","7.2","9.84","6.98","2171","5.2","77.23","6.4","5.5","3.1","0.020578912853125776","0.462629088864414","4.88","11.0","0.09","59894","303","1079","16564.5","12270" +"","en","","Hafiz in London","Text","644","51392","607","https://www.gutenberg.org/ebooks/51392","0","0","Hafiz, 14th cent.","8","March 8, 2016","3","March","2016","6","image/jpeg,text/html,text/plain; charset=utf-8,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","15.2","11.2","7.65","1087","10.3","69.45","12.8","7.0","3.1","0.14300539895710346","0.5480538337924696","4.86","27.0","0.04","31155","73","233","8313.3","6417" +"PS","en","Life on other planets -- Fiction;Science fiction;Dejah Thoris (Fictitious character) -- Fiction;Carter, John (Fictitious character) -- Fiction;Mars (Planet) -- Fiction","The Gods of Mars","Text","643","64","608","https://www.gutenberg.org/ebooks/64","1875","1950","Burroughs, Edgar Rice","17","June 17, 2008","6","June","2008","6","text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","11.1","9.69","6.01","6956","7.9","75.54","10.4","17.5","3.1","0.06361411769567474","0.49531161879412466","4.65","21.0","0.05","384286","1580","3896","110563.2","82689" +"TR","en","Photography -- Early works to 1850","The Pencil of Nature","Text","642","33447","609","https://www.gutenberg.org/ebooks/33447","1800","1877","Talbot, William Henry Fox","16","August 16, 2010","8","August","2010","10","text/plain; charset=utf-8,text/plain; charset=us-ascii,text/html; charset=utf-8,application/x-mobipocket-ebook,application/prs.tei,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/pdf","14.3","12.13","7.5","1604","11.5","55.58","11.600000000000001","3.5","8.8","0.10866254948650897","0.4807727524319195","5.02","24.0","0.04","47597","416","393","14123.7","9478" +"JN","en","Feminists -- Great Britain -- Biography;Suffragists -- Great Britain -- Biography;Women -- Suffrage -- Great Britain;Pankhurst, Emmeline, 1858-1928","My Own Story","Text","642","34856","610","https://www.gutenberg.org/ebooks/34856","1858","1928","Pankhurst, Emmeline","6","January 6, 2011","1","January","2011","9","text/plain; charset=us-ascii,text/plain,application/octet-stream,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","13.2","11.67","6.2","8920","10.7","57.61","10.8","11.5","3.1","0.07857264054517853","0.4639535152460216","4.94","22.0","0.04","472645","3799","4233","139579.2","95774" +"PR","en","Salome (Biblical figure) -- Drama,Tragedies","Salomé: A Tragedy in One Act","Text","641","42704","611","https://www.gutenberg.org/ebooks/42704","1854","1900","Wilde, Oscar","12","May 12, 2013","5","May","2013","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","5.5","8.33","5.8","1433","3.3","87.72","5.6000000000000005","5.0","3.1","0.0300128983615591","0.5077335470878329","4.67","9.0","0.1","61485","208","1338","17100.0","13170" +"","en","","An Advanced English Grammar with Exercises","Text","641","45814","612","https://www.gutenberg.org/ebooks/45814","0","0","Farley, Frank Edgar","29","May 29, 2014","5","May","2014","6","image/jpeg,text/plain; charset=utf-8,text/html; charset=utf-8,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.9","12.98","6.05","12153","5.6","76.22","6.800000000000001","15.0","3.1","0.04173232111524642","0.4122829429431409","5.37","12.0","0.08","567626","4591","8762","148430.7","105795" +"","en","","What is Posat?","Text","637","51336","613","https://www.gutenberg.org/ebooks/51336","0","0","Smith, Phyllis Sterling","1","March 1, 2016","3","March","2016","8","text/plain,image/jpeg,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","9.0","11.13","7.37","1095","7.2","66.74","7.2","5.0","3.1","0.061401926533505506","0.5041403619528625","5.0","13.0","0.07","28009","256","408","8132.4","5601" +"PR","en","Private investigators -- England -- Fiction;Detective and mystery stories;Holmes, Sherlock (Fictitious character) -- Fiction","His Last Bow: An Epilogue of Sherlock Holmes","Text","636","2350","614","https://www.gutenberg.org/ebooks/2350","1859","1930","Doyle, Arthur Conan","1","October, 2000","10","October","2000","7","text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","7.3","9.16","6.76","954","4.8","83.66","7.2","17.5","3.1","0.09156548900628148","0.4692262753119895","4.66","13.0","0.07","28325","146","450","8054.1","6082" +"B","en","Science,Philosophy,Mathematics","Mysticism and Logic and Other Essays","Text","634","25447","615","https://www.gutenberg.org/ebooks/25447","1872","1970","Russell, Bertrand","12","May 12, 2008","5","May","2008","7","text/plain; charset=utf-8,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","16.7","12.54","6.64","7332","13.0","51.52","13.200000000000001","12.5","8.8","0.08186254888529201","0.47670014020059515","5.09","28.0","0.04","365179","4665","2533","109523.7","71757" +"F1201","en","Mexico -- History -- Conquest, 1519-1540","The Memoirs of the Conquistador Bernal Diaz del Castillo, Vol 1 (of 2): Written by Himself Containing a True and Full Account of the Discovery and Conquest of Mexico and New Spain.","Text","632","32474","616","https://www.gutenberg.org/ebooks/32474","1496","1584","Diaz del Castillo, Bernal","21","May 21, 2010","5","May","2010","8","text/plain; charset=us-ascii,text/plain,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","17.3","11.85","6.09","10658","13.0","56.93","14.4","8.0","8.8","0.12669723048188217","0.47061780669334224","4.92","31.0","0.03","905914","6423","5930","265553.1","184178" +"","en","","The Dunwich Horror","Text","632","50133","617","https://www.gutenberg.org/ebooks/50133","1890","1937","Lovecraft, H. P. (Howard Phillips)","4","October 4, 2015","10","October","2015","7","application/x-mobipocket-ebook,image/jpeg,text/html; charset=us-ascii,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","14.1","12.13","7.61","3111","9.9","65.05","11.200000000000001","6.0","3.1","0.02003498786971595","0.48103144569671746","5.02","23.0","0.04","86905","588","726","24795.0","17318" +"DF,PA","en","Classical literature;Iran -- History -- To 640;Greece -- History -- Expedition of Cyrus, 401 B.C.;Cyrus, the Younger, approximately 423 B.C.-401 B.C.","Anabasis","Text","630","1170","618","https://www.gutenberg.org/ebooks/1170","-431","-355","Xenophon","1","January, 1998","1","January","1998","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","14.9","10.45","6.45","8529","11.8","59.98","13.200000000000001","5.5","3.1","0.1156870064318746","0.45968487131481617","4.73","28.0","0.04","448493","2378","3370","129461.4","94860" +"PT","en","Mythology, Norse;Scalds and scaldic poetry","The Younger Edda; Also called Snorre's Edda, or The Prose Edda","Text","629","18947","619","https://www.gutenberg.org/ebooks/18947","0","1241","Snorri Sturluson","31","July 31, 2006","7","July","2006","7","text/plain; charset=utf-8,text/html; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","9.7","10.21","6.19","7244","6.4","79.6","8.8","6.5","3.1","0.14476134475962532","0.5027478056860303","4.79","17.0","0.06","320473","1015","3909","85551.3","66946" +"PZ","en","Tales -- Arab countries,Fairy tales -- Arab countries,Fairy tales,Folklore -- Arab countries,Arabs -- Folklore","The Arabian Nights: Their Best-known Tales","Text","629","20916","620","https://www.gutenberg.org/ebooks/20916","0","0","Unknown","27","March 27, 2007","3","March","2007","7","text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","15.7","10.05","6.25","8176","11.5","66.41","14.0","18.5","3.1","0.15694842414725288","0.4956534940671699","4.61","30.0","0.03","529633","2285","3720","154253.7","114821" +"LB","en","Montessori method of education","Dr. Montessori's Own Handbook","Text","628","29635","621","https://www.gutenberg.org/ebooks/29635","1870","1952","Montessori, Maria","8","August 8, 2009","8","August","2009","8","text/html; charset=utf-8,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","13.6","12.02","6.62","3013","9.5","66.07","10.8","16.0","8.8","0.09415678274840188","0.4569725179365185","5.0","22.0","0.04","125695","1138","1097","36100.8","25130" +"PS","en","Fantasy fiction;American fiction -- 19th century;Horror tales, American;Short stories","The Works of Edgar Allan Poe — Volume 4","Text","626","2150","622","https://www.gutenberg.org/ebooks/2150","1809","1849","Poe, Edgar Allan","19","May 19, 2008","5","May","2008","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","12.2","11.89","6.89","11494","9.5","60.65","9.600000000000001","18.5","8.8","0.10760251290366071","0.5056657163612387","5.03","19.0","0.05","394955","4072","3941","115952.4","78589" +"PR","en","Italy -- Fiction,Orphans -- Fiction,Gothic fiction (Literary genre),Guardian and ward -- Fiction,Inheritance and succession -- Fiction,Castles -- Fiction,Young women -- Fiction,Horror tales","The Mysteries of Udolpho","Text","626","3268","623","https://www.gutenberg.org/ebooks/3268","1764","1823","Radcliffe, Ann Ward","1","June, 2002","6","June","2002","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","16.3","11.9","5.92","16415","11.8","59.98","13.200000000000001","13.0","3.1","0.07573298991857325","0.5039265469876234","4.98","28.0","0.04","1444531","9152","10169","415960.2","290340" +"","en","","In the path of the alphabet: an historical account of the ancient beginnings and; evolution of the modern alphabet","Text","625","51422","624","https://www.gutenberg.org/ebooks/51422","0","0","Jermain, Frances","11","March 11, 2016","3","March","2016","6","image/jpeg,text/plain; charset=utf-8,text/html; charset=utf-8,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","15.7","13.64","6.98","4299","11.5","55.58","11.600000000000001","6.0","8.8","0.14060532481819643","0.42455835869301245","5.28","24.0","0.04","166376","1704","1283","48296.7","31506" +"E201,JK","en","United States. Declaration of Independence;United States -- History -- Revolution, 1775-1783 -- Sources","The Declaration of Independence of the United States of America","Text","624","1","625","https://www.gutenberg.org/ebooks/1","1743","1826","Jefferson, Thomas","4","July 4, 1776","7","July","1776","7","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/prs.tex,application/rdf+xml,application/epub+zip,text/plain","23.8","30.95","10.79","14","4.1","74.86","4.0","2.0","3.1","0.0","0.06666666666666667","9.03","5.0","0.19","289","2","6","48.6","32" +"","en","","A Bad Day for Vermin","Text","623","51258","626","https://www.gutenberg.org/ebooks/51258","1925","1993","Laumer, Keith","21","February 21, 2016","2","February","2016","8","application/x-mobipocket-ebook,image/jpeg,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","8.3","11.12","7.8","467","5.2","77.23","6.4","6.5","3.1","0.03684058254963426","0.4288920485644624","5.1","11.0","0.09","10401","48","179","2817.0","2039" +"PZ","en","Friendship -- Fiction;Country life -- Prince Edward Island -- Fiction;Orphans -- Fiction;Prince Edward Island -- History -- 20th century -- Fiction;Canada -- History -- 1867-1914 -- Fiction;Shirley, Anne (Fictitious character) -- Fiction;Marriage -- Fiction;Young women -- Fiction","Anne's House of Dreams","Text","623","544","627","https://www.gutenberg.org/ebooks/544","1874","1942","Montgomery, L. M. (Lucy Maud)","1","May, 1996","5","May","1996","7","text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","7.7","9.33","5.82","7477","5.2","82.65","7.6000000000000005","26.0","3.1","0.12229225828255613","0.5121736514751702","4.69","14.0","0.07","371897","1370","5645","104102.1","79374" +"DS","en","Madhya Pradesh (India) -- Religion,Ethnology -- India -- Madhya Pradesh,Caste -- India -- Madhya Pradesh,Madhya Pradesh (India) -- Scheduled tribes","The Tribes and Castes of the Central Provinces of India, Volume 1","Text","622","20583","628","https://www.gutenberg.org/ebooks/20583","1873","1915","Russell, R. V. (Robert Vane)","15","February 15, 2007","2","February","2007","8","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","12.3","12.76","6.18","19258","9.1","61.67","9.200000000000001","11.5","3.1","0.066345533551416","0.4158270646668092","5.18","18.0","0.05","952723","8940","9851","274562.1","184101" +"PQ","en","Tristan (Legendary character) -- Romances -- Adaptations,Iseult (Legendary character) -- Romances -- Adaptations,Arthurian romances -- Adaptations","The Romance of Tristan and Iseult","Text","621","14244","629","https://www.gutenberg.org/ebooks/14244","1864","1938","Bedier, Joseph","3","December 3, 2004","12","December","2004","8","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","10.8","8.59","6.05","2157","7.2","82.98","10.8","6.5","3.1","0.10664062100710317","0.5092848319573869","4.41","22.0","0.04","113729","73","1128","30776.4","25783" +"D501","de","Jünger, Ernst, 1895-1998;Soldiers -- Germany -- Diaries;World War, 1914-1918 -- Personal narratives, German","In Stahlgewittern, aus dem Tagebuch eines Stoßtruppführers","Text","621","34099","630","https://www.gutenberg.org/ebooks/34099","1895","1998","Junger, Ernst","19","October 19, 2010","10","October","2010","8","image/jpeg,text/html; charset=iso-8859-1,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","15.6","17.8","7.42","12768","9.5","55.24","8.4","5.0","3.1","0.09121485354010024","0.4993734335839607","6.1","16.0","0.06","411406","3964","4060","107951.4","67468" +"PR","en","Widows -- Fiction,England -- Fiction,Mate selection -- Fiction,Mothers and daughters -- Fiction,Epistolary fiction","Lady Susan","Text","621","946","631","https://www.gutenberg.org/ebooks/946","1775","1817","Austen, Jane","1","June 1997","6","June","1997","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","12.4","10.39","6.68","2773","9.9","65.05","11.200000000000001","11.0","3.1","0.1270798777278705","0.5538823770679968","4.72","23.0","0.04","108750","899","993","32407.2","23047" +"PR","en","People with visual disabilities -- Fiction,Wessex (England) -- Fiction,Love stories,Mothers and sons -- Fiction,Mate selection -- Fiction,Heathlands -- Fiction,Didactic fiction,Adultery -- Fiction","The Return of the Native","Text","620","122","632","https://www.gutenberg.org/ebooks/122","1840","1928","Hardy, Thomas","8","March 8, 2006","3","March","2006","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","9.1","9.86","5.8","12299","6.0","80.62","8.4","26.5","3.1","0.06423281051605217","0.47912682895078174","4.73","16.0","0.06","669540","3120","8575","189631.8","141670" +"PR","en","Arthurian romances -- Adaptations;Arthur, King -- Poetry;Knights and knighthood -- Poetry","Idylls of the King","Text","620","610","633","https://www.gutenberg.org/ebooks/610","1809","1892","Tennyson, Alfred Tennyson, Baron","1","August, 1996","8","August","1996","7","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","16.0","10.11","6.57","7468","10.7","73.85","14.4","27.5","3.1","0.13115644810114874","0.5216061925606139","4.62","31.0","0.03","389314","699","2689","104745.6","84178" +"PR","en","Dragons -- Poetry;Epic poetry, English (Old);Monsters -- Poetry;Scandinavia -- Poetry","Beowulf","Text","619","981","634","https://www.gutenberg.org/ebooks/981","0","0","Unknown","1","July, 1997","7","July","1997","6","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/rdf+xml,application/epub+zip,text/plain","13.0","11.49","6.99","3701","8.3","74.53","10.8","17.0","3.1","0.11284929126096759","0.5571408087920058","4.96","22.0","0.05","128374","279","1166","33317.1","25884" +"BX","en","Edwards, Jonathan, 1703-1758;Sermons, American;Congregational churches -- Sermons","Selected Sermons of Jonathan Edwards","Text","618","34632","635","https://www.gutenberg.org/ebooks/34632","1703","1758","Edwards, Jonathan","12","December 12, 2010","12","December","2010","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","15.5","10.86","6.53","6586","12.2","58.96","13.600000000000001","3.5","8.8","0.1734757480454744","0.5320177287321307","4.75","29.0","0.03","338752","2527","2455","99254.7","71349" +"PQ","en","French drama -- 17th century -- Translations into English,Comedies","Tartuffe; Or, The Hypocrite","Text","617","2027","636","https://www.gutenberg.org/ebooks/2027","1622","1673","Moliere","1","January, 2000","1","January","2000","7","text/html,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.4","10.61","6.44","2365","5.6","81.63","8.0","13.5","3.1","0.12522729668342966","0.5561235630053625","4.91","15.0","0.07","88976","209","1185","24332.4","18138" +"PS","en","Science fiction,Short stories","Beyond Lies the Wub","Text","615","28554","637","https://www.gutenberg.org/ebooks/28554","1928","1982","Dick, Philip K.","11","April 11, 2009","4","April","2009","7","text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","5.4","8.77","6.43","418","2.5","89.75","4.800000000000001","2.5","3.1","0.07161837516488681","0.453901100191798","4.9","7.0","0.13","13202","46","361","3479.4","2694" +"PQ","en","Indexes","English Translations Of Works Of Emile Zola: An Index to the Project Gutenberg Works of Zola in English","Text","615","29004","638","https://www.gutenberg.org/ebooks/29004","1840","1902","Zola, Emile","30","May 30, 2009","5","May","2009","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","14.7","19.53","5.99","120","3.7","86.71","6.0","26.5","3.1","0.08160173160173159","0.415021645021645","6.55","10.0","0.09","6692","24","97","1302.3","1022" +"ND","en","Painting -- History","A Text-Book of the History of Painting","Text","613","18900","639","https://www.gutenberg.org/ebooks/18900","1856","1932","Van Dyke, John Charles","23","July 23, 2006","7","July","2006","7","text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","12.6","14.38","6.59","10228","8.4","63.7","8.4","4.0","3.1","0.15860442457770418","0.44487670373189037","5.51","16.0","0.06","411839","4127","4605","114546.6","74680" +"PS","en","United States -- Social life and customs -- 20th century -- Fiction,Short stories","Tales of the Jazz Age","Text","613","6695","640","https://www.gutenberg.org/ebooks/6695","1896","1940","Fitzgerald, F. Scott (Francis Scott)","1","October, 2004","10","October","2004","8","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","9.3","10.95","6.33","10937","6.4","74.19","7.6000000000000005","8.5","3.1","0.06386596547236507","0.4992602376652076","4.97","14.0","0.07","430623","2466","5942","119863.8","86579" +"PR","en","Married women -- Fiction,Domestic fiction,Deception -- Fiction,England -- Fiction,Psychological fiction,Bigamy -- Fiction","Lady Audley's Secret","Text","613","8954","641","https://www.gutenberg.org/ebooks/8954","1835","1915","Braddon, M. E. (Mary Elizabeth)","1","September, 2005","9","September","2005","8","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","11.2","10.5","5.98","12672","8.7","68.1","10.0","18.0","3.1","0.03132011404025713","0.5131034539598939","4.79","20.0","0.05","708542","3433","7329","201331.8","147984" +"PR","en","Pastoral fiction,Wessex (England) -- Fiction,Women farmers -- Fiction,Triangles (Interpersonal relations) -- Fiction,Farm life -- Fiction,Didactic fiction,Love stories","Far from the Madding Crowd","Text","612","107","642","https://www.gutenberg.org/ebooks/107","1840","1928","Hardy, Thomas","1","February, 1994","2","February","1994","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","10.1","10.67","6.11","14118","7.6","71.14","8.8","2.0","3.1","0.06697728349694965","0.48527250854921744","4.87","17.0","0.06","667326","3885","7969","187362.9","137044" +"BJ","en","Values,Conduct of life,Time management","How to Live on 24 Hours a Day","Text","610","2274","643","https://www.gutenberg.org/ebooks/2274","1867","1931","Bennett, Arnold","1","August, 2000","8","August","2000","7","text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","10.2","10.15","6.97","1986","7.9","70.13","9.200000000000001","13.0","3.1","0.08537673587542939","0.49229716856894534","4.73","18.0","0.05","60716","465","690","18198.0","12842" +"PR","en","Kings and rulers -- Drama;Britons -- Drama;Tragedies;Lear, King (Legendary character) -- Drama;Aging parents -- Drama;Inheritance and succession -- Drama;Fathers and daughters -- Drama","The Tragedy of King Lear","Text","609","1128","644","https://www.gutenberg.org/ebooks/1128","1564","1616","Shakespeare, William","1","January 1, 1608","1","January","1608","7","text/html,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","6.4","8.97","6.09","3334","2.9","94.15","6.4","1.5","3.1","0.11629636696789662","0.5278672920217049","4.73","11.0","0.09","130143","274","2474","34220.7","27527" +"BL","en","Mythology, Assyro-Babylonian;Assyro-Babylonian religion","Myths of Babylonia and Assyria","Text","609","16653","645","https://www.gutenberg.org/ebooks/16653","1873","1936","Mackenzie, Donald A. (Donald Alexander)","5","September 5, 2005","9","September","2005","8","text/plain; charset=utf-8,text/plain; charset=us-ascii,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","13.4","12.82","6.25","15745","9.9","59.64","10.0","3.0","8.8","0.11444980825988385","0.4666327073885945","5.19","20.0","0.05","798355","7775","7383","230048.1","153732" +"PG","en","Satire,Humorous stories,Swindlers and swindling -- Russia -- Fiction,Russia -- Social life and customs -- 1533-1917 -- Fiction","Dead Souls","Text","607","1081","646","https://www.gutenberg.org/ebooks/1081","1809","1852","Gogol, Nikolai Vasilevich","1","October, 1997","10","October","1997","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","12.1","11.14","6.26","14633","8.7","68.1","10.0","6.5","3.1","0.09677723195259377","0.47757291858256146","4.9","20.0","0.05","695178","4748","6764","200611.8","141946" +"PK","en","Epic literature, Sanskrit","The Mahabharata of Krishna-Dwaipayana Vyasa, Volume 1: Books 1, 2 and 3","Text","606","15474","647","https://www.gutenberg.org/ebooks/15474","0","0","Unknown","26","March 26, 2005","3","March","2005","6","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","12.3","11.66","1.75","30318","9.9","59.64","10.0","6.5","3.1","0.2133242454433483","0.5571747724057803","4.99","20.0","0.05","3154531","22524","30974","917923.5","631885" +"PR","en","Country life -- Fiction,Barsetshire (England: Imaginary place) -- Fiction,Great Britain -- History -- 19th century -- Fiction,Physicians -- Fiction,England -- Social life and customs -- 19th century -- Fiction,Nieces -- Fiction,Inheritance and succession -- Fiction,Domestic fiction,Love stories","Doctor Thorne","Text","606","3166","648","https://www.gutenberg.org/ebooks/3166","1815","1882","Trollope, Anthony","1","April, 2002","4","April","2002","8","application/rdf+xml,text/plain; charset=us-ascii,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","9.9","9.63","5.55","13959","6.8","78.59","9.200000000000001","1.5","3.1","0.11419468080105089","0.5200339702323366","4.64","18.0","0.05","1006262","5359","11486","285761.7","216995" +"PN","en","Detective and mystery stories","Library of the World's Best Mystery and Detective Stories","Text","603","12758","649","https://www.gutenberg.org/ebooks/12758","0","0","Unknown","28","June 28, 2004","6","June","2004","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","10.5","10.33","6.34","11298","8.3","69.11","9.600000000000001","10.5","3.1","0.09120756587762754","0.5024267000184115","4.76","19.0","0.05","482758","2649","5326","138854.7","101411" +"T","en","Drawing instruments,Mechanical drawing","Mechanical Drawing Self-Taught: Comprising instructions in the selection and preparation of drawing instruments, elementary instruction in practical mechanical drawing; together with examples in simple geometry and elementary mechanism, including screw threads, gear wheels, mechanical motions, engines and boilers","Text","603","23319","650","https://www.gutenberg.org/ebooks/23319","0","0","Rose, Joshua","4","November 4, 2007","11","November","2007","8","application/rdf+xml,text/plain; charset=us-ascii,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","13.3","11.2","6.08","5722","8.7","73.51","11.200000000000001","6.5","3.1","0.07783054213572561","0.40884621320919823","4.86","23.0","0.04","336206","2578","2915","92318.4","69205" +"PR","en","Private investigators -- England -- Fiction;Detective and mystery stories, English;Holmes, Sherlock (Fictitious character) -- Fiction","The Return of Sherlock Holmes","Text","601","221","651","https://www.gutenberg.org/ebooks/221","1859","1930","Doyle, Arthur Conan","10","July 10, 2008","7","July","2008","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","7.7","8.98","5.66","9463","5.2","82.65","7.6000000000000005","2.0","3.1","0.07326075137650391","0.4909885220517207","4.63","14.0","0.07","520468","2375","7654","149505.3","112404" +"PR","en","Fathers and daughters -- Fiction,Dysfunctional families -- Fiction,Family-owned business enterprises -- Fiction,England -- Fiction,Businesspeople -- Fiction,Domestic fiction","Dombey and Son","Text","601","821","652","https://www.gutenberg.org/ebooks/821","1812","1870","Dickens, Charles","1","February, 1997","2","February","1997","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","11.9","10.68","5.74","23846","7.9","75.54","10.4","4.5","3.1","0.10014688398818115","0.5057105849030434","4.82","21.0","0.05","1708731","9150","16660","478006.2","354829" +"DS","en","Egypt -- History -- To 332 B.C.;History, Ancient","History of Egypt, Chaldea, Syria, Babylonia, and Assyria in the Light of Recent Discovery","Text","600","17321","653","https://www.gutenberg.org/ebooks/17321","1869","1919","King, L. W. (Leonard William)","16","December 16, 2005","12","December","2005","9","image/jpeg,text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","15.9","11.9","6.42","10456","12.6","52.53","12.8","13.0","8.8","0.12390364736794648","0.4374350753783349","4.98","27.0","0.04","568016","5887","4105","168993.0","114152" +"BL","en","Philosophy, Chinese;Taoism -- Sacred books","The Tao Teh King, or the Tao and its Characteristics","Text","600","216","654","https://www.gutenberg.org/ebooks/216","0","0","Laozi","1","February, 1995","2","February","1995","6","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/rdf+xml,application/epub+zip,text/plain","11.1","9.98","6.8","1468","7.6","76.56","10.0","10.5","3.1","0.14888362259903742","0.5337788061009402","4.7","20.0","0.05","50124","290","513","13888.8","10657" +"PR,PZ","de","Fantasy","Alice's Abenteuer im Wunderland","Text","599","19778","655","https://www.gutenberg.org/ebooks/19778","1832","1898","Carroll, Lewis","28","February 28, 2007","2","February","2007","6","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","11.8","13.69","6.68","3718","6.8","73.17","8.0","4.0","3.1","0.4144171463815789","0.5381578947368422","5.39","15.0","0.06","137490","459","1637","34974.9","25515" +"PS","en","Science fiction,War stories,Weapons -- Fiction","The Variable Man","Text","599","32154","656","https://www.gutenberg.org/ebooks/32154","1928","1982","Dick, Philip K.","27","April 27, 2010","4","April","2010","8","image/jpeg,text/html; charset=utf-8,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","6.9","10.47","6.16","3372","4.1","80.28","5.2","4.5","3.1","0.023626818429873093","0.4672580189932055","5.09","8.0","0.11","127398","665","2868","35286.3","25044" +"","en","","Pen Pal","Text","599","51286","657","https://www.gutenberg.org/ebooks/51286","1928","2008","Marlowe, Stephen","23","February 23, 2016","2","February","2016","8","image/jpeg,text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","8.5","10.49","6.89","857","6.0","75.2","7.2","6.5","3.1","0.1018985898516101","0.49457896689440345","4.89","13.0","0.07","25306","138","373","7146.0","5179" +"PS","en","Science fiction;Dejah Thoris (Fictitious character) -- Fiction;Carter, John (Fictitious character) -- Fiction;Mars (Planet) -- Fiction","Warlord of Mars","Text","599","68","658","https://www.gutenberg.org/ebooks/68","1875","1950","Burroughs, Edgar Rice","1","June, 1993","6","June","1993","6","text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","13.9","10.04","6.45","5516","9.9","70.47","12.4","25.5","3.1","0.07571986530213368","0.48139038006130996","4.66","26.0","0.04","266383","1184","2134","76756.5","57129" +"PT","en","Fairy tales -- Germany","Household Stories by the Brothers Grimm","Text","598","19068","659","https://www.gutenberg.org/ebooks/19068","1786","1859","Grimm, Wilhelm","17","August 17, 2006","8","August","2006","8","image/jpeg,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","10.7","8.48","5.54","4585","7.2","82.98","10.8","11.5","3.1","0.10486245786529436","0.47581632831457005","4.39","22.0","0.04","389881","488","3881","106541.1","88728" +"PS","en","Essays,Short stories,Storytelling","How to Tell a Story, and Other Essays","Text","598","3250","660","https://www.gutenberg.org/ebooks/3250","1835","1910","Twain, Mark","20","August 20, 2006","8","August","2006","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","10.5","9.4","7.09","1127","7.6","76.56","10.0","11.0","3.1","0.09535018789352298","0.4626397083818963","4.6","20.0","0.05","33284","195","351","9561.6","7236" +"","en","","My Strange Rescue: and other stories of Sport and Adventure in Canada","Text","598","51308","661","https://www.gutenberg.org/ebooks/51308","1855","1907","Oxley, J. Macdonald (James Macdonald)","26","February 26, 2016","2","February","2016","10","image/jpeg,text/plain; charset=utf-8,text/plain; charset=us-ascii,text/x-rst,text/html; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","13.0","10.86","6.47","9085","9.9","65.05","11.200000000000001","11.0","3.1","0.11537989862298245","0.5046388457688545","4.8","23.0","0.04","406325","1922","3584","114395.4","84589" +"PE","en","English language -- Prepositions,English language -- Synonyms and antonyms","English Synonyms and Antonyms: With Notes on the Correct Use of Prepositions","Text","597","28900","662","https://www.gutenberg.org/ebooks/28900","1838","1918","Fernald, James Champlin","21","May 21, 2009","5","May","2009","8","application/rdf+xml,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/html; charset=iso-8859-1,text/plain","15.7","17.22","6.62","26732","9.9","54.22","8.8","8.5","8.8","0.10051289175173679","0.5217081202639278","6.0","17.0","0.06","1184538","12298","11114","309717.9","197332" +"PS","en","Science fiction,Short stories","The Big Trip Up Yonder","Text","597","30240","663","https://www.gutenberg.org/ebooks/30240","1922","2007","Vonnegut, Kurt","13","October 13, 2009","10","October","2009","7","text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","10.3","12.0","7.43","700","6.8","73.17","8.0","7.0","3.1","0.06021841371011114","0.43226390153511934","5.1","15.0","0.06","18465","128","234","5008.5","3623" +"","en","","The Ways of the Planets","Text","597","51284","664","https://www.gutenberg.org/ebooks/51284","0","0","Martin, Martha Evans","22","February 22, 2016","2","February","2016","7","image/jpeg,text/html; charset=utf-8,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","14.4","10.86","6.06","3928","11.1","62.01","12.4","12.5","3.1","0.13815955295249482","0.4819496654434903","4.8","26.0","0.04","262422","2060","2072","77333.4","54701" +"","en","","Gutenberg, and the Art of Printing","Text","597","51358","665","https://www.gutenberg.org/ebooks/51358","0","0","Pearson, Emily Clemens","5","March 5, 2016","3","March","2016","7","image/jpeg,text/plain; charset=utf-8,text/html; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","11.9","11.84","6.63","7796","8.3","69.11","9.600000000000001","5.5","3.1","0.14488347534131588","0.5042640914856564","5.02","19.0","0.05","300494","2240","3101","85509.9","59891" +"PS","en","Erotic literature, American;Prostitutes -- Fiction","The Life and Amours of the Beautiful, Gay and Dashing Kate Percival: The Belle of the Delaware","Text","596","29827","666","https://www.gutenberg.org/ebooks/29827","0","0","Percival, Kate","28","August 28, 2009","8","August","2009","7","text/html,text/plain; charset=us-ascii,text/plain,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","10.5","10.04","6.03","3611","8.3","69.11","9.600000000000001","10.5","3.1","0.1941779687763146","0.5101280646426058","4.71","19.0","0.05","185242","969","2013","54331.2","39324" +"B,PA","en","Classical literature;Socrates, 470 BC-399 BC;Ethics -- Early works to 1800;Virtue -- Early works to 1800","Meno","Text","594","1643","667","https://www.gutenberg.org/ebooks/1643","-428","-348","Plato","1","February, 1999","2","February","1999","6","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","11.5","10.33","6.4","2414","9.1","67.08","10.4","6.0","3.1","0.15315757743651112","0.5059364288497797","4.76","21.0","0.05","105531","708","1050","31353.3","22177" +"BF","de","Psychoanalysis;Uncanny, The (Psychoanalysis)","Das Unheimliche","Text","594","34222","668","https://www.gutenberg.org/ebooks/34222","1856","1939","Freud, Sigmund","6","November 6, 2010","11","November","2010","8","text/plain; charset=utf-8,text/html; charset=iso-8859-1,application/octet-stream,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","17.2","17.93","8.64","3060","11.1","51.18","10.0","7.5","8.8","-0.027801513671875007","0.5796875000000002","6.07","20.0","0.05","73165","810","597","18873.0","12047" +"PN","en","Public speaking","The Art of Public Speaking","Text","593","16317","669","https://www.gutenberg.org/ebooks/16317","1867","1946","Esenwein, J. Berg (Joseph Berg)","17","July 17, 2005","7","July","2005","7","application/rdf+xml,text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/epub+zip,text/html; charset=iso-8859-1,text/plain","12.1","11.84","6.42","18531","8.3","69.11","9.600000000000001","7.0","3.1","0.13031775122990644","0.4821803578116358","5.02","19.0","0.05","798930","6630","8043","229915.8","159258" +"PN","en","Comedy;Laughter;Philosophy, French","Laughter: An Essay on the Meaning of the Comic","Text","593","4352","670","https://www.gutenberg.org/ebooks/4352","1859","1941","Bergson, Henri","1","August, 2003","8","August","2003","7","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","13.6","11.61","6.85","5217","11.1","56.59","11.200000000000001","13.5","8.8","0.10113776172128619","0.47809368393845897","4.93","23.0","0.04","196153","2070","1677","59532.3","39763" +"DG","en","Rome -- History","The History of Rome, Books 01 to 08","Text","592","19725","671","https://www.gutenberg.org/ebooks/19725","0","0","Livy","6","November 6, 2006","11","November","2006","8","application/rdf+xml,text/plain; charset=utf-8,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","19.3","12.2","6.35","15109","15.4","45.43","15.600000000000001","5.0","8.8","0.11444005487225585","0.4671172649956066","4.98","34.0","0.03","1158371","7835","6747","339075.9","232465" +"PS","en","Two thousand, A.D. -- Fiction;Science fiction;Time travel -- Fiction;Utopian fiction;Social problems -- Fiction;Utopias -- Fiction;Boston (Mass.) -- Fiction","Looking Backward, 2000 to 1887","Text","591","624","672","https://www.gutenberg.org/ebooks/624","1850","1898","Bellamy, Edward","1","August, 1996","8","August","1996","7","text/html; charset=iso-8859-1,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","13.2","11.03","6.46","8301","9.9","65.05","11.200000000000001","28.5","8.8","0.11358256417763253","0.49182237690011105","4.83","23.0","0.04","376018","3338","3276","112193.1","77836" +"PE","en","English language","The Art Of Writing & Speaking The English Language: Word-Study and Composition & Rhetoric","Text","589","19719","673","https://www.gutenberg.org/ebooks/19719","1868","1959","Cody, Sherwin","5","November 5, 2006","11","November","2006","8","text/html,text/plain; charset=utf-8,text/plain; charset=us-ascii,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","12.6","11.55","6.7","7916","9.1","67.08","10.4","8.0","3.1","0.10265602836951652","0.4659516599533861","4.97","21.0","0.05","306618","2148","2903","87502.5","61728" +"PZ","en","Grandfathers -- Fiction,Switzerland -- History -- 19th century -- Fiction,Orphans -- Fiction,Mountain life -- Switzerland -- Fiction","Heidi: (Gift Edition)","Text","589","20781","674","https://www.gutenberg.org/ebooks/20781","1827","1901","Spyri, Johanna","9","March 9, 2007","3","March","2007","9","image/jpeg,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","7.6","9.27","5.49","3934","4.8","83.66","7.2","12.0","3.1","0.12147670519679418","0.500543066680949","4.68","13.0","0.07","241058","654","3684","66429.0","51515" +"HX","en","Utopias -- Early works to 1800","New Atlantis","Text","589","2434","675","https://www.gutenberg.org/ebooks/2434","1561","1626","Bacon, Francis","1","December 2000","12","December","2000","6","text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","17.0","10.28","7.46","2222","13.4","55.92","14.8","9.0","3.1","0.16605096287077162","0.49226849920167365","4.65","32.0","0.03","73067","374","476","21274.2","15700" +"PR","en","Repentance -- Fiction,Women -- England -- Fiction,Criminals -- Fiction,Prostitutes -- Fiction,British -- Virginia -- Fiction,London (England) -- Fiction,Picaresque literature,Virginia -- Fiction,Children of prisoners -- Fiction,Adventure stories","The Fortunes and Misfortunes of the Famous Moll Flanders","Text","589","370","676","https://www.gutenberg.org/ebooks/370","0","1731","Defoe, Daniel","19","March 19, 2008","3","March","2008","7","text/html; charset=iso-8859-1,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","19.8","8.37","2.86","6757","16.1","54.23","18.8","13.0","3.1","0.12418680664071241","0.5115584376699144","4.27","42.0","0.02","589274","2378","3274","174636.0","138014" +"B","en","Socrates, 470 BC-399 BC","Apology, Crito, and Phaedo of Socrates","Text","588","13726","677","https://www.gutenberg.org/ebooks/13726","-428","-348","Plato","12","October 12, 2004","10","October","2004","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","14.5","9.99","6.37","4429","11.8","59.98","13.200000000000001","10.5","3.1","0.1348855360466442","0.5206946977175624","4.65","28.0","0.04","242790","1214","1862","70445.7","52171" +"PR","en","England -- Social life and customs -- 18th century -- Drama,English drama -- 18th century,Nobility -- England -- History -- 18th century -- Drama,Comedies","The School for Scandal","Text","586","1929","678","https://www.gutenberg.org/ebooks/1929","1751","1816","Sheridan, Richard Brinsley","1","October, 1999","10","October","1999","6","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","10.6","12.41","6.84","4493","6.8","73.17","8.0","6.5","3.1","0.13240848895167676","0.5430413453027829","5.17","15.0","0.06","149413","921","1872","41153.4","28881" +"ML","en","Composers -- Austria -- Correspondence;Mozart, Wolfgang Amadeus, 1756-1791 -- Correspondence","The Letters of Wolfgang Amadeus Mozart — Volume 01","Text","586","5307","679","https://www.gutenberg.org/ebooks/5307","1756","1791","Mozart, Wolfgang Amadeus","1","March, 2004","3","March","2004","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","9.8","9.05","6.07","8454","7.2","77.57","9.600000000000001","7.0","3.1","0.16374235602207043","0.5124605521829589","4.54","19.0","0.05","405702","1995","4549","119379.6","89375" +"HF","en","Success,Success in business","The Art of Money Getting; Or, Golden Rules for Making Money","Text","586","8581","680","https://www.gutenberg.org/ebooks/8581","1810","1891","Barnum, P. T. (Phineas Taylor)","1","July, 2005","7","July","2005","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","12.5","10.33","7.19","2076","9.9","65.05","11.200000000000001","11.0","3.1","0.1539122285586383","0.48919650274754123","4.71","23.0","0.04","63935","427","579","18817.2","13569" +"B","en","Knowledge, Theory of -- Early works to 1800","An Essay Concerning Humane Understanding, Volume 1: MDCXC, Based on the 2nd Edition, Books 1 and 2","Text","585","10615","681","https://www.gutenberg.org/ebooks/10615","1632","1704","Locke, John","6","January 6, 2004","1","January","2004","7","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","20.0","10.92","6.46","8867","15.8","49.83","17.2","6.0","8.8","0.10023938650105488","0.45538259702079886","4.76","38.0","0.03","712296","5390","3941","214686.0","149772" +"PQ","en","Arthurian romances;Tales, Medieval;Romances -- Translations into English;Chrétien, de Troyes, active 12th century","Four Arthurian Romances","Text","584","831","682","https://www.gutenberg.org/ebooks/831","0","0","Chretien, de Troyes, active 12th century","1","February, 1997","2","February","1997","6","text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","10.0","8.36","5.59","11040","7.9","75.54","10.4","4.5","3.1","0.1611909569424714","0.5294771504699446","4.42","21.0","0.05","844095","2183","9026","240961.5","191075" +"","en","","The Mentor: The Incas, vol. 6, num. 3, Serial No. 151, March 15, 1918","Text","583","51322","683","https://www.gutenberg.org/ebooks/51322","0","0","Hardy, Osgood","28","February 28, 2016","2","February","2016","6","image/jpeg,text/plain; charset=utf-8,text/html; charset=utf-8,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","15.9","14.45","8.31","2020","12.3","48.13","11.200000000000001","11.0","8.8","0.16924462742071714","0.4964847210010695","5.42","23.0","0.04","48924","593","382","14007.6","9022" +"PS","en","New England -- Social life and customs -- Fiction;Short stories;Historical fiction, American","Twice Told Tales","Text","581","13707","684","https://www.gutenberg.org/ebooks/13707","1804","1864","Hawthorne, Nathaniel","11","October 11, 2004","10","October","2004","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","13.7","11.49","6.44","14939","10.3","64.04","11.600000000000001","13.5","3.1","0.08592146173703967","0.486776317186392","4.91","24.0","0.04","717333","4399","6062","205976.7","146115" +"QH","en","Heredity,Drosophila","Sex-linked Inheritance in Drosophila","Text","579","34368","685","https://www.gutenberg.org/ebooks/34368","1889","1938","Bridges, Calvin B. (Calvin Blackman)","18","November 18, 2010","11","November","2010","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","15.6","18.09","5.69","2600","6.0","80.62","8.4","9.0","3.1","0.0420344327311918","0.33244458182420994","6.15","16.0","0.06","200487","1527","2018","43913.7","32604" +"E300","en","African Americans -- Alabama -- Biography,Slaves -- Alabama -- Social conditions,Slaves -- Alabama -- Biography,Slave narratives -- Alabama,Slavery -- Alabama","Slave Narratives: A Folk History of Slavery in the United States From Interviews with Former Slaves: Volume I, Alabama Narratives","Text","578","36020","686","https://www.gutenberg.org/ebooks/36020","0","0","United States. Work Projects Administration","2","May 02, 2011","5","May","2011","10","text/html; charset=utf-8,text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/plain; charset=utf-8,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/x-rst,application/pdf","7.8","7.89","5.63","9322","5.2","88.06","8.8","60.0","3.1","0.09521500295496836","0.40814285653563775","4.39","17.0","0.06","563155","1568","7483","158991.3","128315" +"BF","en","Thought and thinking,Educational psychology","How We Think","Text","575","37423","687","https://www.gutenberg.org/ebooks/37423","1859","1952","Dewey, John","14","September 14, 2011","9","September","2011","8","application/rdf+xml,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/html; charset=iso-8859-1,text/plain","16.7","14.34","6.9","8326","13.0","46.1","12.0","7.0","8.8","0.0897638970350326","0.4758066007634013","5.4","25.0","0.04","351372","4993","2553","104463.0","65074" +"PZ","en","Fairy tales,Folklore -- Arab countries","The Arabian Nights Entertainments","Text","574","19860","688","https://www.gutenberg.org/ebooks/19860","0","0","Anonymous","18","November 18, 2006","11","November","2006","9","image/jpeg,text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","13.5","10.04","6.14","6938","10.7","63.02","12.0","15.0","3.1","0.15684414817217593","0.4867170628238119","4.66","25.0","0.04","404406","1735","3344","117249.3","86813" +"PR","en","Latin America -- Fiction,Political fiction,Revolutions -- Fiction,Sea stories,Sailors -- Fiction","Nostromo: A Tale of the Seaboard","Text","574","2021","689","https://www.gutenberg.org/ebooks/2021","1857","1924","Conrad, Joseph","9","January 9, 2006","1","January","2006","6","text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","10.5","10.67","6.03","16148","7.9","70.13","9.200000000000001","13.5","3.1","0.05782603514374063","0.4880158283023647","4.87","18.0","0.06","829265","5997","9432","240876.0","170152" +"","en","","The Business, As Usual","Text","574","51435","690","https://www.gutenberg.org/ebooks/51435","1931","1992","Sharkey, Jack","13","March 13, 2016","3","March","2016","7","image/jpeg,text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","8.9","12.28","7.38","535","4.8","78.25","6.0","8.0","3.1","0.04998335824228682","0.45634224902082055","5.3","10.0","0.09","13792","97","244","3695.4","2602" +"PS","en","Avarice -- Fiction,Psychological fiction,Murderers -- Fiction,Dentists -- Fiction,Married people -- Fiction,San Francisco (Calif.) -- Fiction,Didactic fiction","McTeague: A Story of San Francisco","Text","573","165","691","https://www.gutenberg.org/ebooks/165","1870","1902","Norris, Frank","12","March 12, 2006","3","March","2006","7","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","8.5","10.32","5.79","10371","5.2","82.65","7.6000000000000005","13.0","3.1","0.05293472786258164","0.4860400042756359","4.86","14.0","0.07","547084","2306","7981","151504.2","112587" +"PR","en","Man-woman relationships -- Drama,Padua (Italy) -- Drama,Comedies,Sex role -- Drama,Married people -- Drama","The Taming of the Shrew","Text","571","1107","692","https://www.gutenberg.org/ebooks/1107","1564","1616","Shakespeare, William","1","January 1, 1590","1","January","1590","6","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","7.8","9.68","6.05","2491","4.8","83.66","7.2","54.0","3.1","0.2166808902114967","0.5470835341965633","4.75","13.0","0.07","105439","246","1622","28903.5","22176" +"PR","en","Bildungsromans,Autobiographical fiction,England -- Fiction,Working class families -- Fiction,Domestic fiction,Young men -- Fiction","Sons and Lovers","Text","571","217","693","https://www.gutenberg.org/ebooks/217","1885","1930","Lawrence, D. H. (David Herbert)","16","January 16, 2006","1","January","2006","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","6.2","8.97","5.33","12197","3.7","86.71","6.0","2.0","3.1","0.06194239249210219","0.495323638146994","4.73","10.0","0.09","758330","2421","15010","204381.9","160203" +"F1401","en","Spain -- Colonies -- America;Indians, Treatment of -- Latin America","A Brief Account of the Destruction of the Indies: Or, a faithful NARRATIVE OF THE Horrid and Unexampled Massacres, Butcheries, and all manner of Cruelties, that Hell and Malice could invent, committed by the Popish Spanish Party on the inhabitants of West-India, TOGETHER With the Devastations of several Kingdoms in America by Fire and Sword, for the space of Forty and Two Years, from the time of its first Discovery by them.","Text","570","20321","694","https://www.gutenberg.org/ebooks/20321","1484","1566","Casas, Bartolome de las","9","January 9, 2007","1","January","2007","7","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","30.9","13.07","8.8","4697","22.8","31.56","24.400000000000002","29.5","8.8","0.10089875961350879","0.4997352346748044","5.08","56.0","0.02","158018","1080","548","44641.8","31078" +"NA","en","Architecture","The Seven Lamps of Architecture","Text","570","35898","695","https://www.gutenberg.org/ebooks/35898","1819","1900","Ruskin, John","18","April 18, 2011","4","April","2011","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","20.1","11.67","7.15","8805","16.2","43.4","16.400000000000002","4.0","8.8","0.11216471005293716","0.49556396001099584","4.89","36.0","0.03","393546","3786","2181","117949.5","80494" +"PQ","en","Picaresque literature,Spain -- Social life and customs -- 16th century -- Fiction,Knights and knighthood -- Spain -- Fiction,Romances","The History of Don Quixote, Volume 2, Complete","Text","569","5946","696","https://www.gutenberg.org/ebooks/5946","1547","1616","Cervantes Saavedra, Miguel de","26","July 26, 2004","7","July","2004","8","image/jpeg,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","21.8","9.94","6.83","14072","16.5","53.21","19.200000000000003","18.0","3.1","0.14575424074970117","0.5160645436381158","4.54","43.0","0.02","955228","3669","4815","276570.0","210198" +"PQ","fr","Paris (France) -- Fiction,Ex-convicts -- Fiction,Epic literature,Orphans -- Fiction,Historical fiction","Les misérables Tome I: Fantine","Text","568","17489","697","https://www.gutenberg.org/ebooks/17489","1802","1885","Hugo, Victor","10","January 10, 2006","1","January","2006","6","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","10.6","12.29","6.51","14838","6.8","73.17","8.0","51.0","3.1","0.12741778720704441","0.582996750232124","5.2","15.0","0.07","572421","2204","7310","154286.1","110063" +"BX","en","Jesus Christ -- Mormon interpretations,Christian biography -- Palestine,Jesus Christ -- Biography","Jesus the Christ: A Study of the Messiah and His Mission According to Holy; Scriptures Both Ancient and Modern","Text","568","22542","698","https://www.gutenberg.org/ebooks/22542","1862","1933","Talmage, James E. (James Edward)","8","September 8, 2007","9","September","2007","9","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/octet-stream,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","14.0","12.07","5.91","21875","9.9","65.05","11.200000000000001","12.5","3.1","0.09628243378455353","0.48032644648984796","5.01","23.0","0.04","1524757","12621","12828","428678.1","304357" +"JC","en","Representative government and representation","Considerations on Representative Government","Text","568","5669","699","https://www.gutenberg.org/ebooks/5669","1806","1873","Mill, John Stuart","1","May, 2004","5","May","2004","7","application/rdf+xml,text/html; charset=iso-8859-1,text/plain,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","21.6","12.95","6.89","8579","17.7","33.92","16.8","19.5","11.2","0.13192465080589888","0.4738488490854102","5.11","37.0","0.03","486701","6766","2515","150299.1","95204" +"G","en","Equator -- Description and travel;Voyages around the world;Twain, Mark, 1835-1910 -- Travel","Following the Equator: A Journey Around the World","Text","567","2895","700","https://www.gutenberg.org/ebooks/2895","1835","1910","Twain, Mark","18","August 18, 2006","8","August","2006","7","image/jpeg,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","11.7","10.79","6.34","20306","8.7","68.1","10.0","8.5","3.1","0.10251340315282509","0.4716636472582813","4.84","20.0","0.05","908085","6544","9041","261915.3","187603" +"PS","en","Sealers (Persons) -- Fiction,Ship captains -- Fiction,Arctic regions -- Fiction,Sea stories,Sealing ships -- Fiction","The Sea-Wolf","Text","566","1074","701","https://www.gutenberg.org/ebooks/1074","1876","1916","London, Jack","24","December 24, 2010","12","December","2010","7","text/html,text/plain; charset=utf-8,text/plain; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","8.3","9.34","5.9","10136","5.6","81.63","8.0","7.5","3.1","0.050003442776121954","0.5001643497003925","4.64","15.0","0.06","490405","2343","6729","138590.1","105620" +"PS","en","Conformity -- Fiction,Businessmen -- Fiction,Satire,Middle-aged men -- Fiction,Psychological fiction","Babbitt","Text","565","1156","702","https://www.gutenberg.org/ebooks/1156","1885","1951","Lewis, Sinclair","11","February 11, 2006","2","February","2006","6","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","10.1","11.02","6.38","15137","7.2","72.16","8.4","14.0","3.1","0.11763032290291715","0.5127131585167801","4.93","16.0","0.06","603433","4064","7379","168830.1","122453" +"PR","en","Science fiction,Twenty-first century -- Fiction,End of the world -- Fiction,Plague -- Fiction","The Last Man","Text","565","18247","703","https://www.gutenberg.org/ebooks/18247","1797","1851","Shelley, Mary Wollstonecraft","24","April 24, 2006","4","April","2006","7","text/html,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","14.2","11.44","6.43","17122","10.7","63.02","12.0","8.0","3.1","0.07232732021225635","0.5071736095498577","4.9","25.0","0.04","855952","5849","6933","249600.6","174555" +"PR,PZ","en","Country life -- Fiction,Humorous stories,Pastoral fiction,Animals -- Fiction,Fantasy fiction,England -- Fiction,Friendship -- Fiction,River life -- Fiction","The Wind in the Willows","Text","563","27805","704","https://www.gutenberg.org/ebooks/27805","1859","1932","Grahame, Kenneth","14","January 14, 2009","1","January","2009","9","image/jpeg,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","10.7","10.39","6.43","6889","7.2","77.57","9.600000000000001","5.0","3.1","0.08222430162778863","0.49909306518711744","4.77","19.0","0.05","279556","1200","3049","77328.9","58643" +"","en","","The Hand Phrenologically Considered: Being a Glimpse at the Relation of the Mind with the Organisation of the Body","Text","562","51328","705","https://www.gutenberg.org/ebooks/51328","0","0","Anonymous","29","February 29, 2016","2","February","2016","7","text/html,image/jpeg,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","18.2","13.99","8.06","2635","14.6","42.04","13.600000000000001","5.5","11.2","0.11087777962777924","0.4820974454930494","5.29","29.0","0.03","73608","959","473","21840.3","13919" +"B","en","Human beings","Human, All-Too-Human: A Book For Free Spirits; Part II","Text","560","37841","706","https://www.gutenberg.org/ebooks/37841","1844","1900","Nietzsche, Friedrich Wilhelm","24","October 24, 2011","10","October","2011","10","application/prs.tei,text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/plain; charset=utf-8,text/html; charset=utf-8,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/pdf","14.0","12.82","6.87","11649","10.3","58.62","10.4","5.5","8.8","0.12895850572457843","0.5113137710369554","5.19","21.0","0.05","436175","4446","3835","124976.7","83985" +"PR","en","Monsters -- Fiction;Frankenstein's monster (Fictitious character) -- Fiction;Gothic fiction (Literary genre);Science fiction;Frankenstein, Victor (Fictitious character) -- Fiction;Scientists -- Fiction;Horror tales","Frankenstein; Or, The Modern Prometheus","Text","560","41445","707","https://www.gutenberg.org/ebooks/41445","1797","1851","Shelley, Mary Wollstonecraft","10","December 10, 2012","12","December","2012","8","text/plain; charset=utf-8,text/plain; charset=us-ascii,text/html; charset=utf-8,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","12.8","10.86","6.48","7838","9.9","65.05","11.200000000000001","5.0","3.1","0.10080889292576224","0.5391718200100555","4.8","23.0","0.04","348454","2549","3128","103424.4","72609" +"PS","en","American essays","The Oxford Book of American Essays","Text","559","40196","708","https://www.gutenberg.org/ebooks/40196","0","0","Unknown","10","July 10, 2012","7","July","2012","9","image/jpeg,text/html; charset=utf-8,text/plain; charset=us-ascii,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","14.2","11.44","6.74","19210","11.9","54.56","12.0","12.5","8.8","0.13165864052264842","0.48894067719247436","4.9","25.0","0.04","799414","7463","6514","237005.1","163191" +"E456","en","United States. Army -- Biography;United States -- History -- Civil War, 1861-1865 -- Campaigns;Sherman, William T. (William Tecumseh), 1820-1891;United States -- History -- Civil War, 1861-1865 -- Personal narratives;Generals -- United States -- Biography","Memoirs of General William T. Sherman — Complete","Text","559","4361","709","https://www.gutenberg.org/ebooks/4361","1820","1891","Sherman, William T. (William Tecumseh)","16","August 16, 2006","8","August","2006","7","image/jpeg,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","15.1","11.84","5.85","20557","11.1","62.01","12.4","8.0","3.1","0.09564697859309615","0.4447375642410902","4.97","26.0","0.04","1748271","12340","13411","506784.6","351745" +"PR,PZ","en","Robin Hood (Legendary character) -- Legends,Folklore -- England","The Merry Adventures of Robin Hood","Text","558","10148","710","https://www.gutenberg.org/ebooks/10148","1853","1911","Pyle, Howard","20","November 20, 2003","11","November","2003","8","text/plain,image/jpeg,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","11.1","8.88","5.64","6050","7.5","81.97","11.200000000000001","26.5","3.1","0.1610444792287879","0.5066235392592461","4.46","23.0","0.04","496155","335","4816","135100.8","111123" +"","en","","Dr. Elsie Inglis","Text","558","51410","711","https://www.gutenberg.org/ebooks/51410","0","0","Balfour, Lady Frances","9","March 9, 2016","3","March","2016","7","image/jpeg,text/html,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.6","9.8","6.23","6705","7.6","71.14","8.8","4.5","3.1","0.14250263202419794","0.4949651981971189","4.72","17.0","0.06","285837","1731","3429","82069.2","60603" +"PZ,PR,NC","en","Fantasy fiction,Children's stories","The Tenniel Illustrations for Carroll's Alice in Wonderland","StillImage","557","114","712","https://www.gutenberg.org/ebooks/114","1820","1914","Tenniel, John","27","May 27, 2008","5","May","2008","3","text/plain; charset=us-ascii,application/rdf+xml,text/html; charset=iso-8859-1","14.6","17.17","9.06","162","10.3","47.79","8.0","5.5","8.8","0.1218488828244926","0.4039428051623174","5.99","15.0","0.06","3276","46","35","930.6","547" +"HB","en","Economics","Principles Of Political Economy: Abridged with Critical, Bibliographical, and Explanatory Notes, and a Sketch of the History of Political Economy","Text","557","30107","713","https://www.gutenberg.org/ebooks/30107","1806","1873","Mill, John Stuart","27","September 27, 2009","9","September","2009","10","text/html; charset=utf-8,text/plain; charset=us-ascii,application/pdf,text/plain; charset=utf-8,application/prs.tei,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","16.0","12.65","5.95","15472","12.3","53.55","12.4","5.0","8.8","0.1011668725734072","0.4302854553716701","5.11","26.0","0.04","1219880","14156","8937","359276.4","238908" +"","en","","The Mysteries of London, v. 2/4","Text","557","51294","714","https://www.gutenberg.org/ebooks/51294","1814","1879","Reynolds, George W. M. (George William MacArthur)","24","February 24, 2016","2","February","2016","7","image/jpeg,text/html; charset=utf-8,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","12.6","12.13","5.88","32853","9.9","59.64","10.0","2.0","3.1","0.09085858469879354","0.5144812667670124","5.07","20.0","0.05","2106486","16124","20412","603654.3","415590" +"PR","en","English essays","All Things Considered","Text","556","11505","715","https://www.gutenberg.org/ebooks/11505","1874","1936","Chesterton, G. K. (Gilbert Keith)","7","March 7, 2004","3","March","2004","8","text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","11.6","10.33","6.55","7059","9.1","67.08","10.4","20.0","3.1","0.08415981872779983","0.5031775226650531","4.76","21.0","0.05","283614","2566","2818","85736.7","59638" +"","en","","The Iliads of Homer: Translated according to the Greek","Text","556","51355","716","https://www.gutenberg.org/ebooks/51355","-750","-650","Homer","4","March 4, 2016","3","March","2016","5","text/plain; charset=utf-8,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook,text/html","18.0","10.92","6.53","13604","11.4","71.82","15.200000000000001","7.0","3.1","0.15984436139392316","0.5433049834483786","4.76","33.0","0.03","812716","1532","5029","211622.4","170676" +"PQ","fr","Courtly love -- Poetry,Romances","Le roman de la rose - Tome I","Text","555","16816","717","https://www.gutenberg.org/ebooks/16816","0","0","Guillaume, de Lorris, active 1230","8","October 8, 2005","10","October","2005","8","application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/pdf,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","13.5","12.65","7.09","14401","7.9","75.54","10.4","18.5","3.1","0.3168624089039905","0.7222142249757018","5.16","21.0","0.05","487412","1191","4425","127344.6","94433" +"PR","en","Jews -- Italy -- Drama,Moneylenders -- Drama,Venice (Italy) -- Drama,Comedies","The Merchant of Venice","Text","555","2243","718","https://www.gutenberg.org/ebooks/2243","1564","1616","Shakespeare, William","1","January 1, 1623","1","January","1623","6","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","11.5","9.52","6.49","2532","8.3","74.53","10.8","13.5","3.1","0.1278037768921836","0.4941401183377823","4.57","22.0","0.04","103455","138","993","28773.0","22651" +"TX","en","Coffee Industry,Drinking customs,Coffee","All About Coffee","Text","555","28500","719","https://www.gutenberg.org/ebooks/28500","1873","1945","Ukers, William H. (William Harrison)","4","April 4, 2009","4","April","2009","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","13.3","14.27","6.04","40838","7.9","70.13","9.200000000000001","11.0","3.1","0.11706452228042852","0.4220112888680871","5.44","18.0","0.05","2322451","20477","23291","613353.6","426570" +"PQ","en","Erotic stories;France -- History -- 15th century -- Fiction;Rais, Gilles de, 1404-1440 -- Fiction;Satanism -- Fiction;Paranormal fiction","Là-bas","Text","553","14323","720","https://www.gutenberg.org/ebooks/14323","1848","1907","Huysmans, J.-K. (Joris-Karl)","10","December 10, 2004","12","December","2004","7","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","10.6","11.25","6.75","12865","7.6","71.14","8.8","11.0","3.1","0.05832779625906054","0.5150812387972078","4.97","17.0","0.06","445639","3402","5215","128355.3","89623" +"","en","","A Husband for My Wife","Text","553","51460","721","https://www.gutenberg.org/ebooks/51460","0","0","Stuart, William W.","15","March 15, 2016","3","March","2016","8","application/x-mobipocket-ebook,image/jpeg,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","6.0","8.16","6.47","767","4.0","85.69","6.4","3.5","3.1","0.06569741438030033","0.44106367408380853","4.59","11.0","0.09","24327","86","453","6882.3","5296" +"PR","en","English drama (Comedy)","The Way of the World","Text","551","1292","722","https://www.gutenberg.org/ebooks/1292","1670","1729","Congreve, William","25","January 25, 2015","1","January","2015","6","text/html,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","7.7","9.5","6.34","3722","4.8","83.66","7.2","6.5","3.1","0.09237580968918573","0.5332499410419979","4.72","13.0","0.07","134515","608","2056","37433.7","28497" +"","en","","English Coins and Tokens: With A Chapter on Greek and Roman Coins","Text","551","51302","723","https://www.gutenberg.org/ebooks/51302","0","0","Jewitt, Llewellynn Frederick William","26","February 26, 2016","2","February","2016","7","image/jpeg,text/plain; charset=utf-8,text/html; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","12.8","14.67","7.09","5904","8.4","63.7","8.4","6.5","3.1","0.07571568049187988","0.3949089834361292","5.56","16.0","0.06","195317","1652","2191","52396.2","35100" +"PR","en","England -- Social life and customs -- 20th century -- Fiction,Women -- England -- Fiction,Forsyte family (Fictitious characters) -- Fiction,Middle class -- England -- Fiction,Families -- England -- Fiction,England -- Social life and customs -- 19th century -- Fiction,Domestic fiction","The Forsyte Saga - Complete","Text","550","4397","724","https://www.gutenberg.org/ebooks/4397","1867","1933","Galsworthy, John","14","June 14, 2006","6","June","2006","8","text/plain,image/jpeg,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","9.1","10.5","5.65","25469","5.6","81.63","8.0","7.0","3.1","0.07006427327007062","0.4822505066949107","4.84","15.0","0.06","1532361","7105","20380","426178.8","316853" +"","en","","The Sleeping Beauty and other fairy tales","Text","550","51275","725","https://www.gutenberg.org/ebooks/51275","1628","1703","Perrault, Charles","21","February 21, 2016","2","February","2016","8","image/jpeg,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","11.8","10.27","6.79","3600","7.9","75.54","10.4","13.5","3.1","0.14903743215226378","0.5194439695989809","4.75","21.0","0.05","127977","495","1243","35728.2","26932" +"PR","en","Horror tales","The Willows","Text","548","11438","726","https://www.gutenberg.org/ebooks/11438","1869","1951","Blackwood, Algernon","4","March 4, 2004","3","March","2004","6","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","11.5","10.39","6.78","2668","8.7","68.1","10.0","18.0","3.1","0.06093706417307718","0.499641101701123","4.77","20.0","0.05","93215","545","938","27086.4","19559" +"","en","","In Bad Company and other stories","Text","548","51314","727","https://www.gutenberg.org/ebooks/51314","1826","1915","Boldrewood, Rolf","27","February 27, 2016","2","February","2016","7","image/jpeg,text/plain; charset=utf-8,text/html; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","11.7","11.89","6.48","23200","7.9","70.13","9.200000000000001","2.0","3.1","0.09559920035345747","0.47309802161469905","5.03","18.0","0.05","944582","6892","9995","269083.8","187926" +"","en","","The Birth of Tragedy: or Hellenism and Pessimism","Text","547","51356","728","https://www.gutenberg.org/ebooks/51356","1844","1900","Nietzsche, Friedrich Wilhelm","4","March 4, 2016","3","March","2016","7","image/jpeg,text/plain; charset=utf-8,text/html; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","22.3","13.76","7.81","7846","18.1","32.91","17.2","7.0","11.2","0.10877583097249459","0.5305068031979987","5.25","38.0","0.03","283814","3596","1421","84419.1","54029" +"PR","en","Tragedies,Jews -- Malta -- Drama","The Jew of Malta","Text","547","901","729","https://www.gutenberg.org/ebooks/901","1564","1593","Marlowe, Christopher","1","May 1997","5","May","1997","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","9.2","11.42","6.31","3309","4.8","83.66","7.2","4.5","3.1","0.13462881451154268","0.4918552638258147","5.05","13.0","0.07","130346","400","1887","34632.0","25793" +"PR","en","Science fiction","The House on the Borderland","Text","546","10002","730","https://www.gutenberg.org/ebooks/10002","1877","1918","Hodgson, William Hope","10","November 10, 2003","11","November","2003","7","text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","9.3","9.63","6.17","5437","6.4","79.6","8.8","5.5","3.1","0.05147364218466206","0.47223970519847963","4.69","17.0","0.06","238821","1158","2936","68444.1","50912" +"PR","en","Salvation Army -- Drama,Children of the rich -- Drama,Didactic drama,Crime -- Drama,Fathers and daughters -- Drama","Major Barbara","Text","546","3790","731","https://www.gutenberg.org/ebooks/3790","1856","1950","Shaw, Bernard","1","February, 2003","2","February","2003","6","text/html; charset=iso-8859-1,text/plain,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","7.3","9.96","6.13","4031","5.2","77.23","6.4","13.0","3.1","0.08640936786137618","0.5033662974822694","4.85","11.0","0.08","158204","724","2767","44451.0","32605" +"PQ","en","Roland (Legendary character) -- Romances;Epic poetry, French -- Translations into English","The Song of Roland","Text","546","391","732","https://www.gutenberg.org/ebooks/391","0","0","Unknown","1","January, 1996","1","January","1996","6","text/html,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","12.2","10.85","6.25","3227","7.9","75.54","10.4","9.0","3.1","0.15946041676773057","0.5003291824579864","4.85","21.0","0.05","156953","97","1505","40498.2","32369" +"PQ","en","Drama","Life Is a Dream","Text","545","2587","733","https://www.gutenberg.org/ebooks/2587","1600","1681","Calderon de la Barca, Pedro","31","March 31, 2006","3","March","2006","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","13.8","11.96","7.26","2747","8.7","73.51","11.200000000000001","15.0","3.1","0.07960708289938018","0.5213609196425429","4.99","23.0","0.04","86968","338","744","23067.9","17436" +"BC","en","Logic -- Juvenile literature;Logic, Symbolic and mathematical","The Game of Logic","Text","544","4763","734","https://www.gutenberg.org/ebooks/4763","1832","1898","Carroll, Lewis","1","December, 2003","12","December","2003","7","text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","11.0","13.62","6.01","1579","4.8","83.66","7.2","25.5","3.1","0.07281476997906713","0.4949161417981161","5.48","13.0","0.08","78980","430","1088","18483.3","14408" +"PZ","en","Oz (Imaginary place) -- Fiction,Fantasy","The Marvelous Land of Oz","Text","544","54","735","https://www.gutenberg.org/ebooks/54","1856","1919","Baum, L. Frank (Lyman Frank)","1","February, 1993","2","February","1993","7","text/html; charset=iso-8859-1,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","9.9","10.73","6.04","4344","6.0","80.62","8.4","11.0","3.1","0.1438024071038538","0.5337373143595852","4.88","16.0","0.06","207468","787","2545","57116.7","42489" +"PR","en","England -- Fiction;Brown, Father (Fictitious character) -- Fiction;Clergy -- Fiction;Detective and mystery stories, English;Catholics -- Fiction","The Wisdom of Father Brown","Text","543","223","736","https://www.gutenberg.org/ebooks/223","1874","1936","Chesterton, G. K. (Gilbert Keith)","1","February, 1995","2","February","1995","6","text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","10.9","10.39","6.44","8465","8.3","69.11","9.600000000000001","2.5","3.1","0.03873463638187335","0.4711543459261611","4.77","19.0","0.05","341476","1785","3641","97495.2","71640" +"","en","","Cawnpore","Text","543","51383","737","https://www.gutenberg.org/ebooks/51383","1838","1928","Trevelyan, George Otto","6","March 6, 2016","3","March","2016","8","image/jpeg,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","15.8","12.02","7.13","11165","12.6","52.53","12.8","6.0","3.1","0.057073281867798524","0.4554838487951683","5.0","27.0","0.04","409381","2838","3004","119606.4","81913" +"PN","en","Science fiction, American -- Periodicals;Science fiction -- Periodicals","Astounding Stories of Super-Science January 1930","Text","541","41481","738","https://www.gutenberg.org/ebooks/41481","0","0","Unknown","25","November 25, 2012","11","November","2012","8","application/rdf+xml,image/jpeg,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,text/plain","7.9","10.19","6.1","8717","5.6","76.22","6.800000000000001","8.5","3.1","0.037050344707437205","0.46457066325745777","4.89","12.0","0.08","359174","1884","5816","100852.2","73514" +"","en","","Nice Girl With 5 Husbands","Text","541","51101","739","https://www.gutenberg.org/ebooks/51101","1910","1992","Leiber, Fritz","1","February 1, 2016","2","February","2016","8","image/jpeg,text/html; charset=us-ascii,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","8.0","10.77","7.37","884","5.2","77.23","6.4","6.5","3.1","0.055117349379187816","0.49446124596542457","5.04","11.0","0.09","22048","113","386","6072.3","4378" +"PC","en,es","Spanish language -- Textbooks for foreign speakers -- English,Spanish language -- Readers","A First Spanish Reader","Text","539","15353","740","https://www.gutenberg.org/ebooks/15353","1880","0","Roessler, Erwin W. (Erwin William)","13","March 13, 2005","3","March","2005","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","10.5","14.36","8.63","11248","7.2","61.33","6.0","7.0","3.1","0.060725283362845224","0.5386133173880466","5.71","10.0","0.1","225477","2517","3905","63081.9","39506" +"PR","en","Literature -- History and criticism","The Essays of ""George Eliot"": Complete","Text","539","28289","741","https://www.gutenberg.org/ebooks/28289","1819","1880","Eliot, George","9","March 9, 2009","3","March","2009","8","image/jpeg,text/html,text/plain; charset=utf-8,text/plain; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","18.4","12.54","7.36","14152","14.6","47.46","14.8","8.0","8.8","0.11807214781248161","0.4979543826238048","5.04","32.0","0.03","527396","5525","3253","156049.2","104655" +"CS","nl","Names, Personal -- Netherlands;Names, Personal -- Frisian","De Nederlandsche Geslachtsnamen in Oorsprong, Geschiedenis en Beteekenis","Text","539","36077","742","https://www.gutenberg.org/ebooks/36077","1840","1916","Winkler, Johan","10","May 10, 2011","5","May","2011","6","application/x-mobipocket-ebook,text/html; charset=us-ascii,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","15.8","16.19","6.88","26504","9.9","59.64","10.0","7.0","8.8","0.008955585668424885","0.13483622430990871","5.77","20.0","0.05","1074571","10432","9257","286219.8","186286" +"PZ,PS","en","Fairy tales;Short stories;Children's stories, American;Fairy tales -- United States","American Fairy Tales","Text","539","4357","743","https://www.gutenberg.org/ebooks/4357","1856","1919","Baum, L. Frank (Lyman Frank)","1","August, 2003","8","August","2003","7","text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","9.4","9.74","6.19","3454","6.4","79.6","8.8","13.0","3.1","0.1043950004449531","0.5046095979731989","4.71","17.0","0.06","149784","507","1832","41889.6","31809" +"","en","","The Social Contract & Discourses","Text","539","46333","744","https://www.gutenberg.org/ebooks/46333","1712","1778","Rousseau, Jean-Jacques","19","July 19, 2014","7","July","2014","8","text/html,text/plain; charset=utf-8,text/plain; charset=us-ascii,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","18.2","11.91","6.63","10997","14.6","47.46","14.8","8.0","8.8","0.11165279436326019","0.483876584913792","4.93","32.0","0.03","608759","6143","3769","182998.8","123505" +"G","en","Geography -- Outlines, syllabi, etc.","Home Geography for Primary Grades","Text","538","12228","745","https://www.gutenberg.org/ebooks/12228","0","0","Long, C. C.","1","May 1, 2004","5","May","2004","8","text/html,text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","6.3","8.8","5.76","1726","4.0","85.69","6.4","6.0","3.1","0.13030708947617764","0.4967393419024084","4.7","11.0","0.09","81387","242","1539","21984.3","17312" +"PT","de","","Bahnwärter Thiel","Text","537","29376","746","https://www.gutenberg.org/ebooks/29376","1862","1946","Hauptmann, Gerhart","11","July 11, 2009","7","July","2009","7","text/html; charset=iso-8859-1,text/plain,application/octet-stream,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","13.0","15.42","8.17","3878","7.6","65.73","7.6000000000000005","9.0","3.1","0.11598044774865592","0.5758064516129031","5.74","14.0","0.07","91605","560","1084","23600.7","15967" +"B,PA","en","Rhetoric, Ancient;Love -- Early works to 1800;Soul -- Early works to 1800;Classical literature;Rhetoric -- Early works to 1800;Socrates, 470 BC-399 BC;Lysias","Phaedrus","Text","536","1636","747","https://www.gutenberg.org/ebooks/1636","-428","-348","Plato","1","February 1999","2","February","1999","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","15.9","10.8","6.97","4580","12.2","58.96","13.600000000000001","11.5","3.1","0.16507411893437757","0.5194680412927598","4.74","29.0","0.03","180589","1202","1274","53522.1","38132" +"","en","","Ibrahim Pasha: Grand Vizir of Suleiman the Magnificent","Text","535","51299","748","https://www.gutenberg.org/ebooks/51299","1869","1941","Jenkins, Hester Donaldson","25","February 25, 2016","2","February","2016","6","text/html,image/jpeg,text/plain; charset=utf-8,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","13.3","12.88","7.14","5794","9.9","59.64","10.0","10.5","3.1","0.14490163937144712","0.48875186764760625","5.2","20.0","0.05","189567","1605","1777","53784.0","36438" +"PZ,PS","en","Orphans -- Juvenile fiction,Conduct of life -- Juvenile fiction,Cheerfulness -- Juvenile fiction,Aunts -- Juvenile fiction,Interpersonal relations -- Juvenile fiction,Vermont -- History -- 20th century -- Juvenile fiction","Pollyanna","Text","534","1450","749","https://www.gutenberg.org/ebooks/1450","1868","1920","Porter, Eleanor H. (Eleanor Hodgman)","1","September, 1998","9","September","1998","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","7.9","10.08","5.68","5100","4.4","84.68","6.800000000000001","1.5","3.1","0.0981814216796885","0.5301693346020302","4.87","12.0","0.08","271307","873","4357","72739.8","55688" +"PA","en","Cicero, Marcus Tullius -- Correspondence;Statesmen -- Rome -- Correspondence;Authors, Latin -- Correspondence","The Letters of Cicero, Volume 1: The Whole Extant Correspodence in Chronological Order","Text","534","21200","750","https://www.gutenberg.org/ebooks/21200","-106","-43","Cicero, Marcus Tullius","22","April 22, 2007","4","April","2007","7","text/plain; charset=utf-8,text/html; charset=iso-8859-1,text/plain; charset=us-ascii,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","12.2","10.44","6.04","14156","9.5","66.07","10.8","8.5","3.1","0.13591709617689035","0.5091248676091383","4.78","22.0","0.05","812337","5618","7675","237222.0","169933" +"PR","en","Friendship -- Fiction;Hessen (Hesse, Germany : Province) -- Fiction;Middle class -- Fiction;Bad Nauheim (Germany) -- Fiction;British -- Germany -- Fiction;Married people -- Fiction;Domestic fiction;Adultery -- Fiction","The Good Soldier","Text","534","2775","751","https://www.gutenberg.org/ebooks/2775","1873","1939","Ford, Ford Madox","1","August, 2001","8","August","2001","9","text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/octet-stream,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","9.7","9.63","6.05","7250","7.9","70.13","9.200000000000001","13.5","3.1","0.07379491831732046","0.5037568063139329","4.64","18.0","0.05","348578","1973","4064","101672.1","75182" +"BX","en","Christian life -- Catholic authors,Spiritual life -- Catholic Church","The Practice of the Presence of God","Text","534","5657","752","https://www.gutenberg.org/ebooks/5657","1611","1691","Lawrence, of the Resurrection, Brother","1","May, 2004","5","May","2004","7","text/html,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","8.6","8.76","6.35","1304","7.6","71.14","8.8","8.0","3.1","0.17328897003113025","0.5209387786042834","4.54","17.0","0.06","49984","308","638","14902.2","11018" +"PR","en","Grandfathers -- Fiction,Antique dealers -- Fiction,Didactic fiction,England -- Fiction,Grandparent and child -- Fiction,Gamblers -- Fiction,Domestic fiction,Girls -- Fiction","The Old Curiosity Shop","Text","534","700","753","https://www.gutenberg.org/ebooks/700","1812","1870","Dickens, Charles","7","March 7, 2008","3","March","2008","7","text/html; charset=iso-8859-1,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","12.5","10.86","5.94","16588","8.3","74.53","10.8","19.0","3.1","0.0906479831321859","0.498803003441187","4.8","22.0","0.04","1037397","4966","9534","288724.5","215977" +"PR","en","English drama,Man-woman relationships -- Drama","Man and Superman: A Comedy and a Philosophy","Text","533","3328","754","https://www.gutenberg.org/ebooks/3328","1856","1950","Shaw, Bernard","21","March 21, 2006","3","March","2006","6","text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","8.8","9.91","6.33","8489","6.8","73.17","8.0","13.5","3.1","0.09198820667211678","0.5217183472024728","4.79","15.0","0.07","329624","2300","4496","95438.7","68761" +"","en","","Moral Equivalent","Text","533","51449","755","https://www.gutenberg.org/ebooks/51449","1925","1980","Neville, Kris","14","March 14, 2016","3","March","2016","8","text/plain,image/jpeg,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","7.9","11.28","7.11","1468","4.4","79.26","5.6000000000000005","5.5","3.1","0.0732406302444508","0.5090977565624896","5.18","9.0","0.1","39615","230","777","10759.5","7645" +"GR","tl","Folklore -- Philippines","Ibong Adarna: Corrido at Buhay na Pinagdaanan nang tatlong Principeng Magcacapatid na Anac nang Haring Fernando at nang Reina Valeriana sa Cahariang Berbania","Text","532","16157","756","https://www.gutenberg.org/ebooks/16157","0","0","Anonymous","1","July 1, 2005","7","July","2005","5","application/rdf+xml,text/html; charset=iso-8859-1,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","14.2","16.64","7.54","3200","9.1","56.25","8.0","9.0","8.8","0.2486111111111112","0.37222222222222207","5.95","15.0","0.07","95076","1243","1049","26331.3","15989" +"PQ","fr","French literature","Madame Bovary","Text","531","14155","757","https://www.gutenberg.org/ebooks/14155","1821","1880","Flaubert, Gustave","26","November 26, 2004","11","November","2004","8","text/html,text/rtf,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","12.9","13.69","6.86","16783","7.6","71.14","8.8","28.0","3.1","0.1858018738749709","0.5520667504538458","5.39","17.0","0.06","599538","2686","6208","160988.4","111313" +"","en","","The Anabasis of Alexander: or, The History of the Wars and Conquests of Alexander the Great","Text","531","46976","758","https://www.gutenberg.org/ebooks/46976","0","0","Nicomedia, Arrian of","27","September 27, 2014","9","September","2014","6","image/jpeg,text/html; charset=utf-8,text/plain; charset=utf-8,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","12.9","12.07","5.99","12837","8.7","68.1","10.0","8.0","3.1","0.11561349851461428","0.4507230257136369","5.06","20.0","0.05","751421","6316","7107","206685.0","148516" +"PZ","en","Fantasy,Goblins -- Juvenile fiction,Fairy tales,Children's stories,Princesses -- Juvenile fiction","The Princess and the Goblin","Text","531","708","759","https://www.gutenberg.org/ebooks/708","1824","1905","MacDonald, George","1","November, 1996","11","November","1996","7","text/html; charset=iso-8859-1,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","8.5","8.93","5.64","3901","6.0","80.62","8.4","1.5","3.1","0.09893567367046213","0.5039647325463663","4.57","16.0","0.06","233013","604","3017","64576.8","50951" +"PA","en","Epic poetry, Greek -- Translations into English;Odysseus (Greek mythology) -- Poetry;Homer -- Translations into English","The Odyssey","Text","529","3160","760","https://www.gutenberg.org/ebooks/3160","-750","-650","Homer","1","April, 2002","4","April","2002","7","text/html,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","14.6","12.13","6.36","11740","9.1","72.5","11.600000000000001","14.0","3.1","0.12720465681670373","0.532590641354689","5.02","24.0","0.04","608935","1528","4912","161866.8","121231" +"","en","","That Which Hath Wings","Text","529","51428","761","https://www.gutenberg.org/ebooks/51428","1863","1932","Dehan, Richard","12","March 12, 2016","3","March","2016","10","application/rdf+xml,image/jpeg,text/plain; charset=utf-8,text/plain; charset=us-ascii,text/html; charset=utf-8,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/x-rst,application/x-mobipocket-ebook","10.7","12.12","6.51","24095","7.2","72.16","8.4","6.0","3.1","0.06698440917462299","0.46388303047369417","5.12","16.0","0.06","936877","5772","11419","259076.7","183089" +"PS","en","American poetry","Spoon River Anthology","Text","528","1280","762","https://www.gutenberg.org/ebooks/1280","1868","1950","Masters, Edgar Lee","1","April, 1998","4","April","1998","7","text/html,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","12.3","10.51","7.08","4635","8.3","74.53","10.8","5.5","3.1","0.07594229649625198","0.4733555945778791","4.74","22.0","0.04","147836","358","1364","40511.7","31172" +"PK","en","India -- Social life and customs -- Fiction;English language -- Textbooks for foreign speakers -- Indic;Tagore, Rabindranath, 1861-1941 -- Translations into English;Short stories, Bengali -- Translations into English","Stories from Tagore","Text","528","33525","763","https://www.gutenberg.org/ebooks/33525","1861","1941","Tagore, Rabindranath","24","August 24, 2010","8","August","2010","8","image/jpeg,text/plain; charset=utf-8,text/plain; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","9.3","10.61","6.38","6008","6.8","73.17","8.0","3.5","3.1","0.09375660116024671","0.49749088569922084","4.86","15.0","0.06","230715","1225","3038","65824.2","47491" +"PQ","en","Epic poetry, Italian -- Translations into English;Italian poetry -- To 1400 -- Translations into English","The Divine Comedy by Dante, Illustrated, Purgatory, Complete","Text","528","8795","764","https://www.gutenberg.org/ebooks/8795","1265","1321","Dante Alighieri","5","August 5, 2004","8","August","2004","6","text/html; charset=iso-8859-1,text/plain,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","13.3","10.97","7.0","5030","9.1","72.5","11.600000000000001","13.5","3.1","0.11386061975448257","0.487794717507692","4.82","24.0","0.04","176375","260","1517","46422.0","36584" +"","en","","Cicero: Letters to Atticus, Volume III (of 3)","Text","527","51403","765","https://www.gutenberg.org/ebooks/51403","-106","-43","Cicero, Marcus Tullius","8","March 8, 2016","3","March","2016","6","image/jpeg,text/plain; charset=utf-8,text/html; charset=utf-8,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.2","11.48","6.58","16813","7.2","66.74","7.2","7.5","3.1","0.14268579388919697","0.5052127835441389","5.06","13.0","0.07","584777","4582","8551","169297.2","115638" +"PE","en","Readers","McGuffey's First Eclectic Reader, Revised Edition","Text","525","14640","766","https://www.gutenberg.org/ebooks/14640","1800","1873","McGuffey, William Holmes","29","June 29, 2005","6","June","2005","10","text/plain,text/html,text/plain; charset=us-ascii,application/pdf,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook,application/msword","5.6","7.69","5.32","546","1.7","102.61","6.4","5.0","3.1","0.12735286325419187","0.4672983585548125","4.51","11.0","0.09","34174","118","653","8627.4","7573" +"GR","en","Tales -- Hawaii,Legends -- Hawaii","Hawaiian Folk Tales: A Collection of Native Legends","Text","525","18450","767","https://www.gutenberg.org/ebooks/18450","0","0","Unknown","25","May 25, 2006","5","May","2006","8","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","12.3","10.39","6.51","7815","9.9","65.05","11.200000000000001","8.0","3.1","0.10333415461328078","0.4686163690474591","4.72","23.0","0.04","336875","2078","3095","96653.7","71358" +"PR","en","Mowgli (Fictitious character) -- Fiction,India -- Fiction,Jungle animals -- Fiction","The Second Jungle Book","Text","525","1937","768","https://www.gutenberg.org/ebooks/1937","1865","1936","Kipling, Rudyard","1","October, 1999","10","October","1999","6","text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","9.5","9.4","6.02","6012","6.8","78.59","9.200000000000001","53.0","3.1","0.04883327316258828","0.44836859459889966","4.6","18.0","0.05","293271","644","3446","80476.2","63730" +"PR","en","Detective and mystery stories;Holmes, Sherlock (Fictitious character) -- Fiction;Private investigators -- England -- Fiction;Blessing and cursing -- Fiction;Dogs -- Fiction;Dartmoor (England) -- Fiction","The Hound of the Baskervilles","Text","524","3070","769","https://www.gutenberg.org/ebooks/3070","1859","1930","Doyle, Arthur Conan","1","February, 2002","2","February","2002","8","application/rdf+xml,text/html; charset=iso-8859-1,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","8.1","9.1","5.85","5502","5.6","81.63","8.0","8.5","3.1","0.0670261522512151","0.49565361727072155","4.6","15.0","0.06","272373","1307","3769","78099.3","59192" +"DE","en","Greece -- Biography -- Early works to 1800,Rome -- Biography -- Early works to 1800","Plutarch: Lives of the noble Grecians and Romans","Text","524","674","770","https://www.gutenberg.org/ebooks/674","46","119","Plutarch","1","January 1, 1517","1","January","1517","6","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","23.4","11.97","2.8","31379","17.7","44.75","19.200000000000003","18.5","8.8","0.14230231450941924","0.49803435919770667","4.89","43.0","0.02","3616766","24502","16998","1059746.4","740378" +"PZ","en","Fairy tales","The Story of the Three Little Pigs","Text","523","18155","771","https://www.gutenberg.org/ebooks/18155","1862","1940","Brooke, L. Leslie (Leonard Leslie)","11","April 11, 2006","4","April","2006","7","image/jpeg,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","9.9","10.1","5.64","73","5.6","87.05","9.200000000000001","6.0","3.1","-0.013368794326241103","0.4726684397163121","4.72","18.0","0.05","4907","30","57","1258.2","1039" +"HM","en","Crowds","The Crowd: A Study of the Popular Mind","Text","522","445","772","https://www.gutenberg.org/ebooks/445","1841","1931","Le Bon, Gustave","1","January 1, 1895","1","January","1895","6","text/html,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","16.2","13.47","6.87","6930","13.0","46.1","12.0","4.5","8.8","0.09898743254048696","0.48773040467754697","5.25","25.0","0.04","288178","3936","2124","86414.4","54919" +"","en","","The Cool War","Text","522","51256","773","https://www.gutenberg.org/ebooks/51256","0","0","Fetler, Andrew","21","February 21, 2016","2","February","2016","8","image/jpeg,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","8.2","11.86","7.28","1053","4.4","79.26","5.6000000000000005","5.5","3.1","0.07762007075557498","0.42921459492888037","5.33","9.0","0.11","27708","144","570","7484.4","5201" +"PA","en","Epic poetry, Greek -- Translations into English;Achilles (Mythological character) -- Poetry;Trojan War -- Poetry","The Iliad of Homer: Translated into English Blank Verse by William Cowper","Text","521","16452","774","https://www.gutenberg.org/ebooks/16452","-750","-650","Homer","5","August 5, 2005","8","August","2005","8","image/jpeg,text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","13.7","12.07","6.28","16551","8.7","73.51","11.200000000000001","11.0","3.1","0.13454782419134345","0.5301961470271083","5.01","23.0","0.04","872233","3525","7542","231075.0","174002" +"BV","en","Meditations","The Imitation of Christ","Text","520","1653","775","https://www.gutenberg.org/ebooks/1653","1380","1471","Thomas, a Kempis","1","January 1, 1422","1","January","1422","7","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","12.4","10.16","6.02","4892","8.7","73.51","11.200000000000001","7.0","3.1","0.21862230313048123","0.5629650248761386","4.68","23.0","0.04","290060","1352","2632","82431.9","62007" +"PZ","en","Readers,Folklore,History","Fifty Famous Stories Retold","Text","519","18442","776","https://www.gutenberg.org/ebooks/18442","1841","1925","Baldwin, James","23","May 23, 2006","5","May","2006","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","6.4","7.71","5.49","2377","4.0","91.11","7.6000000000000005","19.0","3.1","0.16143717472002866","0.5367264059398374","4.41","14.0","0.07","142498","219","2272","39082.5","32289" +"PR","en","Mysteries and miracle-plays, English;Moralities, English;English drama -- To 1500;Bible plays, English","""Everyman,"" with other interludes, including eight miracle plays","Text","519","19481","777","https://www.gutenberg.org/ebooks/19481","0","0","Unknown","6","October 6, 2006","10","October","2006","9","image/jpeg,text/html; charset=utf-8,text/plain; charset=us-ascii,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","10.1","10.55","6.28","6451","6.4","79.6","8.8","14.5","3.1","0.15251314359664556","0.5025945438355118","4.85","17.0","0.06","275211","841","3281","71472.6","56715" +"","en","","The Fight Against Lynching: Anti-Lynching Work of the National Association for the Advancement of Colored People for the Year Nineteen Eighteen","Text","519","51317","778","https://www.gutenberg.org/ebooks/51317","0","0","Anonymous","28","February 28, 2016","2","February","2016","9","image/jpeg,text/html,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","14.3","14.97","8.03","1235","9.1","61.67","9.200000000000001","8.5","8.8","0.02511001082251085","0.311151858558108","5.56","18.0","0.05","30965","351","293","8486.1","5565" +"TT","en","Handicraft for boys","The Boy Mechanic: Volume 1: 700 Things for Boys to Do","Text","518","12655","779","https://www.gutenberg.org/ebooks/12655","0","0","Popular Mechanics Company","18","June 18, 2004","6","June","2004","10","text/html,text/plain; charset=us-ascii,text/rtf,application/pdf,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","9.0","9.1","1.62","11853","6.4","79.6","8.8","9.0","3.1","0.05190455560025698","0.43751110075402544","4.6","17.0","0.06","1112426","6045","13859","314069.4","242015" +"PR","en","Detective and mystery stories, English;Short stories;Fiction","The Lock and Key Library: Classic Mystery and Detective Stories: Modern English","Text","518","2038","780","https://www.gutenberg.org/ebooks/2038","0","0","Unknown","4","June 4, 2005","6","June","2005","9","image/jpeg,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","8.3","9.34","5.95","12427","5.6","81.63","8.0","6.0","3.1","0.0748020447725204","0.4856628497912022","4.64","15.0","0.06","580220","2812","7923","166939.2","125114" +"","en","","Motor Matt's Reverse: or, Caught in a Losing Cause","Text","518","51343","781","https://www.gutenberg.org/ebooks/51343","0","0","Matthews, Stanley R.","2","March 2, 2016","3","March","2016","8","image/jpeg,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","8.8","10.37","6.18","3800","5.2","82.65","7.6000000000000005","4.0","3.1","0.08149703414241341","0.46280786817101777","4.87","14.0","0.07","157763","533","2216","43237.8","32368" +"PG","en","Russian fiction -- Translations into English;Dostoyevsky, Fyodor, 1821-1881 -- Translations into English","White Nights and Other Stories: The Novels of Fyodor Dostoevsky, Volume X","Text","517","36034","782","https://www.gutenberg.org/ebooks/36034","1821","1881","Dostoyevsky, Fyodor","5","May 5, 2011","5","May","2011","8","text/html; charset=iso-8859-1,text/plain,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","9.2","9.51","5.88","10485","7.6","71.14","8.8","8.0","3.1","0.08991930319120311","0.5228010014502227","4.67","17.0","0.06","552879","3243","6828","160288.2","118405" +"PA","en","Rome -- Fiction;Satire, Latin -- Translations into English","The Satyricon — Volume 02: Dinner of Trimalchio","Text","517","5219","783","https://www.gutenberg.org/ebooks/5219","20","66","Petronius Arbiter","22","May 22, 2004","5","May","2004","7","text/html; charset=iso-8859-1,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","11.8","9.87","6.92","2669","8.3","74.53","10.8","8.0","3.1","0.10181995578452943","0.4932589862774186","4.63","22.0","0.04","89032","362","843","25479.9","19213" +"","en","","Hunt the Hunter","Text","515","51433","784","https://www.gutenberg.org/ebooks/51433","1925","1980","Neville, Kris","13","March 13, 2016","3","March","2016","8","image/jpeg,text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","6.8","10.35","6.41","832","2.9","88.74","5.2","5.0","3.1","0.040068695843018504","0.49734987986835283","5.07","8.0","0.11","28031","103","633","7305.3","5524" +"PR","en","England -- Social life and customs -- Fiction;Love stories, English","The Complete Project Gutenberg Works of Jane Austen: A Linked Index of all PG Editions of Jane Austen","Text","514","31100","785","https://www.gutenberg.org/ebooks/31100","1775","1817","Austen, Jane","25","January 25, 2010","1","January","2010","6","text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","11.3","10.5","1.66","33092","8.7","68.1","10.0","29.0","3.1","0.1422975167076866","0.5317648296850239","4.79","20.0","0.05","3720159","25224","38194","1079247.6","777121" +"PT","en","Poetry","Poems","Text","513","38594","786","https://www.gutenberg.org/ebooks/38594","1875","1926","Rilke, Rainer Maria","17","January 17, 2012","1","January","2012","8","text/html; charset=utf-8,text/plain; charset=us-ascii,text/plain; charset=utf-8,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","16.3","12.07","7.66","1709","11.8","59.98","13.200000000000001","20.0","3.1","0.1268570039042375","0.49956476109137765","5.01","28.0","0.04","51223","285","362","14119.2","10230" +"","en","","Advance Agent","Text","513","51273","787","https://www.gutenberg.org/ebooks/51273","0","0","Anvil, Christopher","21","February 21, 2016","2","February","2016","8","application/x-mobipocket-ebook,image/jpeg,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","8.0","10.31","6.55","1630","4.4","84.68","6.800000000000001","6.5","3.1","0.019978024563016592","0.46156338206497466","4.91","12.0","0.08","54431","257","879","14952.6","11079" +"B","en","Philosophy","The Life of Reason: The Phases of Human Progress","Text","512","15000","788","https://www.gutenberg.org/ebooks/15000","1863","1952","Santayana, George","14","February 14, 2005","2","February","2005","9","text/html,text/html; charset=iso-8859-1,text/plain; charset=us-ascii,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","16.2","13.81","6.06","23866","13.0","46.1","12.0","6.5","8.8","0.13461651034901076","0.5098036613943464","5.31","25.0","0.04","1686496","23009","12555","513038.7","317450" +"PQ","en","Submarines (Ships) -- Fiction,Science fiction,Sea stories,Underwater exploration -- Fiction","Twenty Thousand Leagues Under the Seas: An Underwater Tour of the World","Text","511","2488","789","https://www.gutenberg.org/ebooks/2488","1828","1905","Verne, Jules","1","January 1, 1870","1","January","1870","6","text/html; charset=utf-8,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","10.7","12.06","6.04","14773","7.2","72.16","8.4","6.0","3.1","0.08302148404156265","0.4781636148509944","5.11","16.0","0.06","738533","4730","8940","208071.0","144604" +"PR","en","English drama;Historical drama;Timur, 1336-1405 -- Drama;Tragedies","Tamburlaine the Great — Part 1","Text","510","1094","790","https://www.gutenberg.org/ebooks/1094","1564","1593","Marlowe, Christopher","1","November, 1997","11","November","1997","7","application/rdf+xml,text/plain; charset=us-ascii,text/plain,text/plain; charset=iso-8859-1,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","11.2","12.58","6.64","3466","6.0","80.62","8.4","5.0","3.1","0.1583532907991535","0.5455780288177369","5.2","16.0","0.06","128897","402","1526","33333.3","24765" +"BC","en","Logic, Symbolic and mathematical","Symbolic Logic","Text","510","28696","791","https://www.gutenberg.org/ebooks/28696","1832","1898","Carroll, Lewis","5","May 5, 2009","5","May","2009","8","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","11.8","14.55","5.53","4455","3.6","92.12","7.2","13.0","3.1","0.07666183182052325","0.46631190835325986","5.59","13.0","0.07","313684","2063","4045","69408.0","56160" +"PT","en","Norwegian drama -- Translations into English,Architects -- Drama","The Master Builder","Text","510","4070","792","https://www.gutenberg.org/ebooks/4070","1828","1906","Ibsen, Henrik","1","May, 2003","5","May","2003","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","8.0","11.46","5.8","3121","3.3","87.72","5.6000000000000005","11.0","3.1","0.07363803377080269","0.5092071055972305","5.21","9.0","0.1","149464","524","2920","37348.2","28713" +"","en","","Poem Outlines","Text","509","51346","793","https://www.gutenberg.org/ebooks/51346","1842","1881","Lanier, Sidney","3","March 3, 2016","3","March","2016","7","image/jpeg,text/html,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","12.3","10.79","7.34","1389","7.9","75.54","10.4","4.5","3.1","0.13936223989254276","0.5041435832218659","4.84","21.0","0.05","39817","172","378","10667.7","8232" +"QH","en","Instinct;Expression;Psychology, Comparative;Emotions","The Expression of the Emotions in Man and Animals","Text","508","1227","794","https://www.gutenberg.org/ebooks/1227","1809","1882","Darwin, Charles","1","March, 1998","3","March","1998","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","15.0","12.65","6.19","9381","11.5","55.58","11.600000000000001","8.5","8.8","0.06499134286152958","0.4664115628097054","5.11","24.0","0.04","557040","4990","4420","160755.3","108949" +"PT","en","Wives -- Drama,Man-woman relationships -- Drama,Marriage -- Drama,Norwegian drama -- Translations into English","A Doll's House","Text","508","15492","795","https://www.gutenberg.org/ebooks/15492","1828","1906","Ibsen, Henrik","29","March 29, 2005","3","March","2005","7","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","6.0","8.79","5.56","2390","3.7","86.71","6.0","3.5","3.1","0.02778539327600929","0.5796285515855477","4.75","10.0","0.1","125711","377","2627","33739.2","26487" +"PR","en","Conduct of life -- Fiction,Humorous stories,Germany -- Fiction,Satire,Clothing and dress -- Fiction,Philosophers -- Fiction,Didactic fiction","Sartor Resartus: The Life and Opinions of Herr Teufelsdröckh","Text","507","1051","796","https://www.gutenberg.org/ebooks/1051","1795","1881","Carlyle, Thomas","1","September, 1997","9","September","1997","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","18.8","13.7","7.96","14156","14.2","48.47","14.4","19.0","8.8","0.09288454489808681","0.48799389152656836","5.24","31.0","0.03","419819","4111","2582","120520.8","80184" +"PJ","en","Epic poetry, Assyro-Babylonian","An Old Babylonian Version of the Gilgamesh Epic","Text","506","11000","797","https://www.gutenberg.org/ebooks/11000","1866","1925","Clay, Albert Tobias","4","July 4, 2006","7","July","2006","6","text/html,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","13.4","13.69","6.75","5088","8.3","69.11","9.600000000000001","9.0","3.1","0.06174681603589338","0.42854842149029204","5.34","19.0","0.05","197157","1657","1912","53425.8","36952" +"CT","en","Philanthropists -- United States -- Biography;Carnegie, Andrew, 1835-1919;Industrialists -- United States -- Biography","Autobiography of Andrew Carnegie","Text","505","17976","798","https://www.gutenberg.org/ebooks/17976","1835","1919","Carnegie, Andrew","13","March 13, 2006","3","March","2006","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","10.3","10.79","6.01","11297","7.6","71.14","8.8","14.0","3.1","0.16792223990467164","0.4858677640257155","4.89","17.0","0.06","571703","4130","6692","164034.9","116938" +"ML","en","Ballad operas -- Librettos","The Beggar's Opera; to Which is Prefixed the Musick to Each Song","Text","503","25063","799","https://www.gutenberg.org/ebooks/25063","1685","1732","Gay, John","13","April 13, 2008","4","April","2008","12","application/x-mobipocket-ebook,image/jpeg,audio/midi,text/html; charset=utf-8,text/plain; charset=us-ascii,text/plain,application/octet-stream,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/pdf","8.5","10.14","6.55","2879","5.2","82.65","7.6000000000000005","4.5","3.1","0.18180384782813888","0.5646924413166461","4.83","14.0","0.07","99115","331","1431","26753.4","20514" +"NC","en","Drawing","The Elements of Drawing, in Three Letters to Beginners","Text","503","30325","800","https://www.gutenberg.org/ebooks/30325","1819","1900","Ruskin, John","24","October 24, 2009","10","October","2009","7","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","18.8","10.57","6.81","6475","15.0","51.86","16.400000000000002","8.5","8.8","0.12127883544444025","0.49537386738179534","4.7","36.0","0.03","346156","2272","2042","101190.6","73717" +"PS","en","Cowboys -- Fiction,Wyoming -- Fiction,Western stories,Vigilantes -- Fiction,Cattle stealing -- Fiction","The Virginian: A Horseman of the Plains","Text","502","1298","801","https://www.gutenberg.org/ebooks/1298","1860","1938","Wister, Owen","1","May, 1998","5","May","1998","6","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","7.4","9.45","5.68","11472","4.8","83.66","7.2","13.5","3.1","0.09713736958517312","0.47803747211148445","4.71","13.0","0.07","608632","2116","9653","169119.9","129298" +"PA","en","Agricola, Gnaeus Julius, 40-93;Germanic peoples -- Early works to 1800;Statesmen -- Rome -- Biography -- Early works to 1800","The Germany and the Agricola of Tacitus","Text","502","7524","802","https://www.gutenberg.org/ebooks/7524","56","117","Tacitus, Cornelius","1","February, 2005","2","February","2005","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","14.9","12.65","7.3","7654","11.5","55.58","11.600000000000001","7.0","8.8","0.10412632269731245","0.4594809276293613","5.11","24.0","0.04","249362","2099","1990","71808.3","48789" +"E201","en","Monarchy,United States -- Politics and government -- 1775-1783,Political science","Common Sense","Text","501","3755","803","https://www.gutenberg.org/ebooks/3755","1737","1809","Paine, Thomas","1","February, 2003","2","February","2003","7","text/html; charset=iso-8859-1,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","16.9","11.73","7.65","3123","13.8","49.49","14.0","5.5","8.8","0.0854058966046603","0.4497163136509274","4.9","30.0","0.03","95718","800","641","28330.2","19521" +"BJ","en","Conduct of life","Letters to His Son, Complete: On the Fine Art of Becoming a Man of the World and a Gentleman","Text","500","3361","804","https://www.gutenberg.org/ebooks/3361","1694","1773","Chesterfield, Philip Dormer Stanhope, Earl of","12","October 12, 2004","10","October","2004","6","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","15.3","10.86","6.09","19660","11.8","59.98","13.200000000000001","10.5","3.1","0.1531343137768362","0.5085491005285964","4.75","28.0","0.03","1382425","10005","10107","407355.3","291127" +"","en","","Chain Reaction","Text","500","51255","805","https://www.gutenberg.org/ebooks/51255","0","0","Ellanby, Boyd","20","February 20, 2016","2","February","2016","8","text/plain,image/jpeg,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","7.2","10.13","6.52","712","3.7","86.71","6.0","5.5","3.1","0.015901539838940937","0.5052707454289733","4.93","10.0","0.09","23251","93","440","6337.8","4718" +"","en","","The Border and the Buffalo: An Untold Story of the Southwest Plains","Text","499","51448","806","https://www.gutenberg.org/ebooks/51448","0","0","Cook, John R.","14","March 14, 2016","3","March","2016","7","image/jpeg,text/html,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.7","9.17","5.84","8485","7.2","77.57","9.600000000000001","4.0","3.1","0.06753961771625394","0.3900972661048646","4.56","19.0","0.05","483715","1761","5480","137519.1","106053" +"PS","en","Psychological fiction,Alcoholics -- Fiction,Married people -- Fiction,New York (N.Y.) -- Fiction,Inheritance and succession -- Fiction,Domestic fiction,Socialites -- Fiction,Young men -- Fiction","The Beautiful and Damned","Text","499","9830","807","https://www.gutenberg.org/ebooks/9830","1896","1940","Fitzgerald, F. Scott (Francis Scott)","1","February, 2006","2","February","2006","9","application/rdf+xml,image/jpeg,text/html; charset=iso-8859-1,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","10.3","11.77","6.28","14901","6.8","73.17","8.0","19.0","3.1","0.061224919865318805","0.5061916891059333","5.06","15.0","0.06","625494","4728","7777","177029.1","123560" +"PR","en","London (England) -- History -- 1800-1950 -- Fiction;Conduct of life -- Fiction;Paranormal fiction;Portraits -- Fiction;Appearance (Philosophy) -- Fiction;Supernatural -- Fiction;Great Britain -- History -- Victoria, 1837-1901 -- Fiction;Didactic fiction","The Picture of Dorian Gray","Text","497","4078","808","https://www.gutenberg.org/ebooks/4078","1854","1900","Wilde, Oscar","1","May, 2003","5","May","2003","8","application/rdf+xml,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/html; charset=iso-8859-1,text/plain","6.9","8.57","5.89","5558","4.8","83.66","7.2","52.0","3.1","0.06408950066457991","0.5523969925916752","4.61","13.0","0.08","252052","1185","4115","72519.3","54616" +"","en","","Franklin's Way to Wealth: or, 'Poor Richard Improved'","Text","497","43855","809","https://www.gutenberg.org/ebooks/43855","1706","1790","Franklin, Benjamin","1","October 1, 2013","10","October","2013","8","text/plain,image/jpeg,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","13.8","11.03","7.66","646","9.1","72.5","11.600000000000001","5.0","3.1","0.10713288279119008","0.5135136632785536","4.83","24.0","0.04","17389","89","144","4815.0","3597" +"PS","en","Gifts -- Fiction,Short stories,Christmas stories","The Gift of the Magi","Text","497","7256","810","https://www.gutenberg.org/ebooks/7256","1862","1910","Henry, O.","1","January, 2005","1","January","2005","7","text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","6.8","8.69","6.82","338","4.4","84.68","6.800000000000001","4.0","3.1","0.141650867733457","0.5055745808424384","4.63","12.0","0.08","9560","40","161","2690.1","2063" +"QA","ru","Word problems (Mathematics);Mathematics -- Problems, exercises, etc.","1001 zadacha dlia umstvennogo scheta","Text","496","16527","811","https://www.gutenberg.org/ebooks/16527","1836","1902","Rachinskii, Sergei Aleksandrovich","14","August 14, 2005","8","August","2005","7","text/html; charset=windows-1251,text/plain; charset=windows-1251,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","4.9","7.91","0.4","0","-12.5","198.72","5.2","3.5","3.1","0.25","1.0","4.7","8.0","0.12","126930","0","3209","0.9","27030" +"","en","","The Golden Gems of Life: Gathered Jewels for the Home Circle","Text","493","51374","812","https://www.gutenberg.org/ebooks/51374","0","0","Ferguson, S. C.","6","March 6, 2016","3","March","2016","7","image/jpeg,text/plain; charset=utf-8,text/html; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","13.0","11.38","6.17","14446","9.5","66.07","10.8","5.0","3.1","0.17697757970999542","0.5282491963901849","4.89","22.0","0.04","775097","6448","6961","229402.8","158526" +"","en","","Sordman the Protector","Text","491","51445","813","https://www.gutenberg.org/ebooks/51445","1936","0","Purdom, Tom","14","March 14, 2016","3","March","2016","8","image/jpeg,text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","5.8","8.84","6.3","1149","2.9","88.74","5.2","6.0","3.1","0.07900105155230819","0.4731788469222326","4.86","8.0","0.12","38809","133","923","10403.1","7989" +"PR","en","People with disabilities -- Fiction,Artists -- Fiction,Orphans -- Fiction,Bildungsromans,Physicians -- Fiction","Of Human Bondage","Text","490","351","814","https://www.gutenberg.org/ebooks/351","1874","1965","Maugham, W. Somerset (William Somerset)","6","May 6, 2008","5","May","2008","6","text/html,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","8.3","9.28","5.38","16344","5.6","81.63","8.0","4.0","3.1","0.07034892536625358","0.5107271252332691","4.63","15.0","0.06","1201159","5672","16316","341277.3","259443" +"PQ","en","Lays -- Translations into English;Romances -- Translations into English;Marie, de France, active 12th century -- Translations into English","French Mediaeval Romances from the Lays of Marie de France","Text","489","11417","815","https://www.gutenberg.org/ebooks/11417","0","0","Marie, Queen of Rumania","3","March 3, 2004","3","March","2004","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","9.3","8.65","5.59","4736","7.2","77.57","9.600000000000001","7.5","3.1","0.2107104691606505","0.5746695154300446","4.47","19.0","0.05","329626","537","3825","92768.4","73791" +"PQ","en","French fiction -- Translations into English","Against the Grain","Text","489","12341","816","https://www.gutenberg.org/ebooks/12341","1848","1907","Huysmans, J.-K. (Joris-Karl)","14","May 14, 2004","5","May","2004","7","text/html; charset=iso-8859-1,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","17.4","13.47","7.86","10684","13.0","51.52","13.200000000000001","26.0","8.8","0.057992504982762164","0.5193248874219464","5.25","28.0","0.04","312655","3058","2106","91548.0","59501" +"PR","en","English poetry","Browning's Shorter Poems","Text","489","16376","817","https://www.gutenberg.org/ebooks/16376","1812","1889","Browning, Robert","28","July 28, 2005","7","July","2005","8","text/html,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","10.0","10.67","6.87","7591","6.0","80.62","8.4","5.5","3.1","0.1285389954610535","0.4722392079223402","4.87","16.0","0.06","239594","898","2906","63913.5","49170" +"PS","en","Science fiction,War stories,Space ships -- Fiction","Mr. Spaceship","Text","489","32522","818","https://www.gutenberg.org/ebooks/32522","1928","1982","Dick, Philip K.","25","May 25, 2010","5","May","2010","8","image/jpeg,text/html; charset=utf-8,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","6.3","9.54","6.31","1520","2.9","88.74","5.2","3.5","3.1","0.04973266596754502","0.41743694337696313","4.93","8.0","0.11","52070","219","1177","14153.4","10562" +"","en","","Ambition","Text","488","51274","819","https://www.gutenberg.org/ebooks/51274","0","0","Bade, William L.","21","February 21, 2016","2","February","2016","8","text/plain,image/jpeg,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","7.9","10.66","6.84","1300","5.2","77.23","6.4","4.5","3.1","0.07569219316514489","0.43404886196903003","4.97","11.0","0.08","38365","248","649","10570.5","7720" +"PR","en","Historical fiction,Caribbean Area -- Fiction,Pirates -- Fiction,Physicians -- Fiction,Sea stories,Adventure stories,British -- Caribbean Area -- Fiction","Captain Blood","Text","487","1965","820","https://www.gutenberg.org/ebooks/1965","1875","1950","Sabatini, Rafael","1","November, 1999","11","November","1999","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.3","10.73","5.98","11441","6.8","73.17","8.0","1.5","3.1","0.058282885171534723","0.4910771779799587","4.88","15.0","0.06","552249","3255","7345","156525.3","113152" +"TL","en","Aeronautics -- Periodicals,Airships -- Periodicals","Jane's All the World's Aircraft. 1913","Text","487","34815","821","https://www.gutenberg.org/ebooks/34815","0","0","Unknown","2","January 2, 2011","1","January","2011","8","text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","14.5","19.8","6.93","13451","2.9","88.74","5.2","6.0","3.1","0.08034192596692613","0.33511286295069975","6.75","8.0","0.12","495674","4172","8846","95225.4","73423" +"","en","","""1812"" Napoleon I in Russia","Text","487","51418","822","https://www.gutenberg.org/ebooks/51418","1842","1904","Vereshchagin, Vasilii Vasilevich","12","March 12, 2016","3","March","2016","7","image/jpeg,text/html,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","13.4","12.19","6.69","9678","10.7","57.61","10.8","3.5","3.1","0.06800440554784958","0.4640113191434833","5.03","22.0","0.04","391785","2869","3480","113021.1","77864" +"QH","en","Natural history,Voyages around the world -- History -- 19th century,Beagle Expedition (1831-1836),South America -- Discovery and exploration,Geology","The Voyage of the Beagle","Text","487","944","823","https://www.gutenberg.org/ebooks/944","1809","1882","Darwin, Charles","1","June, 1997","6","June","1997","7","text/html,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","14.6","11.61","6.14","16512","10.7","63.02","12.0","11.0","3.1","0.09148821504963213","0.46567583983367417","4.93","25.0","0.04","1013480","7968","7998","297199.8","205655" +"PR","en","Country homes -- Fiction,Sisters -- Fiction,Social classes -- Fiction,Illegitimate children -- Fiction,England -- Fiction,Remarried people -- Fiction,Inheritance and succession -- Fiction,Domestic fiction","Howards End","Text","486","2891","824","https://www.gutenberg.org/ebooks/2891","1879","1970","Forster, E. M. (Edward Morgan)","1","November, 2001","11","November","2001","7","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","7.7","10.19","5.93","11698","5.6","76.22","6.800000000000001","5.0","3.1","0.07356223902588506","0.5070000840149904","4.89","12.0","0.08","531013","2485","8872","146719.8","108676" +"PR,PS","en","American essays,English essays","Modern Essays","Text","486","38280","825","https://www.gutenberg.org/ebooks/38280","0","0","Unknown","11","December 11, 2011","12","December","2011","9","image/jpeg,text/plain; charset=utf-8,text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","12.0","11.08","7.01","12817","8.7","68.1","10.0","6.0","3.1","0.12332106363457924","0.48810731519440814","4.89","20.0","0.05","414673","3314","4063","120670.2","84843" +"PR","en","English essays -- Early modern, 1500-1700","The Essays or Counsels, Civil and Moral","Text","486","575","826","https://www.gutenberg.org/ebooks/575","1561","1626","Bacon, Francis","1","June, 1996","6","June","1996","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","15.7","11.21","7.24","7449","11.8","59.98","13.200000000000001","19.0","3.1","0.18285578106272385","0.523910305370067","4.81","28.0","0.03","254896","1608","1832","74285.1","53007" +"PS","en","Hudson River Valley (N.Y. and N.J.) -- Fiction;Americans -- England -- History -- 19th century;Fantasy fiction, American;Catskill Mountains Region (N.Y.) -- Fiction;Irving, Washington, 1783-1859 -- Travel -- England;England -- Social life and customs -- 19th century","The Sketch-Book of Geoffrey Crayon","Text","485","2048","827","https://www.gutenberg.org/ebooks/2048","1783","1859","Irving, Washington","1","August, 2000","8","August","2000","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","16.9","11.96","6.98","15117","12.6","57.95","14.0","28.0","8.8","0.12081327056114714","0.48880341519998","4.94","30.0","0.03","634742","4933","4253","185427.9","128395" +"HN","en","Social problems","What's Wrong with the World","Text","484","1717","828","https://www.gutenberg.org/ebooks/1717","1874","1936","Chesterton, G. K. (Gilbert Keith)","1","April, 1999","4","April","1999","6","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/rdf+xml,application/epub+zip,text/plain","12.5","10.74","6.75","7710","9.5","66.07","10.8","29.0","8.8","0.07178302884992178","0.4863486550279686","4.78","22.0","0.04","287275","2644","2640","86892.3","60066" +"BR","en","Persecution,Martyrs,Church history","Fox's Book of Martyrs: Or A History of the Lives, Sufferings, and Triumphant; Deaths of the Primitive Protestant Martyrs","Text","484","22400","829","https://www.gutenberg.org/ebooks/22400","1516","1587","Foxe, John","25","August 25, 2007","8","August","2007","8","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","15.4","11.9","6.19","21045","11.1","62.01","12.4","30.0","8.8","0.08334225729256706","0.46701749254107433","4.98","26.0","0.04","1313898","9945","9837","380135.7","263862" +"PR","en","Hamlet (Legendary character) -- Drama,Tragedies,Murder victims' families -- Drama,Princes -- Drama,Denmark -- Drama,Fathers -- Death -- Drama,Revenge -- Drama,Kings and rulers -- Succession -- Drama","Hamlet, Prince of Denmark","Text","484","27761","830","https://www.gutenberg.org/ebooks/27761","1564","1616","Shakespeare, William","10","January 10, 2009","1","January","2009","8","text/html; charset=utf-8,text/plain; charset=us-ascii,text/plain; charset=utf-8,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","10.0","12.58","6.65","4772","4.8","83.66","7.2","5.5","3.1","0.1413975814238429","0.5334191918099934","5.25","13.0","0.07","167162","570","2386","41687.1","31823" +"PR","en","Science fiction","The Night Land","Text","483","10662","831","https://www.gutenberg.org/ebooks/10662","1877","1918","Hodgson, William Hope","9","January 9, 2004","1","January","2004","6","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","18.3","7.79","2.54","6981","14.2","64.72","18.0","26.0","3.1","0.14868612577409168","0.5432977426414309","4.17","40.0","0.02","821706","1458","4901","239606.1","197075" +"PR","en","Ghost stories,English fiction","Three Ghost Stories","Text","483","1289","832","https://www.gutenberg.org/ebooks/1289","1812","1870","Dickens, Charles","9","March 9, 2013","3","March","2013","6","text/html,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","11.6","9.98","7.1","3227","9.1","67.08","10.4","6.5","3.1","0.07190042841092642","0.4723569235823697","4.7","21.0","0.05","99041","657","970","28866.6","21066" +"PS","en","Science fiction,Short stories,Time travel -- Fiction","The Skull","Text","483","30255","833","https://www.gutenberg.org/ebooks/30255","1928","1982","Dick, Philip K.","14","October 14, 2009","10","October","2009","6","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","5.7","8.89","6.26","1102","2.9","88.74","5.2","5.0","3.1","0.06457596013807312","0.45014969550573203","4.87","8.0","0.12","38008","131","922","10189.8","7812" +"","en","","The Story of Elizabeth Canning Considered","Text","483","51334","834","https://www.gutenberg.org/ebooks/51334","1858","1916","Hill, John A. (John Alexander)","29","February 29, 2016","2","February","2016","7","image/jpeg,text/html,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","16.1","10.51","7.46","1534","12.6","57.95","14.0","5.5","8.8","0.10141019099684441","0.5336613180238673","4.69","30.0","0.03","48751","337","336","14367.6","10390" +"PR","en","Ocean travel -- Fiction,Women travelers -- Fiction,Bildungsromans,Love stories,Young women -- Fiction,British -- South America -- Fiction","The Voyage Out","Text","482","144","835","https://www.gutenberg.org/ebooks/144","1882","1941","Woolf, Virginia","12","January 12, 2006","1","January","2006","7","text/plain; charset=utf-8,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","9.6","10.38","5.8","11835","7.2","72.16","8.4","13.0","3.1","0.08292245803351996","0.49767984688045314","4.82","16.0","0.06","655337","3208","8150","183927.6","136016" +"PA","en","Classical literature,Metamorphosis -- Fiction","The Golden Asse","Text","482","1666","836","https://www.gutenberg.org/ebooks/1666","0","0","Apuleius","21","February 21, 2006","2","February","2006","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","26.1","10.35","7.47","6644","20.8","36.63","22.400000000000002","14.0","3.1","0.16956594114985257","0.5349162318413028","4.61","51.0","0.02","371394","1281","1559","109950.3","80581" +"PA","en","Abelard, Peter, 1079-1142 -- Correspondence;Love-letters;Authors, Latin (Medieval and modern) -- France -- Correspondence;Héloïse, approximately 1095-1163 or 1164 -- Correspondence","Letters of Abelard and Heloise: To which is prefix'd a particular account of their lives, amours, and misfortunes","Text","482","35977","837","https://www.gutenberg.org/ebooks/35977","0","1163","Heloise","27","April 27, 2011","4","April","2011","7","text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","12.5","10.62","6.57","5565","9.5","66.07","10.8","3.5","3.1","0.1260984354024401","0.5583840755560185","4.76","22.0","0.04","227069","1413","2079","66871.8","47674" +"LB","en","Montessori method of education","The Montessori Method: Scientific Pedagogy as Applied to Child Education in 'The Children's Houses' with Additions and Revisions by the Author","Text","482","39863","838","https://www.gutenberg.org/ebooks/39863","1870","1952","Montessori, Maria","31","May 31, 2012","5","May","2012","7","application/rdf+xml,text/html; charset=iso-8859-1,text/plain,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","15.4","12.48","6.28","10516","11.9","54.56","12.0","12.0","8.8","0.12238194753972871","0.48735885015369124","5.08","25.0","0.04","600723","6521","4570","175430.7","118351" +"","de","","The German Classics from the Fourth to the Nineteenth Century, Vol. 1 (of 2)","Text","482","51389","839","https://www.gutenberg.org/ebooks/51389","1823","1900","Muller, F. Max (Friedrich Max)","7","March 7, 2016","3","March","2016","6","image/jpeg,text/plain; charset=utf-8,text/html; charset=utf-8,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","12.2","12.82","6.92","30157","5.6","87.05","9.200000000000001","6.0","3.1","0.05266262012845208","0.4034631806309031","5.19","18.0","0.05","1034461","3039","10914","245326.5","199486" +"PR","en","Biographers -- Fiction,Triangles (Interpersonal relations) -- Fiction,Poets -- Family relationships -- Fiction,London (England) -- Fiction,Mothers and daughters -- Fiction,Domestic fiction,Young women -- Fiction,Love stories","Night and Day","Text","481","1245","840","https://www.gutenberg.org/ebooks/1245","1882","1941","Woolf, Virginia","1","March, 1998","3","March","1998","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","10.8","11.08","5.83","13662","7.9","70.13","9.200000000000001","17.5","3.1","0.09658642284740927","0.5055298212462686","4.89","18.0","0.05","812422","5127","9032","232335.9","166200" +"PS","en","Boston (Mass.) -- History -- Colonial period, ca. 1600-1775 -- Fiction;Revenge -- Fiction;Psychological fiction;Triangles (Interpersonal relations) -- Fiction;Women immigrants -- Fiction;Illegitimate children -- Fiction;Historical fiction;Married women -- Fiction;Clergy -- Fiction;Puritans -- Fiction;Adultery -- Fiction","The Scarlet Letter","Text","481","25344","841","https://www.gutenberg.org/ebooks/25344","1804","1864","Hawthorne, Nathaniel","5","May 5, 2008","5","May","2008","8","text/plain; charset=utf-8,text/plain; charset=us-ascii,text/html; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","13.7","12.13","6.72","10324","9.9","65.05","11.200000000000001","4.5","3.1","0.08795711497479257","0.49797372095211556","5.02","23.0","0.04","421010","3315","3644","120875.4","83817" +"PQ","en","Detective and mystery stories;Rouletabille, Joseph (Fictitious character) -- Fiction;Reporters and reporting -- Fiction","The Mystery of the Yellow Room","Text","480","1685","842","https://www.gutenberg.org/ebooks/1685","1868","1927","Leroux, Gaston","1","March, 1999","3","March","1999","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","9.9","10.67","5.83","6481","7.2","72.16","8.4","13.5","3.1","0.07345189135831416","0.47604070314064406","4.87","16.0","0.06","356919","2647","4362","102702.6","73251" +"PA","en","Rome -- History -- Civil War, 49-48 B.C.;Gaul -- History -- Gallic Wars, 58-51 B.C.","""De Bello Gallico"" and Other Commentaries","Text","478","10657","843","https://www.gutenberg.org/ebooks/10657","-100","-44","Caesar, Julius","9","January 9, 2004","1","January","2004","7","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","20.9","12.25","6.7","12447","15.4","50.84","16.8","13.5","8.8","0.12410392918942957","0.454345734069688","4.99","37.0","0.03","798061","5173","4240","229664.7","159795" +"BL,PB","en","Mythology, Celtic;Celts -- Religion","Myths & Legends of the Celtic Race","Text","478","34081","844","https://www.gutenberg.org/ebooks/34081","1857","1920","Rolleston, T. W. (Thomas William)","16","October 16, 2010","10","October","2010","11","application/prs.tei,text/plain; charset=us-ascii,text/html; charset=utf-8,application/pdf,text/plain; charset=utf-8,application/octet-stream,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","13.7","11.09","6.45","14495","10.3","64.04","11.600000000000001","10.5","3.1","0.12830201517402923","0.46384385373554865","4.84","24.0","0.04","683116","3762","5736","190580.4","141007" +"G","en","Political science -- Handbooks, manuals, etc.;World politics -- Handbooks, manuals, etc.;Political statistics -- Handbooks, manuals, etc.;Geography -- Handbooks, manuals, etc.","The 2010 CIA World Factbook","Text","478","35830","845","https://www.gutenberg.org/ebooks/35830","0","0","United States. Central Intelligence Agency","11","April 11, 2011","4","April","2011","11","text/html,image/jpeg,text/plain; charset=utf-8,text/plain; charset=us-ascii,image/gif,text/plain,application/octet-stream,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","15.2","18.49","1.1","42141","7.6","65.73","7.6000000000000005","7.5","8.8","0.03009633929176575","0.32788085324238225","6.27","14.0","0.07","10286089","131707","115413","2396909.7","1640506" +"PG","en","Russia -- Social life and customs -- Drama,Russian drama -- Translations into English,Comedies","The Inspector-General","Text","478","3735","846","https://www.gutenberg.org/ebooks/3735","1809","1852","Gogol, Nikolai Vasilevich","1","February, 2003","2","February","2003","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","6.6","9.83","5.98","3523","4.4","79.26","5.6000000000000005","15.5","3.1","0.11002336165492482","0.501097532007289","4.93","9.0","0.1","144918","863","3055","40373.1","29373" +"","en","","Toadstools, mushrooms, fungi, edible and poisonous; one thousand American fungi","Text","478","51393","847","https://www.gutenberg.org/ebooks/51393","0","0","Macadam, Robert K.","8","March 8, 2016","3","March","2016","6","image/jpeg,text/html; charset=utf-8,text/plain; charset=utf-8,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","11.9","15.76","5.69","22048","7.6","60.31","6.4","7.0","3.1","0.038408118660845474","0.43208731182618487","5.9","11.0","0.09","1363230","15152","20954","362191.5","231146" +"PR","en","Short stories, New Zealand;New Zealand -- Social life and customs -- Fiction","The Garden Party, and Other Stories","Text","477","1429","848","https://www.gutenberg.org/ebooks/1429","1888","1923","Mansfield, Katherine","1","1998","1","January","1998","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","6.9","9.38","5.85","6029","4.0","85.69","6.4","1.5","3.1","0.04379000729409234","0.4923300367723425","4.8","11.0","0.09","274198","693","5007","74325.6","57173" +"PQ","en","Life on other planets -- Fiction;Voyages, Imaginary -- Fiction;Interplanetary voyages -- Fiction;Short stories;Science fiction","Micromegas","Text","477","30123","849","https://www.gutenberg.org/ebooks/30123","1694","1778","Voltaire","28","September 28, 2009","9","September","2009","7","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","11.3","11.14","7.22","1286","8.3","69.11","9.600000000000001","4.5","3.1","0.07680243704031862","0.5312174843907336","4.9","19.0","0.05","37744","330","400","10782.0","7702" +"PQ","es","Authors -- Fiction,Andalusia (Spain) -- Social life and customs -- Fiction,Donkeys -- Fiction","Platero y yo","Text","476","9980","850","https://www.gutenberg.org/ebooks/9980","1881","1958","Jimenez, Juan Ramon","1","February, 2006","2","February","2006","7","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","12.9","14.9","8.43","7942","9.1","56.25","8.0","31.0","3.1","0.06647432940696632","0.48699439522529864","5.6","15.0","0.06","173502","1726","1938","48623.4","30987" +"PL","en","Ethics -- China;Philosophy, Chinese","The Analects of Confucius (from the Chinese Classics)","Text","475","3330","851","https://www.gutenberg.org/ebooks/3330","-551","-479","Confucius","1","July, 2002","7","July","2002","6","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","9.3","9.8","6.07","2961","6.4","79.6","8.8","11.5","3.1","0.13473181478419755","0.5483378387165824","4.72","17.0","0.06","138419","624","1722","37985.4","29311" +"PN,GR","en","Folklore -- England,Fairy tales -- England","English Fairy Tales","Text","475","7439","852","https://www.gutenberg.org/ebooks/7439","0","0","Unknown","1","February, 2005","2","February","2005","8","text/plain; charset=us-ascii,text/plain,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","9.5","8.82","5.83","4811","6.0","86.03","9.600000000000001","7.5","3.1","0.0797049039978293","0.49371392293611027","4.5","19.0","0.05","274260","811","3135","74587.5","60883" +"PS","en","Paris (France) -- Fiction,Man-woman relationships -- Fiction,Americans -- France -- Fiction,Psychological fiction,Young men -- Fiction","The Ambassadors","Text","474","432","853","https://www.gutenberg.org/ebooks/432","1843","1916","James, Henry","1","February, 1996","2","February","1996","7","text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","10.0","10.21","5.79","13443","7.6","71.14","8.8","11.0","3.1","0.13282047128407817","0.5079733387759909","4.79","17.0","0.06","775285","4846","9123","219842.1","162021" +"","en","","A Pail of Air","Text","473","51461","854","https://www.gutenberg.org/ebooks/51461","1910","1992","Leiber, Fritz","15","March 15, 2016","3","March","2016","8","image/jpeg,text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","8.8","8.59","6.29","645","6.8","78.59","9.200000000000001","7.0","3.1","0.053383245107383036","0.4816585212173448","4.46","18.0","0.05","25861","76","313","7294.5","5800" +"PL","en","Autobiographical fiction;China -- History -- Qing dynasty, 1644-1912 -- Fiction;Domestic fiction;Cao, Xueqin, approximately 1717-1763 -- Fiction;Jia, Baoyu (Fictitious character) -- Fiction","Hung Lou Meng, or, the Dream of the Red Chamber, a Chinese Novel, Book I","Text","473","9603","855","https://www.gutenberg.org/ebooks/9603","1715","1763","Cao, Xueqin","1","January, 2006","1","January","2006","8","text/html,text/plain; charset=us-ascii,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","14.5","10.51","6.05","12542","10.3","69.45","12.8","14.0","3.1","0.10779523916128833","0.4490715424049771","4.74","27.0","0.04","874241","4051","6757","248011.2","184327" +"PR","en","England -- Fiction,Detective and mystery stories","The Red House Mystery","Text","472","1872","856","https://www.gutenberg.org/ebooks/1872","1882","1956","Milne, A. A. (Alan Alexander)","1","August, 1999","8","August","1999","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","6.7","9.09","5.5","5036","4.0","85.69","6.4","5.5","3.1","0.06645752208777729","0.4870598107871714","4.75","11.0","0.09","287012","1127","5210","78778.8","60370" +"PR","en","Psychological fiction,Triangles (Interpersonal relations) -- Fiction,Missing persons -- Fiction,England -- Fiction,Mystery fiction,Choral conductors -- Fiction,Cathedrals -- Fiction,Separation (Psychology) -- Fiction","The Mystery of Edwin Drood","Text","472","564","857","https://www.gutenberg.org/ebooks/564","1812","1870","Dickens, Charles","25","December 25, 2010","12","December","2010","7","text/html,text/plain; charset=utf-8,text/plain; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.8","10.61","6.24","10966","7.2","72.16","8.4","5.5","3.1","0.08760718903691751","0.4992177504633191","4.86","16.0","0.06","464174","2701","5743","129901.5","95606" +"PQ","en","Murder -- Fiction,Guilt -- Fiction,Adultery -- Fiction","Theresa Raquin","Text","471","6626","858","https://www.gutenberg.org/ebooks/6626","1840","1902","Zola, Emile","22","April 22, 2006","4","April","2006","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","10.5","10.79","5.95","6591","7.6","71.14","8.8","19.0","3.1","0.013582576325879343","0.4919608853956109","4.89","17.0","0.06","346902","1810","3984","99846.0","70936" +"PR","en","British -- Foreign countries -- Fiction,Impostors and imposture -- Fiction,Adventure stories","The Prisoner of Zenda","Text","471","95","859","https://www.gutenberg.org/ebooks/95","1863","1933","Hope, Anthony","10","January 10, 2006","1","January","2006","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","7.6","8.69","5.92","5418","5.2","82.65","7.6000000000000005","55.0","3.1","0.09295242634592055","0.47140109045575","4.58","14.0","0.07","246183","801","3583","68324.4","53712" +"BR","en","Christianity -- Essence, genius, nature;Apologetics;Chesterton, G. K. (Gilbert Keith), 1874-1936","Orthodoxy","Text","470","16769","860","https://www.gutenberg.org/ebooks/16769","1874","1936","Chesterton, G. K. (Gilbert Keith)","28","September 28, 2005","9","September","2005","8","text/plain; charset=utf-8,text/plain; charset=us-ascii,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","10.8","10.1","6.37","7016","8.7","68.1","10.0","4.5","3.1","0.07488876795002697","0.5125026289895424","4.72","20.0","0.05","300209","2749","3180","90596.7","63642" +"PZ,PT","en","Family life -- Fiction,Survival -- Fiction,Islands -- Fiction","The Swiss Family Robinson; or Adventures in a Desert Island","Text","469","11703","861","https://www.gutenberg.org/ebooks/11703","1743","1818","Wyss, Johann David","24","March 24, 2004","3","March","2004","7","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","12.2","10.22","6.05","9840","8.7","73.51","11.200000000000001","7.0","3.1","0.13662616586577633","0.5027232475902264","4.69","23.0","0.04","574215","2906","5303","164467.8","122543" +"PA","en","Latin language -- Grammar","New Latin Grammar","Text","469","15665","862","https://www.gutenberg.org/ebooks/15665","1858","1921","Bennett, Charles E. (Charles Edwin)","20","April 20, 2005","4","April","2005","7","text/plain; charset=utf-8,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","11.0","14.48","7.21","15618","6.4","68.77","6.4","6.0","3.1","0.10220333438647515","0.41596249184995837","5.68","11.0","0.09","463619","4650","7233","119139.3","81574" +"PR,PZ","en","Fantasy fiction;Satire;Voyages, Imaginary -- Early works to 1800;Travelers -- Fiction;Gulliver, Lemuel (Fictitious character) -- Fiction","Gulliver's Travels into Several Remote Regions of the World","Text","469","17157","863","https://www.gutenberg.org/ebooks/17157","1667","1745","Swift, Jonathan","26","November 26, 2005","11","November","2005","9","image/jpeg,text/html; charset=iso-8859-1,text/plain,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","16.2","10.63","6.89","5832","12.6","57.95","14.0","5.5","3.1","0.10880184133876691","0.4684500981588397","4.71","30.0","0.03","245686","1346","1688","71464.5","52111" +"B","en","Hindu philosophy,India -- Religion","A History of Indian Philosophy, Volume 1","Text","468","12956","864","https://www.gutenberg.org/ebooks/12956","1885","1952","Dasgupta, Surendranath","20","July 20, 2004","7","July","2004","8","text/html,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","16.5","14.45","6.09","16981","12.7","47.12","11.600000000000001","21.0","8.8","0.07724100622713882","0.4637152296528388","5.42","24.0","0.04","1154886","16296","8603","334907.1","212995" +"PZ,PS","en","New England -- History -- 19th century -- Fiction,Family life -- New England -- Fiction,Boarding schools -- Fiction,Schools -- Fiction","Little Men","Text","468","2788","865","https://www.gutenberg.org/ebooks/2788","1832","1888","Alcott, Louisa May","1","2001","1","January","2001","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","10.4","8.94","5.89","8051","7.9","75.54","10.4","2.5","3.1","0.13241984029170245","0.5198706054167309","4.52","21.0","0.05","474837","1495","4975","132327.0","104971" +"PR","en","Psychological fiction,Epistolary fiction,England -- Fiction,Young women -- Crimes against -- Fiction,Conflict of generations -- Fiction,Rape victims -- Fiction,Kidnapping victims -- Fiction","Clarissa Harlowe; or the history of a young lady — Volume 1","Text","468","9296","866","https://www.gutenberg.org/ebooks/9296","1689","1761","Richardson, Samuel","1","November, 2005","11","November","2005","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","11.3","9.46","6.1","9318","9.5","66.07","10.8","14.5","3.1","0.12844338932586247","0.544504498581412","4.61","22.0","0.05","492734","3248","4843","144820.8","106924" +"TX","en","Vegetarianism,Food -- Analysis,Diet","The Chemistry of Food and Nutrition","Text","467","15237","867","https://www.gutenberg.org/ebooks/15237","0","0","Duncan, A. W.","2","March 2, 2005","3","March","2005","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","12.1","12.7","6.74","4727","8.7","62.68","8.8","11.0","3.1","0.08606164662817284","0.47103777954936993","5.22","17.0","0.06","172239","1839","1851","49484.7","32972" +"PS","en","Short stories, American;Fiction","Flappers and Philosophers","Text","467","4368","868","https://www.gutenberg.org/ebooks/4368","1896","1940","Fitzgerald, F. Scott (Francis Scott)","1","August, 2003","8","August","2003","8","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","9.3","11.07","6.41","7945","6.4","74.19","7.6000000000000005","18.5","3.1","0.057485445416860174","0.4806159973406343","4.99","14.0","0.07","301886","1727","4155","83546.1","60462" +"","fr","","La chanson des vieux époux","Text","467","51313","869","https://www.gutenberg.org/ebooks/51313","1850","1923","Loti, Pierre","27","February 27, 2016","2","February","2016","8","image/jpeg,text/html; charset=utf-8,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","19.0","15.1","9.52","773","12.2","58.96","13.600000000000001","8.5","3.1","0.09387400793650792","0.7027777777777778","5.48","29.0","0.03","15025","75","94","3972.6","2744" +"B,PA","en","Classical literature;Philosophy, Ancient;Socrates, 470 BC-399 BC;Piety -- Early works to 1800","Euthyphro","Text","466","1642","870","https://www.gutenberg.org/ebooks/1642","-428","-348","Plato","1","February, 1999","2","February","1999","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","11.0","9.92","6.44","1056","8.7","68.1","10.0","11.0","3.1","0.16249830052759745","0.5600563672438674","4.69","20.0","0.05","43113","208","447","12623.4","9202" +"PA","en","Epic poetry, Greek -- Translations into English;Hymns, Greek (Classical) -- Translations into English;Gods, Greek -- Poetry;Epic poetry, Greek;Hesiod -- Translations into English","Hesiod, the Homeric Hymns, and Homerica","Text","466","348","871","https://www.gutenberg.org/ebooks/348","0","0","Hesiod","5","July 5, 2008","7","July","2008","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","12.8","11.38","6.45","9810","8.3","74.53","10.8","14.5","3.1","0.13655120406824772","0.5224412960568154","4.89","22.0","0.04","441248","1832","4039","118998.0","90161" +"","en","","The Furious Rose","Text","466","51257","872","https://www.gutenberg.org/ebooks/51257","0","0","Evans, Dean","21","February 21, 2016","2","February","2016","7","text/plain,image/jpeg,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","6.5","9.54","6.34","643","3.3","87.72","5.6000000000000005","7.0","3.1","0.033560080514916296","0.4549068895419259","4.88","9.0","0.1","21990","108","459","5952.6","4508" +"JC","en","Great Britain -- Politics and government -- 1760-1820;France -- History -- Revolution, 1789-1799 -- Causes;Burke, Edmund, 1729-1797. Reflections on the revolution in France;Political science","The Writings of Thomas Paine — Volume 2 (1779-1792): The Rights of Man","Text","465","3742","873","https://www.gutenberg.org/ebooks/3742","1737","1809","Paine, Thomas","1","February, 2003","2","February","2003","8","application/rdf+xml,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,text/plain","15.3","11.73","6.4","8689","12.3","53.55","12.4","6.5","8.8","0.07867469266232535","0.4378467874227099","4.95","26.0","0.04","461496","4716","3471","137565.0","93230" +"","en","","Nursing as Caring: A Model for Transforming Practice","Text","465","42988","874","https://www.gutenberg.org/ebooks/42988","0","0","Boykin, Anne","20","June 20, 2013","6","June","2013","12","application/rdf+xml,image/jpeg,text/plain; charset=us-ascii,application/pdf,application/x-mobipocket-ebook,application/octet-stream,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/html; charset=iso-8859-1,text/plain,application/msword","14.4","15.14","6.45","4209","10.7","52.19","9.600000000000001","15.5","8.8","0.10308436199246854","0.41856854402907173","5.59","19.0","0.05","198690","2601","1863","56629.8","35556" +"PR","en","Ship captains -- Fiction,Fugitives from justice -- Fiction,Psychological fiction,Sea stories","The Secret Sharer","Text","463","220","875","https://www.gutenberg.org/ebooks/220","1857","1924","Conrad, Joseph","1","February 1995","2","February","1995","6","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","7.7","8.58","6.51","2229","5.6","81.63","8.0","27.5","3.1","0.022859249587897326","0.4754694408004009","4.56","15.0","0.07","75367","351","1083","21790.8","16538" +"K","en","Common law","The Common Law","Text","463","2449","876","https://www.gutenberg.org/ebooks/2449","1841","1935","Holmes, Oliver Wendell","1","December, 2000","12","December","2000","6","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","11.3","10.21","5.72","9100","7.6","76.56","10.0","4.5","3.1","0.06165126114660273","0.44151405947984645","4.74","20.0","0.05","625340","4665","6329","177481.8","132004" +"PS","en","Western stories,Frontier and pioneer life -- West (U.S.) -- Fiction","The Luck of Roaring Camp and Other Tales: With Condensed Novels, Spanish and American Legends, and Earlier Papers","Text","463","6373","877","https://www.gutenberg.org/ebooks/6373","1836","1902","Harte, Bret","1","August, 2004","8","August","2004","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","10.7","11.54","6.44","16450","7.2","72.16","8.4","18.5","3.1","0.06654640256468654","0.4755482478225085","5.02","16.0","0.06","649524","4492","7610","183800.7","129266" +"HX","en","Socialism","The Soul of Man under Socialism","Text","462","1017","878","https://www.gutenberg.org/ebooks/1017","1854","1900","Wilde, Oscar","26","September 26, 2014","9","September","2014","7","image/jpeg,text/html,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","10.0","10.32","6.69","2018","8.7","62.68","8.8","8.0","3.1","0.12331553055805884","0.5447954828305094","4.81","17.0","0.06","69161","764","820","21019.5","14391" +"DC","en","France -- History -- Revolution, 1789-1799;France -- History -- Louis XVI, 1774-1793","The French Revolution: A History","Text","462","1301","879","https://www.gutenberg.org/ebooks/1301","1795","1881","Carlyle, Thomas","15","February 15, 2006","2","February","2006","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","14.4","13.81","6.76","39727","10.3","58.62","10.4","1.5","3.1","0.05971791746935568","0.48970679977854986","5.36","21.0","0.05","1610702","14129","14188","450294.3","300739" +"PS","en","Swedish Americans -- Fiction,Women pioneers -- Fiction,Women farmers -- Fiction,Domestic fiction,Women immigrants -- Fiction,Frontier and pioneer life -- Nebraska -- Fiction,Historical fiction,Nebraska -- Fiction,Brothers and sisters -- Fiction,Farm life -- Fiction","O Pioneers!","Text","461","24","880","https://www.gutenberg.org/ebooks/24","1873","1947","Cather, Willa","1","January 1992","1","January","1992","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","7.3","8.69","5.75","4990","5.2","82.65","7.6000000000000005","13.0","3.1","0.08161564597512085","0.47308327051129134","4.58","14.0","0.07","254122","1163","3894","71888.4","55435" +"PR","en","Arthurian romances,Lady of the Lake (Legendary character) -- Romances","The Lady of the Lake","Text","461","3011","881","https://www.gutenberg.org/ebooks/3011","1771","1832","Scott, Walter","1","January, 2002","1","January","2002","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","12.1","11.72","6.68","10414","7.2","77.57","9.600000000000001","6.5","3.1","0.09757067452463182","0.48945360233868485","5.0","19.0","0.05","391852","1427","3947","102721.5","78425" +"D","en","World history,World history -- Juvenile literature","The Story of Mankind","Text","461","754","882","https://www.gutenberg.org/ebooks/754","1882","1944","Van Loon, Hendrik Willem","1","December, 1996","12","December","1996","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","12.6","11.31","6.16","12161","9.1","67.08","10.4","7.5","3.1","0.11101541682587594","0.4578413125762167","4.93","21.0","0.05","637026","4641","5995","186628.5","129204" +"PS","en","American poetry -- 20th century","A Boy's Will","Text","460","3021","883","https://www.gutenberg.org/ebooks/3021","1874","1963","Frost, Robert","1","January, 2002","1","January","2002","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","13.9","9.64","7.01","740","9.1","77.91","12.8","5.5","3.1","0.0862794102805264","0.49601716141001895","4.59","27.0","0.04","26318","38","209","7145.1","5737" +"PQ","fr","Poetry","Les Fleurs du Mal","Text","460","6099","884","https://www.gutenberg.org/ebooks/6099","1821","1867","Baudelaire, Charles","1","July, 2004","7","July","2004","7","text/html; charset=iso-8859-1,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","16.1","13.81","8.39","5514","10.7","63.02","12.0","19.0","3.1","0.09990522747948051","0.682167658730159","5.31","25.0","0.04","131501","341","990","34137.9","24751" +"HQ","en","Sex (Psychology),Sex","Studies in the Psychology of Sex, Volume 1: The Evolution of Modesty; The Phenomena of Sexual Periodicity; Auto-Erotism","Text","459","13610","885","https://www.gutenberg.org/ebooks/13610","1859","1939","Ellis, Havelock","8","October 8, 2004","10","October","2004","8","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","16.2","13.81","6.65","15679","13.0","46.1","12.0","7.5","8.8","0.12191525109195543","0.5005144428589046","5.31","25.0","0.04","740616","8488","5519","216453.6","139447" +"U","en","Military art and science -- Early works to 1800,War -- Early works to 1800","The Art of War","Text","458","17405","886","https://www.gutenberg.org/ebooks/17405","0","0","Sunzi, active 6th century B.C.","28","December 28, 2005","12","December","2005","7","text/html; charset=iso-8859-1,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","11.7","11.08","7.06","1683","8.7","68.1","10.0","5.5","3.1","0.059535866062083206","0.518208120080779","4.89","20.0","0.05","53504","363","543","15072.3","10936" +"PS","en","United States -- Social life and customs -- Fiction;Humorous stories, American","Sketches New and Old","Text","458","3189","887","https://www.gutenberg.org/ebooks/3189","1835","1910","Twain, Mark","1","April, 2002","4","April","2002","5","application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,image/jpeg","11.7","10.39","6.68","12386","9.1","67.08","10.4","58.0","3.1","0.09811391385953448","0.4988454416335551","4.77","21.0","0.05","466586","3130","4567","134607.6","97716" +"B","en","Philosophy","Hegel's Philosophy of Mind","Text","458","39064","888","https://www.gutenberg.org/ebooks/39064","1770","1831","Hegel, Georg Wilhelm Friedrich","5","March 5, 2012","3","March","2012","11","application/prs.tei,text/plain; charset=us-ascii,text/html; charset=utf-8,application/x-mobipocket-ebook,text/plain; charset=utf-8,application/octet-stream,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/pdf","17.0","13.76","6.6","12610","13.4","45.09","12.4","8.0","11.2","0.06290359855726985","0.4472751173209761","5.3","26.0","0.04","629417","9410","4420","187151.4","118842" +"PS","en","Mysticism -- Poetry,Parables","The Madman: His Parables and Poems","Text","458","5616","889","https://www.gutenberg.org/ebooks/5616","1883","1931","Gibran, Kahlil","1","May, 2004","5","May","2004","7","text/html; charset=utf-8,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","8.9","8.93","6.43","871","6.4","79.6","8.8","9.0","3.1","0.13453011030065823","0.5064890259410806","4.57","17.0","0.06","32207","75","399","8834.4","7052" +"ML","en","Paganini, Nicolò, 1782-1840;Violinists -- Biography","Nicolo Paganini: His Life and Work","Text","457","39571","890","https://www.gutenberg.org/ebooks/39571","1840","1906","Stratton, Stephen S. (Stephen Samuel)","29","April 29, 2012","4","April","2012","9","image/jpeg,text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","12.4","12.71","6.84","8008","9.5","60.65","9.600000000000001","3.0","8.8","0.1416088534957932","0.46775096955932755","5.17","19.0","0.05","289437","3157","2943","83926.8","55955" +"PQ","en","Molière, 1622-1673 -- Translations into English;Hypochondria -- Drama;Comedies","The Imaginary Invalid","Text","457","9070","891","https://www.gutenberg.org/ebooks/9070","1622","1673","Moliere","2","September 2, 2003","9","September","2003","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","8.1","9.85","6.43","2680","4.8","83.66","7.2","2.5","3.1","0.1379784760277495","0.5614889539057532","4.78","13.0","0.07","93964","464","1408","26114.4","19674" +"PZ","en","World War, 1914-1918 -- Prince Edward Island -- Juvenile fiction;Country life -- Canada -- Juvenile fiction;Prince Edward Island -- Juvenile fiction","Rilla of Ingleside","Text","455","3796","892","https://www.gutenberg.org/ebooks/3796","1874","1942","Montgomery, L. M. (Lucy Maud)","1","February, 2003","2","February","2003","7","text/html; charset=iso-8859-1,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","8.2","9.21","5.87","9767","5.6","81.63","8.0","54.0","3.1","0.050799156161206706","0.4919444613977015","4.67","15.0","0.07","482994","2028","6748","136524.6","103358" +"PZ","en","Rabbits -- Juvenile fiction","The Tale of Benjamin Bunny","Text","454","14407","893","https://www.gutenberg.org/ebooks/14407","1866","1943","Potter, Beatrix","21","December 21, 2004","12","December","2004","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","10.2","12.23","6.79","185","6.4","74.19","7.6000000000000005","4.0","3.1","0.054286271213354526","0.3828689057855726","5.19","14.0","0.07","6177","47","83","1621.8","1190" +"NC","en","Decoration and ornament,Drawing","Line and Form (1900)","Text","454","25290","894","https://www.gutenberg.org/ebooks/25290","1845","1915","Crane, Walter","2","May 2, 2008","5","May","2008","8","application/rdf+xml,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,text/plain","19.0","13.99","7.01","5291","14.2","48.47","14.4","5.5","8.8","0.1319788677324939","0.4833963807185189","5.29","31.0","0.03","241540","2451","1468","69435.0","45623" +"E151","en","United States -- Social life and customs -- 1783-1865;Dickens, Charles, 1812-1870 -- Travel -- United States;United States -- Description and travel","American Notes","Text","454","675","895","https://www.gutenberg.org/ebooks/675","1812","1870","Dickens, Charles","18","February 18, 2013","2","February","2013","6","text/html,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","16.2","11.38","6.96","12331","12.2","58.96","13.600000000000001","11.5","3.1","0.09512242920910764","0.48435171673925975","4.84","29.0","0.03","499881","3466","3476","145466.1","103322" +"PA,JC","en","Political science -- Early works to 1800;State, The -- Early works to 1800","Laws","Text","453","1750","896","https://www.gutenberg.org/ebooks/1750","-428","-348","Plato","1","May, 1999","5","May","1999","6","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/rdf+xml,application/epub+zip,text/plain","16.6","10.69","6.14","14601","13.0","56.93","14.4","11.5","8.8","0.1335592640414666","0.504477488386724","4.72","31.0","0.03","1125953","7841","7530","335637.0","238593" +"","de","","Demian: Die Geschichte von Emil Sinclairs Jugend","Text","453","41907","897","https://www.gutenberg.org/ebooks/41907","1877","1962","Hesse, Hermann","24","January 24, 2013","1","January","2013","7","text/html; charset=iso-8859-1,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","11.2","13.05","6.73","7032","6.8","73.17","8.0","5.5","3.1","0.26379897642327116","0.6574297188755022","5.28","15.0","0.06","249434","1102","3052","65056.5","47222" +"PS","en","Racially mixed people -- Fiction,African American men -- Fiction","The Autobiography of an Ex-Colored Man","Text","452","11012","898","https://www.gutenberg.org/ebooks/11012","1871","1938","Johnson, James Weldon","9","February 9, 2004","2","February","2004","8","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","12.1","9.64","6.5","5653","9.9","65.05","11.200000000000001","19.0","3.1","0.11989797564462013","0.459904012905849","4.59","23.0","0.04","237815","1593","2177","70965.0","51804" +"PS","en","Fantasy poetry, American","The Complete Poetical Works of Edgar Allan Poe: Including Essays on Poetry","Text","451","10031","899","https://www.gutenberg.org/ebooks/10031","1809","1849","Poe, Edgar Allan","10","November 10, 2003","11","November","2003","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","14.0","12.65","7.19","9392","9.5","66.07","10.8","10.5","3.1","0.12517435887118686","0.5135634301187022","5.11","22.0","0.04","308412","2177","2645","85563.9","60330" +"PR","en","Humorous stories,Men -- England -- Fiction,Diary fiction,England -- Fiction,Suburban life -- Fiction,Middle class -- Fiction","The Diary of a Nobody","Text","451","1026","900","https://www.gutenberg.org/ebooks/1026","1852","1919","Grossmith, Weedon","14","August 14, 2011","8","August","2011","6","text/html,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","7.9","9.04","5.97","4345","5.2","82.65","7.6000000000000005","7.0","3.1","0.07110745400998242","0.49833415693874333","4.64","14.0","0.07","194604","968","2812","55386.9","41930" +"F001","en","Massachusetts -- History -- Colonial period, ca. 1600-1775","Bradford's History of 'Plimoth Plantation': From the Original Manuscript. With a Report of the Proceedings Incident to the Return of the Manuscript to Massachusetts","Text","451","24950","901","https://www.gutenberg.org/ebooks/24950","1590","1657","Bradford, William","29","March 29, 2008","3","March","2008","8","text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","13.4","10.86","6.11","13688","9.1","72.5","11.600000000000001","5.5","3.1","0.18046822505168494","0.4590197231930973","4.8","24.0","0.04","808901","3601","6910","226529.1","168627" +"PZ","en","Nursery rhymes,Children's poetry","The Real Mother Goose","Text","450","10607","902","https://www.gutenberg.org/ebooks/10607","0","0","Unknown","5","January 5, 2004","1","January","2004","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","10.5","10.15","6.11","1557","6.0","86.03","9.600000000000001","18.0","3.1","0.05448300610535866","0.46017777876947213","4.73","19.0","0.05","75688","57","830","19559.7","16013" +"PZ,PS","en","Plantation life -- Fiction;Animals -- Fiction;African American men -- Fiction;Remus, Uncle (Fictitious character) -- Fiction;Georgia -- Social life and customs -- Fiction","Uncle Remus and Brer Rabbit","Text","450","22282","903","https://www.gutenberg.org/ebooks/22282","1848","1908","Harris, Joel Chandler","9","August 9, 2007","8","August","2007","6","text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","10.3","8.12","6.15","623","7.2","82.98","10.8","5.0","3.1","0.12381677083023457","0.4275494318361756","4.38","22.0","0.05","30239","98","312","8043.3","6904" +"PK","en","Persian poetry -- Translations into English","The Rubaiyat of Omar Khayyam","Text","450","246","904","https://www.gutenberg.org/ebooks/246","1048","1122","Omar Khayyam","1","April, 1995","4","April","1995","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","14.8","12.19","7.7","2092","10.7","63.02","12.0","11.0","3.1","0.0929561175147684","0.48537149002758634","5.03","25.0","0.04","58957","319","466","16100.1","11716" +"PL","en","Cebuano language -- Dictionaries -- English","A Dictionary of Cebuano Visayan","Text","450","40074","905","https://www.gutenberg.org/ebooks/40074","0","0","Wolff, John U.","24","June 24, 2012","6","June","2012","6","text/plain; charset=utf-8,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","6.2","9.25","5.77","103095","3.3","87.72","5.6000000000000005","7.0","3.1","0.016062887238603767","0.4636119056926238","4.83","9.0","0.1","4658929","29609","97861","1247171.4","964198" +"","en","","Lords and Lovers: and Other Dramas","Text","450","51282","906","https://www.gutenberg.org/ebooks/51282","1869","1968","Dargan, Olive Tilford","22","February 22, 2016","2","February","2016","7","image/jpeg,text/html; charset=utf-8,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","6.8","9.78","5.63","6971","2.5","95.17","6.0","56.0","3.1","0.1668995085205963","0.5190351855131032","4.87","10.0","0.09","356882","735","6895","90853.2","73261" +"","en","","The Slang Dictionary: Etymological, Historical and Andecdotal","Text","449","42108","907","https://www.gutenberg.org/ebooks/42108","0","0","Hotten, John Camden","16","February 16, 2013","2","February","2013","9","image/jpeg,text/plain; charset=utf-8,text/plain; charset=us-ascii,text/html; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","10.9","13.39","6.77","24807","7.2","66.74","7.2","4.0","3.1","0.05426228414550942","0.4544068931940714","5.39","13.0","0.07","847901","7464","11248","231826.5","157261" +"PR","en","Detective and mystery stories, English;Horror tales, English","Tales of Terror and Mystery","Text","449","537","908","https://www.gutenberg.org/ebooks/537","1859","1930","Doyle, Arthur Conan","1","May, 1996","5","May","1996","6","text/html; charset=iso-8859-1,text/plain,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","9.8","9.69","6.19","7917","7.9","70.13","9.200000000000001","54.0","3.1","0.06994043554317293","0.5015683152420384","4.65","18.0","0.05","349340","1891","4034","102024.0","75100" +"PS","en","Bildungsromans,Autobiographical fiction,Authors -- Fiction,San Francisco (Calif.) -- Fiction,Working class -- Fiction,Young men -- Fiction","Martin Eden","Text","448","1056","909","https://www.gutenberg.org/ebooks/1056","1876","1916","London, Jack","25","November 25, 2004","11","November","2004","7","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","8.6","9.92","5.89","13304","5.6","81.63","8.0","11.0","3.1","0.10658698657777987","0.5066089169303423","4.74","15.0","0.06","657206","3938","8987","186489.0","138767" +"PR","en","Magicians -- Drama;Tragedies;Germany -- Drama;Faust, -approximately 1540 -- Drama","The Tragical History of Doctor Faustus: From the Quarto of 1616","Text","448","811","910","https://www.gutenberg.org/ebooks/811","1564","1593","Marlowe, Christopher","1","February, 1997","2","February","1997","7","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","8.9","11.59","6.24","2835","4.4","84.68","6.800000000000001","5.5","3.1","0.1458036609607627","0.4990775969112156","5.13","12.0","0.08","114433","375","1795","28475.1","22297" +"PZ,PJ","en","Fairy tales -- Arab countries,Fairy tales,Folklore -- Arab countries,Children's stories,Tales -- Arab countries,Arabs -- Folklore","The Arabian Nights Entertainments","Text","447","128","911","https://www.gutenberg.org/ebooks/128","1844","1912","Lang, Andrew","9","June 9, 2008","6","June","2008","6","text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","12.0","9.23","5.84","7174","9.1","72.5","11.600000000000001","52.0","3.1","0.11937383750959953","0.5021455041929525","4.52","24.0","0.04","504353","1509","4594","145614.6","111586" +"PR","en","Fantasy fiction, English;Horror tales, English;Supernatural -- Fiction","Four Weird Tales","Text","445","16726","912","https://www.gutenberg.org/ebooks/16726","1869","1951","Blackwood, Algernon","20","September 20, 2005","9","September","2005","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","10.7","11.37","6.49","6868","7.6","71.14","8.8","28.5","3.1","0.044254835478798514","0.49784608255067797","4.99","17.0","0.06","269395","1737","3126","76867.2","54037" +"BF","en","Witchcraft -- Scotland;Fian, John, d. 1591;Magic;Demonology","Daemonologie.","Text","443","25929","913","https://www.gutenberg.org/ebooks/25929","1566","1625","James I, King of England","29","June 29, 2008","6","June","2008","10","application/prs.tei,text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/plain; charset=utf-8,text/html; charset=utf-8,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/pdf","23.7","12.09","7.92","3629","17.7","44.75","19.200000000000003","4.5","3.1","0.07539954641928327","0.4620168716221344","4.91","43.0","0.02","130985","555","608","37359.0","26697" +"","en","","A Beginner's Psychology","Text","443","51442","914","https://www.gutenberg.org/ebooks/51442","0","0","Titchener, Edward Bradford","14","March 14, 2016","3","March","2016","7","image/jpeg,text/html; charset=utf-8,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","14.1","12.94","6.43","11280","10.7","57.61","10.8","5.0","8.8","0.0696654658921719","0.4498369916097325","5.16","22.0","0.04","541032","6454","4652","156313.8","104870" +"HT","en","Fugitive slaves -- West Indies -- Biography;Slavery -- West Indies;Prince, Mary","The History of Mary Prince, a West Indian Slave","Text","442","17851","915","https://www.gutenberg.org/ebooks/17851","1788","1833","Prince, Mary","24","February 24, 2006","2","February","2006","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","11.1","9.28","6.58","3285","7.9","75.54","10.4","4.5","3.1","0.049591759740023715","0.5118022127979603","4.58","21.0","0.05","125085","722","1250","36383.4","27289" +"PR","en","Fathers and daughters -- Fiction,Trials (Murder) -- Fiction,Political fiction,Domestic fiction,Poor families -- Fiction,Triangles (Interpersonal relations) -- Fiction,Manchester (England) -- Fiction,Working class women -- Fiction,Labor unions -- Fiction,Textile industry -- Fiction,Love stories","Mary Barton","Text","442","2153","916","https://www.gutenberg.org/ebooks/2153","1810","1865","Gaskell, Elizabeth Cleghorn","1","January 1, 1848","1","January","1848","8","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","10.1","9.57","5.82","12620","7.2","77.57","9.600000000000001","1.5","3.1","0.06862205671622976","0.5125818842460916","4.63","19.0","0.05","744592","2700","8220","208900.8","160646" +"PR,PZ","en","Fairies -- Fiction;Kensington Gardens (London, England) -- Fiction;Kensington (London, England) -- Fiction;Adventure stories;Peter Pan (Fictitious character) -- Fiction","The Little White Bird; Or, Adventures in Kensington Gardens","Text","441","1376","917","https://www.gutenberg.org/ebooks/1376","1860","1937","Barrie, J. M. (James Matthew)","1","July, 1998","7","July","1998","6","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/rdf+xml,application/epub+zip,text/plain","10.6","8.65","6.13","6094","7.9","75.54","10.4","1.5","3.1","0.08554097711734472","0.5106338661451854","4.47","21.0","0.05","296337","1195","3020","85405.5","66273" +"","en","","Capture and Escape: A Narrative of Army and Prison Life","Text","441","51451","918","https://www.gutenberg.org/ebooks/51451","0","0","Kellogg, John Azor","14","March 14, 2016","3","March","2016","8","image/jpeg,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","10.5","10.79","6.52","4911","7.9","70.13","9.200000000000001","11.0","3.1","0.08458585491788599","0.4783166796653638","4.84","18.0","0.05","188784","1185","2126","54577.8","39030" +"B","en","Philosophy, German;Ethics;Practical reason","The Critique of Practical Reason","Text","441","5683","919","https://www.gutenberg.org/ebooks/5683","1724","1804","Kant, Immanuel","1","May, 2004","5","May","2004","7","text/html,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","25.9","12.78","7.16","4736","20.4","32.23","20.8","11.0","13.0","0.09445096054053644","0.48909118455608486","5.03","47.0","0.02","315751","4012","1326","96999.3","62786" +"PR","en","English poetry","The Poetical Works of John Milton","Text","440","1745","920","https://www.gutenberg.org/ebooks/1745","1608","1674","Milton, John","1","May, 1999","5","May","1999","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","22.9","12.03","7.55","16965","16.1","54.23","18.8","5.5","3.1","0.1282440327202716","0.5056471921606076","4.9","42.0","0.02","715335","1842","3439","188400.6","146106" +"PS","en","African Americans -- Poetry","The Complete Poems of Paul Laurence Dunbar","Text","440","18338","921","https://www.gutenberg.org/ebooks/18338","1872","1906","Dunbar, Paul Laurence","7","May 7, 2006","5","May","2006","8","text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","11.6","9.23","6.25","8368","7.5","81.97","11.200000000000001","5.5","3.1","0.12974795252315474","0.5149316156249669","4.52","23.0","0.04","404516","496","3799","105090.3","89577" +"PQ","en","French poetry -- Translations into English","The Flowers of Evil","Text","440","36098","922","https://www.gutenberg.org/ebooks/36098","1821","1867","Baudelaire, Charles","13","May 13, 2011","5","May","2011","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","15.4","13.18","7.99","1571","10.3","64.04","11.600000000000001","57.0","3.1","0.10446802604457602","0.5701695526695527","5.2","24.0","0.04","40830","149","318","10817.1","7853" +"SK","en","Camping","Woodcraft and Camping","Text","439","34607","923","https://www.gutenberg.org/ebooks/34607","1821","1890","Sears, George Washington","9","December 9, 2010","12","December","2010","7","application/rdf+xml,text/html; charset=iso-8859-1,text/plain,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","11.3","9.63","6.57","4696","7.9","75.54","10.4","7.0","3.1","0.10970989295709156","0.4697165795736123","4.64","21.0","0.05","181622","664","1802","51229.8","39101" +"PT","de","Murderers -- Drama,Soldiers -- Mental health -- Drama,Germany -- Drama","Woyzeck","Text","439","5322","924","https://www.gutenberg.org/ebooks/5322","1813","1837","Buchner, Georg","1","March, 2004","3","March","2004","8","text/html,text/plain; charset=utf-8,text/plain; charset=us-ascii,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","9.0","12.84","7.23","1275","2.9","88.74","5.2","8.5","3.1","0.6709787079782199","0.8382575757575754","5.5","8.0","0.11","34610","132","701","8239.5","6296" +"","en","","Hamewith","Text","438","51412","925","https://www.gutenberg.org/ebooks/51412","1843","1924","Murray, Charles Theodore","9","March 09, 2016","3","March","2016","10","image/jpeg,text/html; charset=utf-8,text/plain; charset=us-ascii,text/plain; charset=utf-8,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/x-rst,application/x-mobipocket-ebook","15.1","13.18","7.73","2526","9.1","72.5","11.600000000000001","11.0","3.1","0.08627270247997464","0.4685066664791861","5.2","24.0","0.04","71487","259","570","17592.3","13757" +"PT","de","Unrequited love -- Fiction,Young men -- Germany -- Fiction,Germany -- Social life and customs -- Fiction","Die Leiden des jungen Werther — Band 1","Text","437","2407","926","https://www.gutenberg.org/ebooks/2407","1749","1832","Goethe, Johann Wolfgang von","29","September 29, 1774","9","September","1774","7","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","14.8","14.1","7.86","3526","9.1","67.08","10.4","4.0","3.1","0.07630511552859574","0.7380952380952385","5.41","21.0","0.05","94674","511","814","24588.9","17490" +"","en","","Narrative and Critical History of America, Vol. IV (of 8): French Explorations and Settlements in North America and Those of the Portuguese, Dutch, and Swedes 1500-1700","Text","437","51291","927","https://www.gutenberg.org/ebooks/51291","0","0","Various","23","February 23, 2016","2","February","2016","7","text/html,image/jpeg,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","12.5","13.23","5.99","26618","7.9","70.13","9.200000000000001","5.0","3.1","0.10201049319345686","0.38730982207487674","5.26","18.0","0.05","1516176","13323","15798","410284.8","288067" +"BQ","en","Zen priests -- Biography,Zen Buddhism -- History","The Zen Experience","Text","436","34325","928","https://www.gutenberg.org/ebooks/34325","1941","0","Hoover, Thomas","14","November 14, 2010","11","November","2010","10","text/plain,text/html; charset=utf-8,text/plain; charset=us-ascii,application/pdf,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook,application/msword","13.0","13.58","6.39","11045","9.1","61.67","9.200000000000001","8.5","8.8","0.10714170384258132","0.4407813454487429","5.32","18.0","0.05","499508","5208","5025","140032.8","93881" +"","en","","An Elephant for the Prinkip","Text","436","51434","929","https://www.gutenberg.org/ebooks/51434","0","0","Wesley, Joseph","13","March 13, 2016","3","March","2016","8","text/plain,image/jpeg,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","7.0","8.87","6.49","542","4.8","83.66","7.2","7.0","3.1","0.13255448406099862","0.49573194630197925","4.61","13.0","0.07","17888","57","287","5097.6","3877" +"TX","en","Cooking -- Pennsylvania","Pennsylvania Dutch Cooking","Text","435","26558","930","https://www.gutenberg.org/ebooks/26558","0","0","Unknown","8","September 8, 2008","9","September","2008","9","image/jpeg,text/plain; charset=utf-8,text/plain; charset=us-ascii,text/html; charset=utf-8,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","7.8","10.6","5.34","1226","2.9","94.15","6.4","12.5","3.1","0.041147653083137024","0.5028392226779334","4.96","11.0","0.08","83183","190","1418","20467.8","16765" +"PS","en","Science fiction,Short stories","The Hanging Stranger","Text","435","41562","931","https://www.gutenberg.org/ebooks/41562","1928","1982","Dick, Philip K.","5","December 5, 2012","12","December","2012","8","image/jpeg,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","5.6","9.0","6.59","864","2.5","89.75","4.800000000000001","5.0","3.1","-0.031309633747278784","0.46953796976418855","4.94","7.0","0.13","25847","96","688","6989.4","5233" +"PZ","en","Outdoor life -- Juvenile fiction,Oceania -- Juvenile fiction,Shipwrecks -- Juvenile fiction,Robinsonades,Conduct of life -- Juvenile fiction,Islands -- Juvenile fiction,Pirates -- Juvenile fiction,Survival skills -- Juvenile fiction,Natural history -- Juvenile fiction,Camping -- Juvenile fiction,Shipwreck survival -- Juvenile fiction","The Coral Island: A Tale of the Pacific Ocean","Text","435","646","932","https://www.gutenberg.org/ebooks/646","1825","1894","Ballantyne, R. M. (Robert Michael)","12","April 12, 2007","4","April","2007","8","image/jpeg,text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","12.7","9.7","6.06","7774","9.1","72.5","11.600000000000001","5.0","3.1","0.08326334679796331","0.4879022322844491","4.6","24.0","0.04","457891","1984","4003","131589.9","99504" +"","en","","The Wonderful Wizard of Oz","Text","434","43936","933","https://www.gutenberg.org/ebooks/43936","1856","1919","Baum, L. Frank (Lyman Frank)","6","January 6, 2014","1","January","2014","6","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","9.2","8.94","5.49","2438","6.8","78.59","9.200000000000001","11.0","3.1","0.12355288337309729","0.5167008070070667","4.52","18.0","0.05","180730","354","2136","50029.2","40009" +"PR","en","Nuclear warfare -- Fiction,Imaginary wars and battles -- Fiction,War stories","The World Set Free","Text","432","1059","934","https://www.gutenberg.org/ebooks/1059","1866","1946","Wells, H. G. (Herbert George)","11","February 11, 2006","2","February","2006","6","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/rdf+xml,application/epub+zip,text/plain","12.6","11.66","6.86","8977","10.3","58.62","10.4","14.0","3.1","0.08094761120979337","0.4702533919027105","4.99","21.0","0.05","324138","3003","3085","94842.0","64967" +"BL","en","Mythology, Celtic;Celts -- Religion","The Religion of the Ancient Celts","Text","432","14672","935","https://www.gutenberg.org/ebooks/14672","1868","1950","MacCulloch, J. A. (John Arnott)","12","January 12, 2005","1","January","2005","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","11.2","12.18","6.03","13267","7.2","72.16","8.4","6.0","3.1","0.0930635082156037","0.434171246688372","5.13","16.0","0.06","672025","4837","7721","181822.5","130922" +"PG","en","Russia -- Social life and customs -- Fiction;Dostoyevsky, Fyodor, 1821-1881 -- Translations into English;Short stories, Russian -- Translations into English","Short Stories","Text","432","40745","936","https://www.gutenberg.org/ebooks/40745","1821","1881","Dostoyevsky, Fyodor","13","September 13, 2012","9","September","2012","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","8.3","9.56","5.88","7901","6.4","74.19","7.6000000000000005","29.5","3.1","0.08140356419330959","0.49730356871906856","4.73","14.0","0.07","380552","2596","5391","109578.6","80442" +"PR","en","Fathers and daughters -- Fiction,Stepfamilies -- Fiction,Social classes -- Fiction,Children of physicians -- Fiction,Bildungsromans,England -- Fiction,Domestic fiction,Young women -- Fiction,Love stories","Wives and Daughters","Text","432","4274","937","https://www.gutenberg.org/ebooks/4274","1810","1865","Gaskell, Elizabeth Cleghorn","26","December 26, 2001","12","December","2001","8","text/plain; charset=us-ascii,text/plain,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","9.6","9.51","5.56","17722","6.8","78.59","9.200000000000001","5.0","3.1","0.10994870541935758","0.5248575619693703","4.67","18.0","0.06","1262322","5768","14887","357757.2","270270" +"PN","en","English essays,Poetry","A Defence of Poetry and Other Essays","Text","432","5428","938","https://www.gutenberg.org/ebooks/5428","1792","1822","Shelley, Percy Bysshe","1","April, 2004","4","April","2004","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","18.3","13.07","7.59","4375","15.4","40.01","14.4","11.0","8.8","0.13782425931105338","0.5005908802245659","5.13","31.0","0.03","146528","1751","919","44339.4","28563" +"PT","en","Authors -- Fiction,Norway -- Fiction,Hunger -- Fiction,Starvation -- Fiction,Urban poor -- Fiction","Hunger","Text","431","8387","939","https://www.gutenberg.org/ebooks/8387","1859","1952","Hamsun, Knut","1","June, 2005","6","June","2005","8","application/rdf+xml,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/plain; charset=us-ascii,text/plain","7.9","8.58","5.99","6599","6.0","80.62","8.4","15.0","3.1","0.05681140426074576","0.4870293712821899","4.51","16.0","0.06","300792","1410","4101","86971.5","66663" +"PZ,PS","en","Fantasy fiction,Tarzan (Fictitious character) -- Fiction,Adventure stories","The Return of Tarzan","Text","430","81","940","https://www.gutenberg.org/ebooks/81","1875","1950","Burroughs, Edgar Rice","23","June 23, 2008","6","June","2008","7","text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","10.4","10.15","5.96","7820","8.3","69.11","9.600000000000001","25.5","3.1","0.06002144390991959","0.4746804675133224","4.73","19.0","0.05","422047","1770","4684","120796.2","89190" +"PS","en","Poetry","Prufrock and Other Observations","Text","429","1459","941","https://www.gutenberg.org/ebooks/1459","1888","1965","Eliot, T. S. (Thomas Stearns)","1","September, 1998","9","September","1998","6","text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","12.4","10.97","7.51","685","7.9","75.54","10.4","8.0","3.1","0.018567594714653544","0.47398467871997313","4.87","21.0","0.05","18623","73","176","5046.3","3826" +"PR","en","Apologetics;Chesterton, G. K. (Gilbert Keith), 1874-1936","Heretics","Text","429","470","942","https://www.gutenberg.org/ebooks/470","1874","1936","Chesterton, G. K. (Gilbert Keith)","1","March, 1996","3","March","1996","7","text/html; charset=iso-8859-1,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,application/x-mobipocket-ebook","11.3","10.39","6.42","7337","8.7","68.1","10.0","8.5","3.1","0.11308282833221926","0.5183114869079091","4.77","20.0","0.05","308417","2976","3147","93195.9","64683" +"PN","en","Short stories","The Great English Short-Story Writers, Volume 1","Text","427","10135","943","https://www.gutenberg.org/ebooks/10135","0","0","Unknown","19","November 19, 2003","11","November","2003","7","text/html,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","12.2","10.62","6.69","10935","9.1","67.08","10.4","3.0","3.1","0.10320356963725927","0.5045075202807995","4.81","21.0","0.05","413165","2557","3914","117201.6","85845" +"BP","en","Theosophy -- Doctrines,Thought and thinking -- Religious aspects -- Theosophy","Thought-Forms","Text","427","16269","944","https://www.gutenberg.org/ebooks/16269","1854","1934","Leadbeater, C. W. (Charles Webster)","12","July 12, 2005","7","July","2005","8","application/rdf+xml,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/html; charset=iso-8859-1,text/plain","17.5","12.54","7.36","2977","13.8","49.49","14.0","11.5","8.8","0.09399859231200738","0.48932263521918684","5.04","30.0","0.03","106072","1093","691","31296.6","21062" +"PQ","en","Hell;Epic poetry, Italian -- Translations into English;Italian poetry -- To 1400 -- Translations into English","The Divine Comedy of Dante Alighieri: The Inferno","Text","427","41537","945","https://www.gutenberg.org/ebooks/41537","1265","1321","Dante Alighieri","2","December 2, 2012","12","December","2012","8","text/html; charset=iso-8859-1,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","12.8","11.2","6.51","13041","9.5","66.07","10.8","9.0","3.1","0.09963528424910617","0.48997349009730456","4.86","22.0","0.04","563037","2915","5128","156377.7","115770" +"PT","en","Mythology, Norse;Scalds and scaldic poetry","The Elder Eddas of Saemund Sigfusson; and the Younger Eddas of Snorre Sturleson","Text","426","14726","946","https://www.gutenberg.org/ebooks/14726","0","1241","Snorri Sturluson","18","January 18, 2005","1","January","2005","7","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","10.3","10.73","6.36","10408","6.4","79.6","8.8","6.0","3.1","0.14717092314394642","0.5236638006572445","4.88","17.0","0.06","425511","1167","5012","112531.5","87242" +"PS","en","Science fiction,Short stories","The Crystal Crypt","Text","425","28698","947","https://www.gutenberg.org/ebooks/28698","1928","1982","Dick, Philip K.","6","May 6, 2009","5","May","2009","7","text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","6.7","9.95","6.36","1057","3.3","87.72","5.6000000000000005","4.5","3.1","0.016375859868660362","0.4457139308474864","4.95","9.0","0.1","36267","76","757","9789.3","7334" +"HM","en","Social psychology,Public opinion -- United States,United States -- Politics and government,Public opinion,Social psychology -- United States","Public Opinion","Text","425","6456","948","https://www.gutenberg.org/ebooks/6456","1889","1974","Lippmann, Walter","1","September, 2004","9","September","2004","8","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","13.2","12.24","6.51","12093","10.3","58.62","10.4","17.0","8.8","0.1017515883223328","0.4621484764720288","5.09","21.0","0.05","529617","6108","4876","158416.2","104125" +"PK","en","Bengali poetry -- Translations into English;Indic poetry -- Translations into English;Tagore, Rabindranath, 1861-1941 -- Translations into English","The Gardener","Text","425","6686","949","https://www.gutenberg.org/ebooks/6686","1861","1941","Tagore, Rabindranath","1","October, 2004","10","October","2004","7","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","6.5","7.53","5.77","1280","4.0","91.11","7.6000000000000005","9.0","3.1","0.06688109897972877","0.5093662005580302","4.38","14.0","0.07","61279","77","958","16740.0","13996" +"PG","en","Tolstoy, Leo, graf, 1828-1910 -- Translations into English;Short stories;Russia -- Social life and customs -- Fiction","The Kreutzer Sonata and Other Stories","Text","425","689","950","https://www.gutenberg.org/ebooks/689","1828","1910","Tolstoy, Leo, graf","18","March 18, 2006","3","March","2006","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.6","9.68","6.09","6516","7.6","71.14","8.8","8.5","3.1","0.06446006086898316","0.49887777001091504","4.7","17.0","0.06","300899","1747","3603","87301.8","63979" +"PS","en","Ghost stories,Fiction","The Jolly Corner","Text","424","1190","951","https://www.gutenberg.org/ebooks/1190","1843","1916","James, Henry","13","May 13, 2005","5","May","2005","7","text/html,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","14.2","10.74","7.47","2282","11.1","62.01","12.4","13.5","3.1","0.08256195209032344","0.48403434770420706","4.78","26.0","0.04","67719","484","540","19573.2","14158" +"TT","en","Furniture making -- Amateurs' manuals;Furniture, Mission -- Design and construction","Mission Furniture: How to Make It, Part 3","Text","424","23666","952","https://www.gutenberg.org/ebooks/23666","1859","1924","Windsor, H. H. (Henry Haven)","30","November 30, 2007","11","November","2007","7","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","7.0","8.11","5.31","1210","4.0","91.11","7.6000000000000005","11.0","3.1","0.12791087034639007","0.4159055093764012","4.48","14.0","0.07","87157","301","1324","22741.2","19461" +"B","en","Yoga -- Early works to 1800","The Yoga Sutras of Patanjali: The Book of the Spiritual Man","Text","424","2526","953","https://www.gutenberg.org/ebooks/2526","0","0","Patanjali","1","February, 2001","2","February","2001","6","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","14.2","12.13","6.65","3584","9.9","65.05","11.200000000000001","20.5","3.1","0.12463903967505562","0.4228521231191227","5.02","23.0","0.04","151966","1178","1266","43891.2","30296" +"PR","en","Fantasy fiction, English;Short stories;Science fiction, English","The Door in the Wall, and Other Stories","Text","423","456","954","https://www.gutenberg.org/ebooks/456","1866","1946","Wells, H. G. (Herbert George)","22","July 22, 2005","7","July","2005","7","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","9.5","9.74","6.45","5382","6.4","79.6","8.8","14.5","3.1","0.048415218272844174","0.4844110228559049","4.71","17.0","0.06","202750","993","2456","57279.6","43052" +"DE","en","Greece -- Biography -- Early works to 1800,Rome -- Biography -- Early works to 1800","Plutarch's Lives, Volume I","Text","422","14033","955","https://www.gutenberg.org/ebooks/14033","46","119","Plutarch","12","November 12, 2004","11","November","2004","8","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","19.2","11.44","6.62","14560","14.6","52.87","16.0","4.5","8.8","0.1409098238062464","0.4966092095433028","4.85","35.0","0.03","893286","5939","5186","262855.8","184338" +"PQ","fr","Adventure stories;Revenge -- Fiction;France -- History -- 19th century -- Fiction;Pirates -- Fiction;Historical fiction;Prisoners -- Fiction;Dantès, Edmond (Fictitious character) -- Fiction","Le comte de Monte-Cristo, Tome I","Text","422","17989","956","https://www.gutenberg.org/ebooks/17989","1802","1870","Dumas, Alexandre","15","March 15, 2006","3","March","2006","7","text/html; charset=iso-8859-1,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","13.3","13.0","6.5","14445","8.7","68.1","10.0","2.0","3.1","0.07509363406660195","0.5939940519829606","5.22","20.0","0.05","634607","2195","5971","168939.9","121578" +"GT","en","Japan -- Social life and customs,Japanese tea ceremony,Tea","The Book of Tea","Text","422","769","957","https://www.gutenberg.org/ebooks/769","1862","1913","Okakura, Kakuzo","1","January, 1997","1","January","1997","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","12.0","11.84","7.63","3474","9.5","60.65","9.600000000000001","7.5","3.1","0.1270930278849212","0.4851650758036999","5.02","19.0","0.05","90237","903","918","26858.7","17976" +"PR","en","Princes -- Fiction,Happiness -- Fiction,Satire,Ethiopia -- Fiction","Rasselas, Prince of Abyssinia","Text","421","652","958","https://www.gutenberg.org/ebooks/652","1709","1784","Johnson, Samuel","31","January 31, 2013","1","January","2013","7","image/jpeg,text/html,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","14.5","11.73","7.06","5259","11.9","54.56","12.0","7.0","8.8","0.12683616449209079","0.5092443634407938","4.95","25.0","0.04","187806","1516","1502","55374.3","37973" +"PA","en","Classical literature;Jason (Greek mythology);Argonauts (Greek mythology);Medea, consort of Aegeus, King of Athens (Mythological character)","The Argonautica","Text","421","830","959","https://www.gutenberg.org/ebooks/830","0","0","Apollonius, Rhodius","1","February, 1997","2","February","1997","7","text/plain,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","15.9","10.22","6.58","5746","11.5","66.41","14.0","4.5","3.1","0.0718966335484308","0.5024139259542105","4.64","30.0","0.03","288695","690","2016","78750.0","62210" +"PQ","it","Italian poetry -- To 1400;Epic poetry, Italian","La Divina Commedia di Dante","Text","417","1012","960","https://www.gutenberg.org/ebooks/1012","1265","1321","Dante Alighieri","1","August, 1997","8","August","1997","5","text/plain; charset=utf-8,text/html; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","14.8","10.86","7.84","17715","12.6","52.53","12.8","10.5","3.1","0.04684678959768401","0.5134580498866211","4.8","27.0","0.04","469130","2371","3577","145258.2","97754" +"PR","en","English drama -- 17th century","The Works of Aphra Behn: Volume V","Text","417","29854","961","https://www.gutenberg.org/ebooks/29854","1640","1689","Behn, Aphra","30","August 30, 2009","8","August","2009","8","text/html; charset=utf-8,text/plain; charset=us-ascii,text/plain; charset=utf-8,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","20.6","10.69","6.86","14548","15.0","57.27","17.6","8.0","3.1","0.16255408621323972","0.5324336780705041","4.72","39.0","0.03","841193","4164","4502","237337.2","178043" +"PR","en","Historical drama;Great Britain -- Kings and rulers -- Drama;Tragedies;Great Britain -- History -- Richard III, 1483-1485 -- Drama;Richard III, King of England, 1452-1485 -- Drama","King Richard III","Text","416","1103","962","https://www.gutenberg.org/ebooks/1103","1564","1616","Shakespeare, William","1","November, 1997","11","November","1997","6","text/html,text/plain; charset=us-ascii,text/plain,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","8.6","10.26","6.15","3561","5.2","82.65","7.6000000000000005","5.5","3.1","0.11573370365655666","0.5369469173967193","4.85","14.0","0.07","149924","401","2158","40128.3","30901" +"PR","en","Private investigators -- England -- Fiction;Detective and mystery stories;Holmes, Sherlock (Fictitious character) -- Fiction","The Adventure of the Cardboard Box","Text","416","2344","963","https://www.gutenberg.org/ebooks/2344","1859","1930","Doyle, Arthur Conan","1","October, 2000","10","October","2000","7","text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","8.5","8.52","6.64","1183","6.4","79.6","8.8","29.0","3.1","0.07205273659300107","0.4635101214668521","4.5","17.0","0.06","38871","173","493","11295.0","8642" +"TX","en","Menus;Food conservation;Cooking, American","Foods That Will Win The War And How To Cook Them (1918)","Text","414","15464","964","https://www.gutenberg.org/ebooks/15464","1880","0","Goudiss, C. Houston (Charles Houston)","25","March 25, 2005","3","March","2005","8","application/rdf+xml,text/plain; charset=us-ascii,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","11.5","12.24","5.95","2804","6.4","79.6","8.8","8.0","3.1","0.023762598772308584","0.48425146062277563","5.14","17.0","0.06","155193","733","1736","40629.6","30184" +"PS","en","American literature -- 19th century,Literature -- Collections","The Entire Project Gutenberg Works of Mark Twain","Text","414","3200","965","https://www.gutenberg.org/ebooks/3200","1835","1910","Twain, Mark","20","September 20, 2004","9","September","2004","6","text/html,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/plain","12.6","11.09","6.41","20687","9.5","66.07","10.8","11.5","3.1","0.11005810625093336","0.5014863613262585","4.84","22.0","0.04","942360","6155","8648","274178.7","194566" +"","en","","Woodcraft Boys at Sunset Island","Text","414","51319","966","https://www.gutenberg.org/ebooks/51319","1868","1932","Roy, Lillian Elizabeth","28","February 28, 2016","2","February","2016","7","image/jpeg,text/plain; charset=utf-8,text/html; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.1","10.43","6.19","6486","5.6","81.63","8.0","11.0","3.1","0.13707262848923796","0.4668201101214974","4.88","15.0","0.07","275533","1148","3721","75572.1","56517" +"PR","en","Tahiti (French Polynesia : Island) -- Fiction,Painters -- Fiction,Psychological fiction,England -- Fiction","The Moon and Sixpence","Text","413","222","967","https://www.gutenberg.org/ebooks/222","1874","1965","Maugham, W. Somerset (William Somerset)","2","July 2, 2007","7","July","2007","6","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/rdf+xml,application/epub+zip,text/plain","7.7","8.92","5.81","7037","5.2","82.65","7.6000000000000005","10.5","3.1","0.06579223908885891","0.5227920285685589","4.62","14.0","0.07","346710","1822","5100","99165.6","74970" +"AG","en","Words and phrase lists -- English","Moby Word Lists","Dataset","411","3201","968","https://www.gutenberg.org/ebooks/3201","0","0","Ward, Grady","1","May, 2002","5","May","2002","4","application/zip,text/plain; charset=us-ascii,application/rdf+xml,application/octet-stream","12.7","16.4","8.88","158","6.8","67.76","6.800000000000001","6.5","3.1","0.10797827903091065","0.3605054302422725","5.96","12.0","0.08","3200","30","44","815.4","537" +"PR","en","Mothers and sons -- Drama,Seafaring life -- Drama,Ireland -- Drama,Drowning victims -- Drama","Riders to the Sea","Text","411","994","969","https://www.gutenberg.org/ebooks/994","1871","1909","Synge, J. M. (John Millington)","3","August 3, 2008","8","August","2008","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","7.6","8.58","6.02","519","4.4","90.09","8.0","13.5","3.1","0.04200113119711119","0.4530780072802689","4.56","15.0","0.07","22823","46","333","6136.2","5001" +"VM","en","Ships -- History,Sailing ships -- History,Shipbuilding -- History","Ancient and Modern Ships, Part 1: Wooden Sailing Ships","Text","410","33098","970","https://www.gutenberg.org/ebooks/33098","1848","1926","Holmes, George Charles Vincent, Sir","6","July 6, 2010","7","July","2010","8","text/html; charset=utf-8,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","12.9","12.42","6.4","4844","8.7","68.1","10.0","3.5","3.1","0.11536461646583493","0.39367972957827546","5.12","20.0","0.05","221221","1800","2107","60102.9","43223" +"PQ","en","Italian literature -- Translations into English","The New Life (La Vita Nuova)","Text","409","41085","971","https://www.gutenberg.org/ebooks/41085","1265","1321","Dante Alighieri","17","October 17, 2012","10","October","2012","9","text/html,image/jpeg,text/plain; charset=utf-8,text/plain; charset=us-ascii,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","15.1","10.05","6.84","2755","11.1","67.42","13.600000000000001","14.0","3.1","0.14494142156990378","0.4887640478751197","4.61","29.0","0.03","113760","417","834","32669.1","24691" +"PR","en","Exiles -- Drama,Comedies,Fathers and daughters -- Drama,Pastoral drama","As You Like It","Text","407","1121","972","https://www.gutenberg.org/ebooks/1121","1564","1616","Shakespeare, William","1","December, 1997","12","December","1997","7","text/html,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","8.0","9.27","6.08","2519","5.2","82.65","7.6000000000000005","26.0","3.1","0.21944888266268556","0.5434138038270281","4.68","14.0","0.07","106607","181","1552","29278.8","22802" +"PZ","en","Short stories,Sagas -- Adaptations,Vikings -- Folklore","Viking Tales","Text","406","24811","973","https://www.gutenberg.org/ebooks/24811","1875","1921","Hall, Jennie","12","March 12, 2008","3","March","2008","7","text/plain; charset=utf-8,text/html; charset=iso-8859-1,text/plain; charset=us-ascii,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","6.2","8.28","5.42","2403","3.3","93.14","6.800000000000001","4.5","3.1","0.163865863490232","0.4628161918281872","4.56","12.0","0.08","145746","278","2612","39147.3","31975" +"PA","la","Epic poetry, Latin;Legends -- Rome -- Poetry;Aeneas (Legendary character) -- Poetry","Aeneidos","Text","404","227","974","https://www.gutenberg.org/ebooks/227","-70","-19","Virgil","3","April 3, 2008","4","April","2008","7","text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","18.1","19.26","9.92","21572","15.4","18.35","9.600000000000001","13.5","3.1","0.1413441932624112","0.49921985815602854","6.3","19.0","0.05","401511","2219","3230","129063.6","63748" +"","fr","","L'autre monde ou Histoire comique des Etats et Empires de la Lune","Text","402","51338","975","https://www.gutenberg.org/ebooks/51338","0","0","Bergerac, Savinien de Cyrano de","1","March 1, 2016","3","March","2016","7","image/jpeg,text/plain; charset=utf-8,text/html; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","21.7","12.6","8.08","7415","15.8","49.83","17.2","5.5","3.1","0.20624420397688067","0.6315734989648042","5.05","38.0","0.03","231466","941","1185","63082.8","45847" +"BT","en","Theodicy,Theism,Free will and determinism","Theodicy: Essays on the Goodness of God, the Freedom of Man and the Origin of Evil","Text","401","17147","976","https://www.gutenberg.org/ebooks/17147","1646","1716","Leibniz, Gottfried Wilhelm, Freiherr von","24","November 24, 2005","11","November","2005","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","15.8","11.32","6.24","14574","13.0","51.52","13.200000000000001","5.5","8.8","0.12561135759106687","0.5470847212330299","4.88","28.0","0.04","922130","9056","6652","275711.4","189070" +"M","en","Catholic Church -- Hymns;Hymns, Latin;Hymns, English;Service books (Music) -- Catholic Church","The St. Gregory Hymnal and Catholic Choir Book","Text","401","23673","977","https://www.gutenberg.org/ebooks/23673","0","0","Unknown","2","December 2, 2007","12","December","2007","10","text/html,text/plain; charset=us-ascii,application/pdf,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/msword","11.1","14.08","6.51","6673","5.6","76.22","6.800000000000001","7.5","3.1","0.21967023721637355","0.5324482089261502","5.56","12.0","0.08","256754","1657","3618","65913.3","46184" +"TT","en","Crocheting,Needlework -- Patterns,Knitting,Lace and lace making","Beeton's Book of Needlework","Text","400","15147","978","https://www.gutenberg.org/ebooks/15147","1836","1865","Beeton, Mrs. (Isabella Mary)","22","February 22, 2005","2","February","2005","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,text/plain","10.4","11.66","1.46","3900","4.8","89.08","8.4","6.0","3.1","0.014259187555593439","0.25502761981748023","5.04","16.0","0.06","462540","2337","5678","114403.5","91863" +"PR","en","Short stories, English;Horror tales, English;Ghost stories, English","Ghost Stories of an Antiquary","Text","400","8486","979","https://www.gutenberg.org/ebooks/8486","1862","1936","James, M. R. (Montague Rhodes)","1","July, 2005","7","July","2005","8","text/html,text/plain; charset=us-ascii,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","11.3","9.86","6.65","5686","7.9","75.54","10.4","27.5","3.1","0.09225629720147005","0.4769119592215237","4.68","21.0","0.05","212641","1142","2134","61002.0","45444" +"PR","en","Grandfathers -- Fiction,Avarice -- Fiction,United States -- Description and travel -- Fiction,Bildungsromans,Satire,Black humor,England -- Fiction,Adventure stories,British -- United States -- Fiction,Young men -- Fiction","Martin Chuzzlewit","Text","400","968","980","https://www.gutenberg.org/ebooks/968","1812","1870","Dickens, Charles","27","April 27, 2006","4","April","2006","8","application/x-mobipocket-ebook,image/jpeg,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain","10.6","10.44","5.71","24147","7.2","77.57","9.600000000000001","14.5","3.1","0.11591116612175509","0.5067948750380669","4.78","19.0","0.05","1610845","8473","17662","450309.6","336735" +"","en","","Boy of My Heart","Text","398","51437","981","https://www.gutenberg.org/ebooks/51437","0","0","Leighton, Marie Connor","13","March 13, 2016","3","March","2016","9","image/jpeg,text/html; charset=iso-8859-1,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","8.6","8.47","5.9","4243","6.8","78.59","9.200000000000001","17.0","3.1","0.09544185460264636","0.48636499842264946","4.44","18.0","0.05","217034","750","2684","61990.2","48894" +"","en","","The Scarecrow of Oz","Text","397","51263","982","https://www.gutenberg.org/ebooks/51263","1856","1919","Baum, L. Frank (Lyman Frank)","21","February 21, 2016","2","February","2016","8","image/jpeg,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/html; charset=iso-8859-1,application/x-mobipocket-ebook","9.7","9.68","5.9","4021","6.8","78.59","9.200000000000001","11.0","3.1","0.1257593035616934","0.5274821837468902","4.7","18.0","0.06","217171","634","2554","59718.6","46170" +"","en","","Henry D. Thoreau","Text","394","51426","983","https://www.gutenberg.org/ebooks/51426","0","0","Sanborn, F. B.","12","March 12, 2016","3","March","2016","8","image/jpeg,text/html; charset=iso-8859-1,text/plain,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","13.1","11.67","6.79","8974","9.5","66.07","10.8","6.0","3.1","0.14800733851193557","0.45998626853946745","4.94","22.0","0.04","338831","2030","3058","94006.8","68651" +"PR","en","Prisons -- Poetry,Imprisonment -- Poetry,Prisoners -- Poetry","The Ballad of Reading Gaol","Text","393","301","984","https://www.gutenberg.org/ebooks/301","1854","1900","Wilde, Oscar","1","July, 1995","7","July","1995","7","text/plain,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","16.3","9.47","6.08","445","11.1","72.84","14.8","7.5","3.1","-0.025723737047266392","0.5154213107154278","4.51","32.0","0.03","37001","25","249","9631.8","8202" +"","en","","The Analysis of Beauty: Written with a view of fixing the fluctuating ideas of taste","Text","390","51459","985","https://www.gutenberg.org/ebooks/51459","1697","1764","Hogarth, William","15","March 15, 2016","3","March","2016","8","image/jpeg,text/html; charset=iso-8859-1,text/plain,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,application/x-mobipocket-ebook","20.9","11.44","7.25","4875","16.1","48.81","17.6","7.0","8.8","0.1492819893375524","0.4858316823814792","4.85","39.0","0.03","222095","1733","1173","64856.7","45783" +"PR","en","Belgium -- Social life and customs -- 19th century -- Fiction,British -- Belgium -- Fiction,Triangles (Interpersonal relations) -- Fiction,Women teachers -- Fiction,Brussels (Belgium) -- Fiction,Love stories","The Professor","Text","388","1028","986","https://www.gutenberg.org/ebooks/1028","1816","1855","Bronte, Charlotte","6","August 6, 2008","8","August","2008","6","application/x-mobipocket-ebook,text/plain; charset=us-ascii,text/html; charset=us-ascii,application/rdf+xml,application/epub+zip,text/plain","14.6","11.32","7.0","11580","11.1","62.01","12.4","13.0","3.1","0.09214197519860112","0.4826468481803372","4.88","26.0","0.04","429454","2959","3363","124044.3","88037" +"GR","en","Folklore -- Russia","Russian Fairy Tales: A Choice Collection of Muscovite Folk-lore","Text","379","22373","987","https://www.gutenberg.org/ebooks/22373","0","0","Unknown","22","August 22, 2007","8","August","2007","7","text/plain; charset=utf-8,text/html; charset=iso-8859-1,text/plain; charset=us-ascii,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,application/x-mobipocket-ebook","9.2","10.15","5.83","11573","6.0","80.62","8.4","5.0","3.1","0.0834380898141997","0.4378349221780228","4.78","16.0","0.06","625217","2612","8021","171237.6","130817" +"ML","en","Composers -- Germany -- Biography;Beethoven, Ludwig van, 1770-1827","Beethoven, the Man and the Artist, as Revealed in His Own Words","Text","377","3528","988","https://www.gutenberg.org/ebooks/3528","1770","1827","Beethoven, Ludwig van","1","November, 2002","11","November","2002","7","text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","11.7","12.06","7.09","3853","7.9","70.13","9.200000000000001","14.0","3.1","0.14833323686941244","0.5351653269095977","5.11","18.0","0.06","121237","923","1308","33524.1","23733" +"PS","en","Human-alien encounters -- Fiction,Science fiction,Space warfare -- Fiction","Triplanetary","Text","375","32706","989","https://www.gutenberg.org/ebooks/32706","1890","1965","Smith, E. E. (Edward Elmer)","6","June 6, 2010","6","June","2010","8","text/plain; charset=us-ascii,application/x-mobipocket-ebook,text/html; charset=iso-8859-1,application/zip,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","10.9","12.24","6.45","11612","8.4","63.7","8.4","11.0","3.1","0.06875362090704779","0.49569430270928405","5.14","16.0","0.06","467426","3768","5587","133090.2","90994" +"PS","en","Bible. New Testament -- History of Biblical events -- Fiction;Historical fiction;Tiberius, Emperor of Rome 42 B.C.-37 A.D. -- Fiction;Christian fiction;Rome -- History -- Tiberius, 14-37 -- Fiction;Jesus Christ -- Fiction","Ben-Hur; a tale of the Christ","Text","364","2145","990","https://www.gutenberg.org/ebooks/2145","1827","1905","Wallace, Lew","1","April, 2000","4","April","2000","7","text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=us-ascii,text/plain","10.1","10.21","5.98","18152","7.9","70.13","9.200000000000001","17.5","3.1","0.136190633917424","0.48124467503505597","4.79","18.0","0.06","945799","4479","10955","266769.9","197376" +"","en","","Claudian, volume 1 (of 2): With an English translation by Maurice Platnauer","Text","364","51443","991","https://www.gutenberg.org/ebooks/51443","0","0","Claudianus, Claudius","14","March 14, 2016","3","March","2016","7","image/jpeg,text/plain; charset=utf-8,text/html; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","14.3","14.56","8.54","23626","10.7","52.19","9.600000000000001","14.0","3.1","0.08935618990684395","0.4974106375262822","5.49","19.0","0.05","516663","2445","4786","149489.1","94195" +"","en","","The Love of Monsieur","Text","287","51468","992","https://www.gutenberg.org/ebooks/51468","1870","1942","Gibbs, George","16","March 16, 2016","3","March","2016","7","image/jpeg,text/plain; charset=utf-8,text/html; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","8.7","9.97","6.26","6277","5.2","82.65","7.6000000000000005","11.0","3.1","0.08188873121414494","0.4871865148232636","4.8","14.0","0.07","247163","958","3433","69030.0","51493" +"","en","","Self-Control Its Kingship and Majesty","Text","201","51469","993","https://www.gutenberg.org/ebooks/51469","1864","1928","Jordan, William George","16","March 16, 2016","3","March","2016","6","image/jpeg,text/html; charset=utf-8,text/plain; charset=utf-8,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","12.0","10.97","7.08","3628","9.1","67.08","10.4","5.5","3.1","0.1472481304361231","0.48939570909662866","4.87","21.0","0.05","116264","994","1136","34361.1","23887" +"","en","","Beach Scene","Text","104","51494","994","https://www.gutenberg.org/ebooks/51494","0","0","King, Marshall","18","March 18, 2016","3","March","2016","7","text/plain,image/jpeg,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","7.0","9.56","6.49","767","4.0","85.69","6.4","5.5","3.1","0.08243354728139407","0.4777909759617081","4.78","11.0","0.08","25103","86","440","6932.7","5250" +"","en","","Dumbwaiter","Text","97","51478","995","https://www.gutenberg.org/ebooks/51478","0","0","Stamers, James","16","March 16, 2016","3","March","2016","8","image/jpeg,text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","8.6","11.12","7.25","800","5.6","76.22","6.800000000000001","5.5","3.1","0.061031723300541414","0.46288461689687843","5.05","12.0","0.08","21155","163","333","6002.1","4190" +"","en","","Kreativity For Kats","Text","92","51493","996","https://www.gutenberg.org/ebooks/51493","1910","1992","Leiber, Fritz","18","March 18, 2016","3","March","2016","8","image/jpeg,text/html; charset=us-ascii,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain","11.4","12.24","7.9","709","8.7","62.68","8.8","8.0","3.1","0.08767238281661366","0.47741735828274284","5.14","17.0","0.06","16853","122","190","4806.9","3276" +"","en","","East In The Morning","Text","88","51475","997","https://www.gutenberg.org/ebooks/51475","1932","0","Fisher, David E.","16","March 16, 2016","3","March","2016","8","application/x-mobipocket-ebook,image/jpeg,text/html; charset=us-ascii,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","8.7","10.66","7.1","778","6.0","75.2","7.2","7.0","3.1","0.14033625531657024","0.4598044657296628","4.92","13.0","0.07","21418","171","311","6137.1","4352" +"","en","","The Donkey, the Elephant, and the Goat: At a Public Meeting","Text","72","51473","998","https://www.gutenberg.org/ebooks/51473","1888","0","Preston, Jack","16","March 16, 2016","3","March","2016","8","image/jpeg,text/html,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","12.7","13.0","7.7","470","8.3","69.11","9.600000000000001","7.0","3.1","0.10956001742553079","0.4845602066584209","5.22","19.0","0.05","12424","35","125","3222.0","2381" +"","en","","A Garden Diary: September 1899—September 1900","Text","66","51477","999","https://www.gutenberg.org/ebooks/51477","1845","1913","Lawless, Emily","16","March 16, 2016","3","March","2016","6","image/jpeg,text/html; charset=utf-8,text/plain; charset=utf-8,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","14.0","11.49","7.29","7467","10.3","64.04","11.600000000000001","13.0","8.8","0.09943987545880542","0.4974991164000981","4.91","24.0","0.04","234934","2172","1938","69373.8","47873" +"","en","","Flying Machines Today","Text","3","51481","1000","https://www.gutenberg.org/ebooks/51481","0","0","Ennis, William Duane","17","March 17, 2016","3","March","2016","7","image/jpeg,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,text/plain; charset=iso-8859-1,application/epub+zip,application/rdf+xml,text/plain","14.2","13.46","7.01","4902","10.3","58.62","10.4","16.0","8.8","0.08893745652478177","0.43748380160432215","5.3","21.0","0.05","175917","2178","1558","51192.0","33189" +"","en","","Perfect Answer","Text","0","51482","1001","https://www.gutenberg.org/ebooks/51482","0","0","Stecher, L.J.","17","March 17, 2016","3","March","2016","8","image/jpeg,text/html; charset=us-ascii,text/plain; charset=us-ascii,text/plain,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","7.9","10.48","7.0","691","5.2","77.23","6.4","5.0","3.1","0.11088290351247666","0.5046814508323656","4.99","11.0","0.09","19328","127","332","5436.9","3871" +"","en","","The Reluctant Heroes","Text","0","51483","1002","https://www.gutenberg.org/ebooks/51483","1926","2014","Robinson, Frank M.","17","March 17, 2016","3","March","2016","7","text/plain,image/jpeg,text/plain; charset=us-ascii,application/x-mobipocket-ebook,application/rdf+xml,application/epub+zip,text/html; charset=us-ascii","6.2","8.68","6.09","835","4.0","85.69","6.4","5.0","3.1","0.07620298176808123","0.45175666507492956","4.68","11.0","0.09","32354","112","618","8824.5","6913" +"","en","","Film Truth; September, 1920","Text","0","51484","1003","https://www.gutenberg.org/ebooks/51484","0","0","Anonymous","17","March 17, 2016","3","March","2016","6","image/jpeg,text/html; charset=utf-8,text/plain; charset=utf-8,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","10.8","11.54","7.61","1813","7.6","71.14","8.8","11.5","3.1","0.14387878605681634","0.4857817824011009","5.02","17.0","0.06","45970","312","536","13080.6","9153" +"","en","","Othmar","Text","0","51487","1004","https://www.gutenberg.org/ebooks/51487","1839","1908","Ouida","17","March 17, 2016","3","March","2016","8","image/jpeg,text/html; charset=iso-8859-1,application/x-mobipocket-ebook,application/zip,application/rdf+xml,application/epub+zip,text/plain; charset=iso-8859-1,text/plain","11.2","9.75","5.95","15425","7.9","75.54","10.4","1.0","3.1","0.09947837225741032","0.5482887606255221","4.66","21.0","0.05","890918","4808","8921","258091.2","191182" +"","en","","Church History (Volumes 1-3)","Text","0","51491","1005","https://www.gutenberg.org/ebooks/51491","1809","1890","Kurtz, J. H. (Johann Heinrich)","17","March 17, 2016","3","March","2016","7","image/jpeg,text/html; charset=utf-8,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","12.3","13.22","5.56","49821","8.7","62.68","8.8","2.0","8.8","0.11224187416199208","0.4400144316605153","5.31","17.0","0.06","3883244","46730","41950","1083170.7","730715" +"","en","","The Uncensored Letters of a Canteen Girl","Text","0","51495","1006","https://www.gutenberg.org/ebooks/51495","0","0","Morse, Katharine Duncan","19","March 19, 2016","3","March","2016","7","image/jpeg,text/html; charset=utf-8,text/plain; charset=utf-8,application/zip,application/rdf+xml,application/epub+zip,application/x-mobipocket-ebook","9.4","9.86","6.24","10665","7.6","71.14","8.8","4.5","3.1","0.059622581728734886","0.4354433298058611","4.73","17.0","0.06","451687","2595","5580","130093.2","95496" diff --git a/samples/Basic_Templates/templates/cars.txt b/samples/Basic_Templates/templates/cars.txt new file mode 100644 index 0000000000..ed5746fc87 --- /dev/null +++ b/samples/Basic_Templates/templates/cars.txt @@ -0,0 +1,27 @@ +# +# Sample template to display records from 'cars.csv' +# https://corgis-edu.github.io/corgis/csv/cars/ +# +# File truncated to first 1000 records +# + +{SECTION} +Listing cars for "Make = {make_filter}" + +{!pad:"#":5} {!pad:"Make":12} {!pad:"Model":40} {!pad:"Engine Type":30} +{!repeat:"-":5} {!repeat:"-":12} {!repeat:"-":40} {!repeat:"-":30} +{/SECTION} + +# Data section follows + +{SECTION}{!ifeq:Identification.Make:make_filter}{!pad:{!add:$record:1}:5} {!pad:Identification.Make:12} {!pad:Identification.Model Year:40} {!pad:Engine Information.Engine Type:30} +{!endif}{/SECTION} + +{SECTION}{!repeat:"-":10} +{!count:1} records searched + +LISTING COMPLETE + +{/SECTION} + +# We're all done. diff --git a/samples/Basic_Templates/templates/classics.json b/samples/Basic_Templates/templates/classics.json new file mode 100644 index 0000000000..edf1cf3036 --- /dev/null +++ b/samples/Basic_Templates/templates/classics.json @@ -0,0 +1,26 @@ + +Sample template to display records from 'classics.csv' +https://corgis-edu.github.io/corgis/csv/classics/ + +{SECTION} +[ + { + "comment": "Listing books published in {year_filter}" + },{/SECTION} + +{SECTION} + { + "title": "{bibliography.title}", + "author": "{bibliography.author.name}", + "published": {bibliography.publication.year}, + "url": "{metadata.url}" + },{/SECTION} + +{SECTION} + { + "comment": "{!count:1} Records listed" + } +] +{/SECTION} + +We're all done. diff --git a/samples/Basic_Templates/templates/classics.xml b/samples/Basic_Templates/templates/classics.xml new file mode 100644 index 0000000000..45aae9f338 --- /dev/null +++ b/samples/Basic_Templates/templates/classics.xml @@ -0,0 +1,29 @@ + +Sample template to display records from 'classics.csv' +https://corgis-edu.github.io/corgis/csv/classics/ + +** HEADER ** +{SECTION} + + + + +{/SECTION} + + +** CONTENT ** +{SECTION} + + {bibliography.title} + {bibliography.author.name} + {bibliography.publication.year} + {metadata.url} + {/SECTION} + + +** FOOTER ** +{SECTION} + + + +{/SECTION} diff --git a/samples/Basic_Utility/.cproject b/samples/Basic_Utility/.cproject deleted file mode 100644 index f907477188..0000000000 --- a/samples/Basic_Utility/.cproject +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Basic_Utility/.project b/samples/Basic_Utility/.project deleted file mode 100644 index 7e7f075df0..0000000000 --- a/samples/Basic_Utility/.project +++ /dev/null @@ -1,29 +0,0 @@ - - - Basic_Utility - - - SmingFramework - Sming - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Basic_Utility/app/utility.cpp b/samples/Basic_Utility/app/utility.cpp index f0247945e7..4a60753e4c 100644 --- a/samples/Basic_Utility/app/utility.cpp +++ b/samples/Basic_Utility/app/utility.cpp @@ -1,9 +1,5 @@ #include -#ifdef ARCH_HOST #include -#endif - -#ifdef ARCH_HOST namespace { @@ -38,8 +34,6 @@ void testWebConstants() } // namespace -#endif - void init() { // Hook up debug output @@ -52,7 +46,6 @@ void init() */ m_printf("\n** Basic Host utility sample **\n"); -#ifdef ARCH_HOST auto parameters = commandLine.getParameters(); if(parameters.count() == 0) { m_printf("No command line parameters\n" @@ -83,14 +76,4 @@ void init() m_putc('\n'); System.restart(); - -#else - - Serial.println(); - Serial.println(_F("** THIS IS A HOST-ONLY APPLICATION **")); - Serial.println(); - Serial.println(_F("Please build with SMING_ARCH=Host")); - Serial.println(); - -#endif } diff --git a/samples/Basic_Utility/component.mk b/samples/Basic_Utility/component.mk index e531cfcec6..c830663c46 100644 --- a/samples/Basic_Utility/component.mk +++ b/samples/Basic_Utility/component.mk @@ -1,3 +1,5 @@ +COMPONENT_SOC := host +DISABLE_NETWORK := 1 # Call the generated executable something different (by default, it's just `app`) APP_NAME := utility @@ -6,5 +8,5 @@ APP_NAME := utility ENABLE_MALLOC_COUNT := 0 # -DISABLE_WIFI := 1 +DISABLE_NETWORK := 1 HOST_NETWORK_OPTIONS := --nonet diff --git a/samples/Basic_WebSkeletonApp/.cproject b/samples/Basic_WebSkeletonApp/.cproject deleted file mode 100644 index b317b1cc50..0000000000 --- a/samples/Basic_WebSkeletonApp/.cproject +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - - all - true - true - true - - - make - - rebuild - true - true - true - - - make - - flash - true - true - true - - - - diff --git a/samples/Basic_WebSkeletonApp/.project b/samples/Basic_WebSkeletonApp/.project deleted file mode 100644 index bae000f0ff..0000000000 --- a/samples/Basic_WebSkeletonApp/.project +++ /dev/null @@ -1,27 +0,0 @@ - - - Basic_WebSkeletonApp - - - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Basic_WebSkeletonApp/app/DelayStream.cpp b/samples/Basic_WebSkeletonApp/app/DelayStream.cpp index e75105eca4..eb69a6b81c 100644 --- a/samples/Basic_WebSkeletonApp/app/DelayStream.cpp +++ b/samples/Basic_WebSkeletonApp/app/DelayStream.cpp @@ -11,7 +11,7 @@ void DelayStream::sendFile() fn = filename; } - if(FileStream::open(fn, eFO_ReadOnly)) { + if(FileStream::open(fn, File::ReadOnly)) { debug_i("opened '%s', %u bytes", fn.c_str(), FileStream::available()); response->setContentType(getMimeType()); } else { diff --git a/samples/Basic_WebSkeletonApp/app/DelayStream.h b/samples/Basic_WebSkeletonApp/app/DelayStream.h index cc67cfdb58..0211bc3d3d 100644 --- a/samples/Basic_WebSkeletonApp/app/DelayStream.h +++ b/samples/Basic_WebSkeletonApp/app/DelayStream.h @@ -10,7 +10,7 @@ * See sendFile() for further details. * * A more realistic example might be if we need to communicate with a slow Serial device, which - * might take several seconds. This can be handled asychronously without affecting other system + * might take several seconds. This can be handled asynchronously without affecting other system * operations. */ class DelayStream : public FileStream diff --git a/samples/Basic_WebSkeletonApp/component.mk b/samples/Basic_WebSkeletonApp/component.mk index de15dbd41b..248c71219b 100644 --- a/samples/Basic_WebSkeletonApp/component.mk +++ b/samples/Basic_WebSkeletonApp/component.mk @@ -1,3 +1,4 @@ +COMPONENT_SOC := esp* ARDUINO_LIBRARIES := ArduinoJson6 HWCONFIG := spiffs diff --git a/samples/Basic_WebSkeletonApp_LTS/.cproject b/samples/Basic_WebSkeletonApp_LTS/.cproject deleted file mode 100644 index b317b1cc50..0000000000 --- a/samples/Basic_WebSkeletonApp_LTS/.cproject +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - - all - true - true - true - - - make - - rebuild - true - true - true - - - make - - flash - true - true - true - - - - diff --git a/samples/Basic_WebSkeletonApp_LTS/.project b/samples/Basic_WebSkeletonApp_LTS/.project deleted file mode 100644 index 219a457e2c..0000000000 --- a/samples/Basic_WebSkeletonApp_LTS/.project +++ /dev/null @@ -1,27 +0,0 @@ - - - Basic_WebSkeletonApp_LTS - - - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Basic_WebSkeletonApp_LTS/README.rst b/samples/Basic_WebSkeletonApp_LTS/README.rst index 83fdd7c927..baf670fa08 100644 --- a/samples/Basic_WebSkeletonApp_LTS/README.rst +++ b/samples/Basic_WebSkeletonApp_LTS/README.rst @@ -10,9 +10,9 @@ Sming uses ArduinoJson version 6 by default, so this sample demonstrates how to This is how it was done: 1. When including SmingCore.h, just use `#include `. -2. Remove the file `include/user_config.h`. Sming provides this by default, but if you have made changes - for your project then remove everything except your changes, but be sure to add `#include_next ` at the top. -3. Remove any `#include ` statements from your files. This file is automatically included by Sming. +2. Remove the file `include/user_config.h`: Sming does not require it. If you have made changes + for your project then move the changes into your project's ``component.mk`` file. +3. Remove any `#include ` statements from your files. 4. Rename `Makefile-user.mk` file to `component.mk`. 5. Replace the file `Makefile` with the one from the `Basic_Blink` sample project. If you've ignored the instructions and modified the file (!) then you'll need to move those changes into your new `component.mk` file instead. diff --git a/samples/Basic_WebSkeletonApp_LTS/app/webserver.cpp b/samples/Basic_WebSkeletonApp_LTS/app/webserver.cpp index 480ab1e41c..b6068fbc09 100644 --- a/samples/Basic_WebSkeletonApp_LTS/app/webserver.cpp +++ b/samples/Basic_WebSkeletonApp_LTS/app/webserver.cpp @@ -20,7 +20,7 @@ void onConfiguration(HttpRequest& request, HttpResponse& response) } else { StaticJsonBuffer jsonBuffer; JsonObject& root = jsonBuffer.parseObject(*request.getBodyStream()); - root.prettyPrintTo(Serial); //Uncomment it for debuging + root.prettyPrintTo(Serial); //Uncomment it for debugging if(root["StaSSID"].success()) // Settings { diff --git a/samples/Basic_WebSkeletonApp_LTS/component.mk b/samples/Basic_WebSkeletonApp_LTS/component.mk index 8621049159..f3b449bbbb 100644 --- a/samples/Basic_WebSkeletonApp_LTS/component.mk +++ b/samples/Basic_WebSkeletonApp_LTS/component.mk @@ -1,3 +1,5 @@ +COMPONENT_SOC := esp* host + ## Local build configuration ## Parameters configured here will override default and ENV values. ## Uncomment and change examples: diff --git a/samples/Basic_WiFi/.cproject b/samples/Basic_WiFi/.cproject deleted file mode 100644 index e800e45284..0000000000 --- a/samples/Basic_WiFi/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Basic_WiFi/.project b/samples/Basic_WiFi/.project deleted file mode 100644 index dc2995c4e2..0000000000 --- a/samples/Basic_WiFi/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Basic_WiFi - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Basic_WiFi/component.mk b/samples/Basic_WiFi/component.mk new file mode 100644 index 0000000000..996e1b20f1 --- /dev/null +++ b/samples/Basic_WiFi/component.mk @@ -0,0 +1 @@ +COMPONENT_SOC := esp* host diff --git a/samples/CanBus/.cproject b/samples/CanBus/.cproject deleted file mode 100644 index 67c056d24e..0000000000 --- a/samples/CanBus/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/CanBus/.project b/samples/CanBus/.project deleted file mode 100644 index 4d1952da65..0000000000 --- a/samples/CanBus/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - CanBus - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/CanBus/component.mk b/samples/CanBus/component.mk index 668373c3fc..469fa2ae38 100644 --- a/samples/CanBus/component.mk +++ b/samples/CanBus/component.mk @@ -1 +1,2 @@ +COMPONENT_SOC := esp* ARDUINO_LIBRARIES := MCP_CAN_lib diff --git a/samples/CommandProcessing_Debug/.cproject b/samples/CommandProcessing_Debug/.cproject deleted file mode 100644 index b3cd7e9a01..0000000000 --- a/samples/CommandProcessing_Debug/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/CommandProcessing_Debug/.project b/samples/CommandProcessing_Debug/.project deleted file mode 100644 index f550083103..0000000000 --- a/samples/CommandProcessing_Debug/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - CommandProcessing_Debug - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/CommandProcessing_Debug/app/application.cpp b/samples/CommandProcessing_Debug/app/application.cpp index a06cf9d035..bccb385b05 100644 --- a/samples/CommandProcessing_Debug/app/application.cpp +++ b/samples/CommandProcessing_Debug/app/application.cpp @@ -54,7 +54,7 @@ void wsMessageReceived(WebsocketConnection& socket, const String& message) void wsBinaryReceived(WebsocketConnection& socket, uint8_t* data, size_t size) { - Serial.printf("Websocket binary data recieved, size: %d\r\n", size); + Serial.printf("Websocket binary data received, size: %d\r\n", size); } void wsDisconnected(WebsocketConnection& socket) diff --git a/samples/CommandProcessing_Debug/component.mk b/samples/CommandProcessing_Debug/component.mk index 298d44e80b..8090a5763c 100644 --- a/samples/CommandProcessing_Debug/component.mk +++ b/samples/CommandProcessing_Debug/component.mk @@ -1 +1,2 @@ +COMPONENT_SOC := esp* host HWCONFIG := spiffs diff --git a/samples/Compass_HMC5883L/.cproject b/samples/Compass_HMC5883L/.cproject deleted file mode 100644 index 5829bbd8cd..0000000000 --- a/samples/Compass_HMC5883L/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Compass_HMC5883L/.project b/samples/Compass_HMC5883L/.project deleted file mode 100644 index f60b888f9d..0000000000 --- a/samples/Compass_HMC5883L/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Compass_HMC5883L - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Compass_HMC5883L/component.mk b/samples/Compass_HMC5883L/component.mk index bfebb2a7dc..1d6386363b 100644 --- a/samples/Compass_HMC5883L/component.mk +++ b/samples/Compass_HMC5883L/component.mk @@ -1 +1,2 @@ ARDUINO_LIBRARIES := HMC5883L +DISABLE_NETWORK := 1 diff --git a/samples/DFPlayerMini/.cproject b/samples/DFPlayerMini/.cproject deleted file mode 100644 index 7ce192f4a7..0000000000 --- a/samples/DFPlayerMini/.cproject +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/DFPlayerMini/.project b/samples/DFPlayerMini/.project deleted file mode 100644 index e11aea2617..0000000000 --- a/samples/DFPlayerMini/.project +++ /dev/null @@ -1,27 +0,0 @@ - - - DFPlayerMini - - - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/DFPlayerMini/app/application.cpp b/samples/DFPlayerMini/app/application.cpp index 819dbb7421..4dcdea9666 100644 --- a/samples/DFPlayerMini/app/application.cpp +++ b/samples/DFPlayerMini/app/application.cpp @@ -1,4 +1,3 @@ -#include #include #include diff --git a/samples/DFPlayerMini/component.mk b/samples/DFPlayerMini/component.mk index fe1938596e..6f71f9bbb9 100644 --- a/samples/DFPlayerMini/component.mk +++ b/samples/DFPlayerMini/component.mk @@ -1 +1,2 @@ ARDUINO_LIBRARIES := DFRobotDFPlayerMini +DISABLE_NETWORK := 1 diff --git a/samples/DS3232RTC_NTP_Setter/.cproject b/samples/DS3232RTC_NTP_Setter/.cproject deleted file mode 100644 index 856edbd329..0000000000 --- a/samples/DS3232RTC_NTP_Setter/.cproject +++ /dev/null @@ -1,155 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/DS3232RTC_NTP_Setter/.project b/samples/DS3232RTC_NTP_Setter/.project deleted file mode 100644 index 144566900a..0000000000 --- a/samples/DS3232RTC_NTP_Setter/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - DS3232RTC_NTP_Setter - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/DS3232RTC_NTP_Setter/component.mk b/samples/DS3232RTC_NTP_Setter/component.mk index 9f593e41f9..e9017a1d47 100644 --- a/samples/DS3232RTC_NTP_Setter/component.mk +++ b/samples/DS3232RTC_NTP_Setter/component.mk @@ -1 +1,2 @@ +COMPONENT_SOC := esp* host ARDUINO_LIBRARIES := DS3232RTC diff --git a/samples/Display_TM1637/.cproject b/samples/Display_TM1637/.cproject deleted file mode 100644 index bc7ccf404a..0000000000 --- a/samples/Display_TM1637/.cproject +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Display_TM1637/.project b/samples/Display_TM1637/.project deleted file mode 100644 index 6ade25eec3..0000000000 --- a/samples/Display_TM1637/.project +++ /dev/null @@ -1,27 +0,0 @@ - - - Display_TM1637 - - - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Display_TM1637/app/application.cpp b/samples/Display_TM1637/app/application.cpp index d15d198263..011a5fd917 100644 --- a/samples/Display_TM1637/app/application.cpp +++ b/samples/Display_TM1637/app/application.cpp @@ -1,4 +1,3 @@ -#include #include #include diff --git a/samples/Display_TM1637/component.mk b/samples/Display_TM1637/component.mk index 76b8ba3655..1087202388 100644 --- a/samples/Display_TM1637/component.mk +++ b/samples/Display_TM1637/component.mk @@ -1 +1,2 @@ ARDUINO_LIBRARIES := TM1637 +DISABLE_NETWORK := 1 diff --git a/samples/Distance_Vl53l0x/.cproject b/samples/Distance_Vl53l0x/.cproject deleted file mode 100644 index e1450b6031..0000000000 --- a/samples/Distance_Vl53l0x/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Distance_Vl53l0x/.project b/samples/Distance_Vl53l0x/.project deleted file mode 100644 index e288750ac8..0000000000 --- a/samples/Distance_Vl53l0x/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Distance_Vl53l10 - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Distance_Vl53l0x/app/application.cpp b/samples/Distance_Vl53l0x/app/application.cpp index 8eed4ff4aa..dcf5e72dcf 100644 --- a/samples/Distance_Vl53l0x/app/application.cpp +++ b/samples/Distance_Vl53l0x/app/application.cpp @@ -31,16 +31,9 @@ void init() Serial.begin(SERIAL_BAUD_RATE); // 115200 by default Serial.systemDebugOutput(true); // Enable debug output to serial - // WIFI not needed for demo. So disabling WIFI. - WifiStation.enable(false); - WifiAccessPoint.enable(false); - - // Create components. Wire.begin(SDA, SCL); - lox.setLongRangeMode(true); - - if(!lox.begin()) { + if(!lox.begin(VL53L0X_I2C_ADDR, false, &Wire, Adafruit_VL53L0X::VL53L0X_SENSE_LONG_RANGE)) { Serial.println(F("Failed to boot VL53L0X")); while(1) { } diff --git a/samples/Distance_Vl53l0x/component.mk b/samples/Distance_Vl53l0x/component.mk index a944fc3b10..f03f6b3041 100644 --- a/samples/Distance_Vl53l0x/component.mk +++ b/samples/Distance_Vl53l0x/component.mk @@ -1 +1,2 @@ ARDUINO_LIBRARIES := Adafruit_VL53L0X +DISABLE_NETWORK := 1 diff --git a/samples/DnsCaptivePortal/.cproject b/samples/DnsCaptivePortal/.cproject deleted file mode 100644 index 67c056d24e..0000000000 --- a/samples/DnsCaptivePortal/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/DnsCaptivePortal/.project b/samples/DnsCaptivePortal/.project deleted file mode 100644 index 605ea2c903..0000000000 --- a/samples/DnsCaptivePortal/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - DnsCaptivePortal - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/DnsCaptivePortal/component.mk b/samples/DnsCaptivePortal/component.mk new file mode 100644 index 0000000000..996e1b20f1 --- /dev/null +++ b/samples/DnsCaptivePortal/component.mk @@ -0,0 +1 @@ +COMPONENT_SOC := esp* host diff --git a/samples/Echo_Ssl/.cproject b/samples/Echo_Ssl/.cproject deleted file mode 100644 index c6777891d2..0000000000 --- a/samples/Echo_Ssl/.cproject +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Echo_Ssl/.project b/samples/Echo_Ssl/.project deleted file mode 100644 index 2a871e7aa7..0000000000 --- a/samples/Echo_Ssl/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Echo_Ssl - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Echo_Ssl/component.mk b/samples/Echo_Ssl/component.mk index ae82bad52a..b304dbdbe3 100644 --- a/samples/Echo_Ssl/component.mk +++ b/samples/Echo_Ssl/component.mk @@ -1 +1,2 @@ +COMPONENT_SOC := esp* host ENABLE_SSL = 1 diff --git a/samples/FtpServer_Files/.cproject b/samples/FtpServer_Files/.cproject deleted file mode 100644 index 1750833d47..0000000000 --- a/samples/FtpServer_Files/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/FtpServer_Files/.project b/samples/FtpServer_Files/.project deleted file mode 100644 index 5c564b8742..0000000000 --- a/samples/FtpServer_Files/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - FtpServer_Files - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/FtpServer_Files/app/application.cpp b/samples/FtpServer_Files/app/application.cpp index 3c19689ca7..95481b31ea 100644 --- a/samples/FtpServer_Files/app/application.cpp +++ b/samples/FtpServer_Files/app/application.cpp @@ -18,7 +18,7 @@ void gotIP(IpAddress ip, IpAddress netmask, IpAddress gateway) ftp.addUser("guest", nullptr, IFS::UserRole::Guest); ftp.addUser("me", "123", IFS::UserRole::User); ftp.addUser("admin", "1234", IFS::UserRole::Admin); - // You can also use special FTP comand: "fsformat" for clearing file system (for example from TotalCMD) + // You can also use special FTP command: "fsformat" for clearing file system (for example from TotalCMD) } // Will be called when WiFi station timeout was reached diff --git a/samples/FtpServer_Files/component.mk b/samples/FtpServer_Files/component.mk index ceb9beac2b..3328bd6994 100644 --- a/samples/FtpServer_Files/component.mk +++ b/samples/FtpServer_Files/component.mk @@ -1,2 +1,8 @@ -HWCONFIG := ftpserver +COMPONENT_SOC := esp* host + +ifeq ($(SMING_ARCH),Esp32) +HWCONFIG := ftpserver-esp32 +else +HWCONFIG := ftpserver-esp8266 +endif SPIFF_FILES := diff --git a/samples/FtpServer_Files/ftpserver-esp32.hw b/samples/FtpServer_Files/ftpserver-esp32.hw new file mode 100644 index 0000000000..3fd3cdb1e4 --- /dev/null +++ b/samples/FtpServer_Files/ftpserver-esp32.hw @@ -0,0 +1,9 @@ +{ + "name": "FTP Server sample", + "base_config": "ftpserver", + "partitions": { + "factory": { + // "size": "384K" + } + } +} diff --git a/samples/FtpServer_Files/ftpserver-esp8266.hw b/samples/FtpServer_Files/ftpserver-esp8266.hw new file mode 100644 index 0000000000..c1aedd3b6b --- /dev/null +++ b/samples/FtpServer_Files/ftpserver-esp8266.hw @@ -0,0 +1,15 @@ +{ + "name": "FTP Server sample", + "base_config": "ftpserver", + "partitions": { + "rom0": { + "size": "480K" + }, + "spiffs0": { + "address": "0x80000" + }, + "fwfs1": { + "address": "0xA0000" + } + } +} \ No newline at end of file diff --git a/samples/FtpServer_Files/ftpserver.hw b/samples/FtpServer_Files/ftpserver.hw index eeeb4898f3..e42bc7e6db 100644 --- a/samples/FtpServer_Files/ftpserver.hw +++ b/samples/FtpServer_Files/ftpserver.hw @@ -2,17 +2,14 @@ "name": "FTP Server sample", "base_config": "standard", "partitions": { - "rom0": { - "size": "480K" - }, "spiffs0": { "type": "data", "subtype": "spiffs", - "address": "0x80000", + "address": "0x100000", "size": "0x20000" }, "fwfs1": { - "address": "0xA0000", + "address": "0x120000", "size": "330K", "type": "data", "subtype": "fwfs", diff --git a/samples/Gesture_APDS-9960/.cproject b/samples/Gesture_APDS-9960/.cproject deleted file mode 100644 index e1450b6031..0000000000 --- a/samples/Gesture_APDS-9960/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Gesture_APDS-9960/.project b/samples/Gesture_APDS-9960/.project deleted file mode 100644 index 0784e87605..0000000000 --- a/samples/Gesture_APDS-9960/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Gesture_APDS-9960 - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Gesture_APDS-9960/component.mk b/samples/Gesture_APDS-9960/component.mk index 6dc722623d..2515f096ae 100644 --- a/samples/Gesture_APDS-9960/component.mk +++ b/samples/Gesture_APDS-9960/component.mk @@ -1 +1,2 @@ ARDUINO_LIBRARIES := SparkFun_APDS9960 +DISABLE_NETWORK := 1 diff --git a/samples/HttpClient/.cproject b/samples/HttpClient/.cproject deleted file mode 100644 index aca5dca953..0000000000 --- a/samples/HttpClient/.cproject +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/HttpClient/.project b/samples/HttpClient/.project deleted file mode 100644 index 8dfc9a27e6..0000000000 --- a/samples/HttpClient/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - HttpClient - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/HttpClient/component.mk b/samples/HttpClient/component.mk index b5818865f6..7cf6292fc2 100644 --- a/samples/HttpClient/component.mk +++ b/samples/HttpClient/component.mk @@ -1,3 +1,4 @@ +COMPONENT_SOC := esp* host HWCONFIG = spiffs ## Prefer BearSSL as it can handle more gracefully big SSL packets. diff --git a/samples/HttpClient_Instapush/.cproject b/samples/HttpClient_Instapush/.cproject deleted file mode 100644 index 8c76871e37..0000000000 --- a/samples/HttpClient_Instapush/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/HttpClient_Instapush/.project b/samples/HttpClient_Instapush/.project deleted file mode 100644 index cf816de14c..0000000000 --- a/samples/HttpClient_Instapush/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - HttpClient_Instapush - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/HttpClient_Instapush/component.mk b/samples/HttpClient_Instapush/component.mk index 6fad8b7821..18dde4ba83 100644 --- a/samples/HttpClient_Instapush/component.mk +++ b/samples/HttpClient_Instapush/component.mk @@ -1 +1,2 @@ +COMPONENT_SOC := esp* host ARDUINO_LIBRARIES := ArduinoJson6 diff --git a/samples/HttpClient_ThingSpeak/.cproject b/samples/HttpClient_ThingSpeak/.cproject deleted file mode 100644 index abd0ddea14..0000000000 --- a/samples/HttpClient_ThingSpeak/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/HttpClient_ThingSpeak/.project b/samples/HttpClient_ThingSpeak/.project deleted file mode 100644 index 1de0080106..0000000000 --- a/samples/HttpClient_ThingSpeak/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - HttpClient_ThingSpeak - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/HttpClient_ThingSpeak/component.mk b/samples/HttpClient_ThingSpeak/component.mk new file mode 100644 index 0000000000..996e1b20f1 --- /dev/null +++ b/samples/HttpClient_ThingSpeak/component.mk @@ -0,0 +1 @@ +COMPONENT_SOC := esp* host diff --git a/samples/HttpServer_AJAX/.cproject b/samples/HttpServer_AJAX/.cproject deleted file mode 100644 index e6469c9e2f..0000000000 --- a/samples/HttpServer_AJAX/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/HttpServer_AJAX/.project b/samples/HttpServer_AJAX/.project deleted file mode 100644 index 63dcdd0071..0000000000 --- a/samples/HttpServer_AJAX/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - HttpServer_AJAX - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/HttpServer_AJAX/app/application.cpp b/samples/HttpServer_AJAX/app/application.cpp index 04d7cf860d..732a00d2d2 100644 --- a/samples/HttpServer_AJAX/app/application.cpp +++ b/samples/HttpServer_AJAX/app/application.cpp @@ -46,10 +46,7 @@ void onAjaxInput(HttpRequest& request, HttpResponse& response) json[stringKey] = stringValue; for(int i = 0; i < 11; i++) { - char buff[3]; - itoa(i, buff, 10); - String desiredString = "sensor_"; - desiredString += buff; + String desiredString = F("sensor_") + String(i); json[desiredString] = desiredString; } diff --git a/samples/HttpServer_AJAX/component.mk b/samples/HttpServer_AJAX/component.mk index 50337d80c6..48a65977fd 100644 --- a/samples/HttpServer_AJAX/component.mk +++ b/samples/HttpServer_AJAX/component.mk @@ -1,3 +1,4 @@ +COMPONENT_SOC := esp* host HWCONFIG := spiffs SPIFF_FILES = web/build ARDUINO_LIBRARIES := ArduinoJson6 diff --git a/samples/HttpServer_Bootstrap/.cproject b/samples/HttpServer_Bootstrap/.cproject deleted file mode 100644 index 0157e197a8..0000000000 --- a/samples/HttpServer_Bootstrap/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/HttpServer_Bootstrap/.project b/samples/HttpServer_Bootstrap/.project deleted file mode 100644 index e33b983f4e..0000000000 --- a/samples/HttpServer_Bootstrap/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - HttpServer_Bootstrap - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/HttpServer_Bootstrap/README.rst b/samples/HttpServer_Bootstrap/README.rst index d5f1a3a69a..9caf2666dc 100644 --- a/samples/HttpServer_Bootstrap/README.rst +++ b/samples/HttpServer_Bootstrap/README.rst @@ -3,7 +3,7 @@ Bootstrap Http Server Embedded web server. -This sample will download all requried files from a remote server. +This sample will download all required files from a remote server. .. image:: esp8266-web-server.png :height: 192px diff --git a/samples/HttpServer_Bootstrap/component.mk b/samples/HttpServer_Bootstrap/component.mk index ab4cb6eed9..a962a87528 100644 --- a/samples/HttpServer_Bootstrap/component.mk +++ b/samples/HttpServer_Bootstrap/component.mk @@ -1,2 +1,3 @@ +COMPONENT_SOC := esp* host HWCONFIG := spiffs SPIFF_FILES := diff --git a/samples/HttpServer_ConfigNetwork/.cproject b/samples/HttpServer_ConfigNetwork/.cproject deleted file mode 100644 index cdd4acfa57..0000000000 --- a/samples/HttpServer_ConfigNetwork/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/HttpServer_ConfigNetwork/.project b/samples/HttpServer_ConfigNetwork/.project deleted file mode 100644 index 89e43291c3..0000000000 --- a/samples/HttpServer_ConfigNetwork/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - HttpServer_ConfigNetwork - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/HttpServer_ConfigNetwork/component.mk b/samples/HttpServer_ConfigNetwork/component.mk index 2574c69f39..330da01820 100644 --- a/samples/HttpServer_ConfigNetwork/component.mk +++ b/samples/HttpServer_ConfigNetwork/component.mk @@ -1,3 +1,4 @@ +COMPONENT_SOC := esp* host HWCONFIG := spiffs SPIFF_FILES = web/build ARDUINO_LIBRARIES := ArduinoJson6 diff --git a/samples/HttpServer_ConfigNetwork/web/dev/index.html b/samples/HttpServer_ConfigNetwork/web/dev/index.html index 9686d09d1e..40d3072c73 100644 --- a/samples/HttpServer_ConfigNetwork/web/dev/index.html +++ b/samples/HttpServer_ConfigNetwork/web/dev/index.html @@ -39,14 +39,14 @@ ConnectURL: '/ajax/connect', Connect: null, CurrentNetwork: null, - GetNetworks: function (reconect) { + GetNetworks: function (reconnect) { (function worker() { $('#floatingCirclesG').show(); var ajax = $.ajax({ url: App.GetNetworksURL, type: 'POST', data: { - 'reconnect': reconect + 'reconnect': reconnect }, success: function (data) { App.SetNetworks(data.available, data.network); diff --git a/samples/HttpServer_FirmwareUpload/.cproject b/samples/HttpServer_FirmwareUpload/.cproject deleted file mode 100644 index cdd4acfa57..0000000000 --- a/samples/HttpServer_FirmwareUpload/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/HttpServer_FirmwareUpload/.project b/samples/HttpServer_FirmwareUpload/.project deleted file mode 100644 index aadd728366..0000000000 --- a/samples/HttpServer_FirmwareUpload/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - HttpServer_FirmwareUpload - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/HttpServer_FirmwareUpload/component.mk b/samples/HttpServer_FirmwareUpload/component.mk index 5bba481389..1ade710396 100644 --- a/samples/HttpServer_FirmwareUpload/component.mk +++ b/samples/HttpServer_FirmwareUpload/component.mk @@ -1,3 +1,4 @@ +COMPONENT_SOC := esp* host HWCONFIG := spiffs SPIFF_FILES = web/ ARDUINO_LIBRARIES := MultipartParser OtaUpgrade diff --git a/samples/HttpServer_Plugins/app/application.cpp b/samples/HttpServer_Plugins/app/application.cpp index 529933e8eb..04af70bb83 100644 --- a/samples/HttpServer_Plugins/app/application.cpp +++ b/samples/HttpServer_Plugins/app/application.cpp @@ -18,6 +18,9 @@ void echoContentBody(HttpRequest& request, HttpResponse& response) auto body = request.getBody(); debug_d("Got content (after modifications): %s", body.c_str()); + if(body.length() == 0) { + body = F("Echo"); + } response.headers[HTTP_HEADER_CONTENT_TYPE] = request.headers[HTTP_HEADER_CONTENT_TYPE]; response.sendString(body); } diff --git a/samples/HttpServer_Plugins/component.mk b/samples/HttpServer_Plugins/component.mk index 6a0c019953..2e97043e61 100644 --- a/samples/HttpServer_Plugins/component.mk +++ b/samples/HttpServer_Plugins/component.mk @@ -1 +1,2 @@ +COMPONENT_SOC := esp* host HWCONFIG := standard diff --git a/samples/HttpServer_WebSockets/.cproject b/samples/HttpServer_WebSockets/.cproject deleted file mode 100644 index e6469c9e2f..0000000000 --- a/samples/HttpServer_WebSockets/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/HttpServer_WebSockets/.project b/samples/HttpServer_WebSockets/.project deleted file mode 100644 index e0abec8f90..0000000000 --- a/samples/HttpServer_WebSockets/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - HttpServer_WebSocket - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/HttpServer_WebSockets/app/application.cpp b/samples/HttpServer_WebSockets/app/application.cpp index 02e46a89e3..65d34d8f62 100644 --- a/samples/HttpServer_WebSockets/app/application.cpp +++ b/samples/HttpServer_WebSockets/app/application.cpp @@ -77,7 +77,7 @@ void wsMessageReceived(WebsocketConnection& socket, const String& message) void wsBinaryReceived(WebsocketConnection& socket, uint8_t* data, size_t size) { - Serial.printf(_F("Websocket binary data recieved, size: %d\r\n"), size); + Serial.printf(_F("Websocket binary data received, size: %d\r\n"), size); } void wsDisconnected(WebsocketConnection& socket) diff --git a/samples/HttpServer_WebSockets/component.mk b/samples/HttpServer_WebSockets/component.mk index 298d44e80b..8090a5763c 100644 --- a/samples/HttpServer_WebSockets/component.mk +++ b/samples/HttpServer_WebSockets/component.mk @@ -1 +1,2 @@ +COMPONENT_SOC := esp* host HWCONFIG := spiffs diff --git a/samples/Humidity_AM2321/.cproject b/samples/Humidity_AM2321/.cproject deleted file mode 100644 index 67c056d24e..0000000000 --- a/samples/Humidity_AM2321/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Humidity_AM2321/.project b/samples/Humidity_AM2321/.project deleted file mode 100644 index c499df7d4f..0000000000 --- a/samples/Humidity_AM2321/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Humidity_AM2321 - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Humidity_AM2321/component.mk b/samples/Humidity_AM2321/component.mk index a1e9eff658..e594fdace0 100644 --- a/samples/Humidity_AM2321/component.mk +++ b/samples/Humidity_AM2321/component.mk @@ -1 +1,2 @@ ARDUINO_LIBRARIES := AM2321 +DISABLE_NETWORK := 1 diff --git a/samples/Humidity_BME280/Makefile b/samples/Humidity_BME280/Makefile new file mode 100644 index 0000000000..ff51b6c3a7 --- /dev/null +++ b/samples/Humidity_BME280/Makefile @@ -0,0 +1,9 @@ +##################################################################### +#### Please don't change this file. Use component.mk instead #### +##################################################################### + +ifndef SMING_HOME +$(error SMING_HOME is not set: please configure it as an environment variable) +endif + +include $(SMING_HOME)/project.mk diff --git a/samples/Humidity_BME280/README.rst b/samples/Humidity_BME280/README.rst new file mode 100644 index 0000000000..56f04de81e --- /dev/null +++ b/samples/Humidity_BME280/README.rst @@ -0,0 +1,6 @@ +BME280 Humidity Sensor +====================== + +Example application demonstrating the use of the :library:`Adafruit_BME280_Library` library. + +This is a port of the ``bme280test`` example from the library. diff --git a/samples/Humidity_BME280/app/application.cpp b/samples/Humidity_BME280/app/application.cpp new file mode 100644 index 0000000000..3ff338a247 --- /dev/null +++ b/samples/Humidity_BME280/app/application.cpp @@ -0,0 +1,83 @@ +/*************************************************************************** + * Sming port of example from Adafruit_BME280_Library + + This is a library for the BME280 humidity, temperature & pressure sensor + + Designed specifically to work with the Adafruit BME280 Breakout + ----> http://www.adafruit.com/products/2650 + + These sensors use I2C or SPI to communicate, 2 or 4 pins are required + to interface. The device's I2C address is either 0x76 or 0x77. + + Adafruit invests time and resources providing this open source code, + please support Adafruit andopen-source hardware by purchasing products + from Adafruit! + + Written by Limor Fried & Kevin Townsend for Adafruit Industries. + BSD license, all text above must be included in any redistribution + See the LICENSE file for details. + ***************************************************************************/ + +#include +#include +#include + +#define SEALEVELPRESSURE_HPA (1013.25) + +Adafruit_BME280 bme; +Timer procTimer; + +// Will use default pins for selected architecture. You can override values here +// #define SDA 4 +// #define SCL 5 + +void printValues() +{ + Serial.print(F("Temperature = ")); + Serial.print(bme.readTemperature()); + Serial.println(" °C"); + + Serial.print(F("Pressure = ")); + + Serial.print(bme.readPressure() / 100.0F); + Serial.println(" hPa"); + + Serial.print(F("Approx. Altitude = ")); + Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA)); + Serial.println(" m"); + + Serial.print(F("Humidity = ")); + Serial.print(bme.readHumidity()); + Serial.println(" %"); + + Serial.println(); +} + +void init() +{ + Serial.begin(SERIAL_BAUD_RATE); // 115200 by default + Serial.systemDebugOutput(true); // Enable/disable debug output + + Serial.println(F("BME280 test")); + +#ifdef SDA + Wire.pins(SDA, SCL); +#endif + + if(!bme.begin()) { // if(!bme.begin(0x76, &Wire)) { if you need a specific address + Serial.println(F("Could not find a valid BME280 sensor, check wiring, address, sensor ID!")); + Serial.print(F("SensorID was: 0x")); + Serial.println(bme.sensorID(), 16); + Serial.println(F(" ID of 0xFF probably means a bad address, a BMP 180 or BMP 085")); + Serial.println(F(" ID of 0x56-0x58 represents a BMP 280,")); + Serial.println(F(" ID of 0x60 represents a BME 280.")); + Serial.println(F(" ID of 0x61 represents a BME 680.")); + return; + } + + Serial.println(F("-- Default Test --")); + + Serial.println(); + + procTimer.initializeMs(3000, printValues).start(); +} diff --git a/samples/Humidity_BME280/component.mk b/samples/Humidity_BME280/component.mk new file mode 100644 index 0000000000..bbb930ddf7 --- /dev/null +++ b/samples/Humidity_BME280/component.mk @@ -0,0 +1,2 @@ +ARDUINO_LIBRARIES := Adafruit_BME280_Library +DISABLE_NETWORK := 1 diff --git a/samples/Humidity_DHT22/.cproject b/samples/Humidity_DHT22/.cproject deleted file mode 100644 index 7bc6a3d85f..0000000000 --- a/samples/Humidity_DHT22/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Humidity_DHT22/.project b/samples/Humidity_DHT22/.project deleted file mode 100644 index 7c49671845..0000000000 --- a/samples/Humidity_DHT22/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Humidity_DHT22 - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Humidity_DHT22/app/application.cpp b/samples/Humidity_DHT22/app/application.cpp index eaeda30469..7ecc3b67e3 100644 --- a/samples/Humidity_DHT22/app/application.cpp +++ b/samples/Humidity_DHT22/app/application.cpp @@ -70,7 +70,7 @@ void onTimer_readTemperatures() // Other goodies: // - // Heatindex is the percieved temperature taking humidity into account + // Heatindex is the perceived temperature taking humidity into account // More: https://en.wikipedia.org/wiki/Heat_index // Serial.print("Heatindex: "); diff --git a/samples/Humidity_DHT22/component.mk b/samples/Humidity_DHT22/component.mk index 6a0e948fe4..60e76d259a 100644 --- a/samples/Humidity_DHT22/component.mk +++ b/samples/Humidity_DHT22/component.mk @@ -1 +1,2 @@ ARDUINO_LIBRARIES := DHTesp +DISABLE_NETWORK := 1 diff --git a/samples/Humidity_SI7021/.cproject b/samples/Humidity_SI7021/.cproject deleted file mode 100644 index a0df18b510..0000000000 --- a/samples/Humidity_SI7021/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Humidity_SI7021/.project b/samples/Humidity_SI7021/.project deleted file mode 100644 index 4df56d4f4b..0000000000 --- a/samples/Humidity_SI7021/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Humidity_SI7021 - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Humidity_SI7021/component.mk b/samples/Humidity_SI7021/component.mk index d570b9b3f4..5c379de55b 100644 --- a/samples/Humidity_SI7021/component.mk +++ b/samples/Humidity_SI7021/component.mk @@ -1 +1,2 @@ ARDUINO_LIBRARIES := SI7021 +DISABLE_NETWORK := 1 diff --git a/samples/IR_lib/.cproject b/samples/IR_lib/.cproject deleted file mode 100644 index e1450b6031..0000000000 --- a/samples/IR_lib/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/IR_lib/.project b/samples/IR_lib/.project deleted file mode 100644 index 27f9d0781b..0000000000 --- a/samples/IR_lib/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - IR_lib - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/IR_lib/component.mk b/samples/IR_lib/component.mk index bf1221327c..bf0ca80f8d 100644 --- a/samples/IR_lib/component.mk +++ b/samples/IR_lib/component.mk @@ -1 +1,2 @@ ARDUINO_LIBRARIES := IR +DISABLE_NETWORK := 1 diff --git a/samples/LED_WS2812/.cproject b/samples/LED_WS2812/.cproject deleted file mode 100644 index 81e7be99ca..0000000000 --- a/samples/LED_WS2812/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/LED_WS2812/.project b/samples/LED_WS2812/.project deleted file mode 100644 index 478c94ca53..0000000000 --- a/samples/LED_WS2812/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - LED_WS2812 - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/LED_WS2812/component.mk b/samples/LED_WS2812/component.mk index 19ece9de25..48f0a0278b 100644 --- a/samples/LED_WS2812/component.mk +++ b/samples/LED_WS2812/component.mk @@ -1 +1,2 @@ ARDUINO_LIBRARIES := WS2812 +DISABLE_NETWORK := 1 diff --git a/samples/LED_YeelightBulb/.cproject b/samples/LED_YeelightBulb/.cproject deleted file mode 100644 index 67c056d24e..0000000000 --- a/samples/LED_YeelightBulb/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/LED_YeelightBulb/.project b/samples/LED_YeelightBulb/.project deleted file mode 100644 index be1925a270..0000000000 --- a/samples/LED_YeelightBulb/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - LED_YeelightBulb - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/LED_YeelightBulb/component.mk b/samples/LED_YeelightBulb/component.mk index 68b70f2b6b..bcb0cc54fe 100644 --- a/samples/LED_YeelightBulb/component.mk +++ b/samples/LED_YeelightBulb/component.mk @@ -1 +1,2 @@ +COMPONENT_SOC := esp* ARDUINO_LIBRARIES := Yeelight diff --git a/samples/Light_BH1750/.cproject b/samples/Light_BH1750/.cproject deleted file mode 100644 index 381169c7e1..0000000000 --- a/samples/Light_BH1750/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Light_BH1750/.project b/samples/Light_BH1750/.project deleted file mode 100644 index 62b43a568e..0000000000 --- a/samples/Light_BH1750/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Light_BH1750 - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Light_BH1750/component.mk b/samples/Light_BH1750/component.mk index 7f0ae9c735..0e15e47fa6 100644 --- a/samples/Light_BH1750/component.mk +++ b/samples/Light_BH1750/component.mk @@ -1 +1,2 @@ ARDUINO_LIBRARIES := BH1750FVI +DISABLE_NETWORK := 1 diff --git a/samples/LiquidCrystal_44780/.cproject b/samples/LiquidCrystal_44780/.cproject deleted file mode 100644 index eceed2eb33..0000000000 --- a/samples/LiquidCrystal_44780/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/LiquidCrystal_44780/.project b/samples/LiquidCrystal_44780/.project deleted file mode 100644 index b286f5f4c7..0000000000 --- a/samples/LiquidCrystal_44780/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - LiquidCrystal_44780 - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/LiquidCrystal_44780/component.mk b/samples/LiquidCrystal_44780/component.mk index 1424c543b2..7d24936b51 100644 --- a/samples/LiquidCrystal_44780/component.mk +++ b/samples/LiquidCrystal_44780/component.mk @@ -1 +1,2 @@ ARDUINO_LIBRARIES := LiquidCrystal +DISABLE_NETWORK := 1 diff --git a/samples/LiveDebug/.cproject b/samples/LiveDebug/.cproject deleted file mode 100644 index 67c056d24e..0000000000 --- a/samples/LiveDebug/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/LiveDebug/.project b/samples/LiveDebug/.project deleted file mode 100644 index 449b510792..0000000000 --- a/samples/LiveDebug/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - LiveDebug - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/LiveDebug/app/application.cpp b/samples/LiveDebug/app/application.cpp index dbe12d1ed7..32fec77f84 100644 --- a/samples/LiveDebug/app/application.cpp +++ b/samples/LiveDebug/app/application.cpp @@ -435,7 +435,7 @@ COMMAND_HANDLER(write0) * @param msg * @retval bool true if we want to report this */ -static bool __attribute__((noinline)) parseOsMessage(OsMessage& msg) +static bool __noinline parseOsMessage(OsMessage& msg) { m_printf(_F("[OS] %s\r\n"), msg.getBuffer()); if(msg.startsWith(_F("E:M "))) { diff --git a/samples/LiveDebug/component.mk b/samples/LiveDebug/component.mk index e54600cb3c..f214e89dbc 100644 --- a/samples/LiveDebug/component.mk +++ b/samples/LiveDebug/component.mk @@ -1,3 +1,4 @@ +DISABLE_NETWORK := 1 ENABLE_GDB = 1 ENABLE_GDB_CONSOLE ?= 1 diff --git a/samples/MeteoControl/.cproject b/samples/MeteoControl/.cproject deleted file mode 100644 index 5d01195b33..0000000000 --- a/samples/MeteoControl/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/MeteoControl/.project b/samples/MeteoControl/.project deleted file mode 100644 index 469d831ab9..0000000000 --- a/samples/MeteoControl/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - MeteoControl - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/MeteoControl/component.mk b/samples/MeteoControl/component.mk index b847e6d1b0..ce01f3d394 100644 --- a/samples/MeteoControl/component.mk +++ b/samples/MeteoControl/component.mk @@ -1,4 +1,4 @@ +COMPONENT_SOC := esp* host ARDUINO_LIBRARIES := LiquidCrystal DHTesp ArduinoJson6 - HWCONFIG := spiffs SPIFF_FILES = web diff --git a/samples/MeteoControl_mqtt/.cproject b/samples/MeteoControl_mqtt/.cproject deleted file mode 100644 index 5d01195b33..0000000000 --- a/samples/MeteoControl_mqtt/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/MeteoControl_mqtt/.project b/samples/MeteoControl_mqtt/.project deleted file mode 100644 index ca114ffccf..0000000000 --- a/samples/MeteoControl_mqtt/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - MeteoControl_mqtt - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/MeteoControl_mqtt/app/bmp180.cpp b/samples/MeteoControl_mqtt/app/bmp180.cpp index d6958bf57d..816c7e8390 100644 --- a/samples/MeteoControl_mqtt/app/bmp180.cpp +++ b/samples/MeteoControl_mqtt/app/bmp180.cpp @@ -23,7 +23,7 @@ void publishBMP() if(!barometer.EnsureConnected()) { Serial.println("Could not connect to BMP180"); } else { - // Retrive the current pressure in Pascals + // Retrieve the current pressure in Pascals long currentPressure = barometer.GetPressure(); // convert pressure to mmHg float BMPPress = currentPressure / 133.322; @@ -34,7 +34,7 @@ void publishBMP() Serial.println(" mmHg"); mqtt.publish(BMP_P, String(BMPPress)); - // Retrive the current temperature in degrees celcius + // Retrieve the current temperature in degrees celsius float BMPTemp = barometer.GetTemperature(); // Print out the Temperature diff --git a/samples/MeteoControl_mqtt/component.mk b/samples/MeteoControl_mqtt/component.mk index 5b00021804..3c83b86cfe 100644 --- a/samples/MeteoControl_mqtt/component.mk +++ b/samples/MeteoControl_mqtt/component.mk @@ -1 +1,2 @@ +COMPONENT_SOC := esp* host ARDUINO_LIBRARIES := BMP180 SI7021 diff --git a/samples/MqttClient_Hello/.cproject b/samples/MqttClient_Hello/.cproject deleted file mode 100644 index 8c76871e37..0000000000 --- a/samples/MqttClient_Hello/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/MqttClient_Hello/.project b/samples/MqttClient_Hello/.project deleted file mode 100644 index 36a8772000..0000000000 --- a/samples/MqttClient_Hello/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - MqttClient_Hello - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/MqttClient_Hello/component.mk b/samples/MqttClient_Hello/component.mk index 10ef45cc95..cb1ff93301 100644 --- a/samples/MqttClient_Hello/component.mk +++ b/samples/MqttClient_Hello/component.mk @@ -1,3 +1,4 @@ +COMPONENT_SOC := esp* host HWCONFIG := standard-4m ifdef MQTT_URL diff --git a/samples/Nextion_Button/.cproject b/samples/Nextion_Button/.cproject deleted file mode 100644 index 39bd845a67..0000000000 --- a/samples/Nextion_Button/.cproject +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Nextion_Button/.project b/samples/Nextion_Button/.project deleted file mode 100644 index 9b712daf01..0000000000 --- a/samples/Nextion_Button/.project +++ /dev/null @@ -1,27 +0,0 @@ - - - Nextion_Button - - - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Nextion_Button/app/application.cpp b/samples/Nextion_Button/app/application.cpp index c766f68398..6bddd18ef9 100644 --- a/samples/Nextion_Button/app/application.cpp +++ b/samples/Nextion_Button/app/application.cpp @@ -1,5 +1,3 @@ -using namespace std; -#include #include #include diff --git a/samples/Nextion_Button/component.mk b/samples/Nextion_Button/component.mk index 7ffeff230d..19cd507d61 100644 --- a/samples/Nextion_Button/component.mk +++ b/samples/Nextion_Button/component.mk @@ -1 +1,2 @@ ARDUINO_LIBRARIES := ITEADLIB_Arduino_Nextion +DISABLE_NETWORK := 1 diff --git a/samples/PortExpander_MCP23017/.cproject b/samples/PortExpander_MCP23017/.cproject deleted file mode 100644 index 4bea20a95b..0000000000 --- a/samples/PortExpander_MCP23017/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/PortExpander_MCP23017/.project b/samples/PortExpander_MCP23017/.project deleted file mode 100644 index 298a84f617..0000000000 --- a/samples/PortExpander_MCP23017/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - PortExpander_MCP23017 - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/PortExpander_MCP23017/component.mk b/samples/PortExpander_MCP23017/component.mk index decdab0b14..c9c8d8c407 100644 --- a/samples/PortExpander_MCP23017/component.mk +++ b/samples/PortExpander_MCP23017/component.mk @@ -1 +1,2 @@ ARDUINO_LIBRARIES := MCP23017 +DISABLE_NETWORK := 1 diff --git a/samples/PortExpander_MCP23S17/.cproject b/samples/PortExpander_MCP23S17/.cproject deleted file mode 100644 index bbb07b987b..0000000000 --- a/samples/PortExpander_MCP23S17/.cproject +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - - rebuild - true - true - true - - - make - - flash - true - true - true - - - - - - - - - - diff --git a/samples/PortExpander_MCP23S17/.project b/samples/PortExpander_MCP23S17/.project deleted file mode 100644 index 65d722f322..0000000000 --- a/samples/PortExpander_MCP23S17/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - PortExpander_MCP23S17 - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/PortExpander_MCP23S17/app/application.cpp b/samples/PortExpander_MCP23S17/app/application.cpp index 1e14b607c3..7de5674543 100644 --- a/samples/PortExpander_MCP23S17/app/application.cpp +++ b/samples/PortExpander_MCP23S17/app/application.cpp @@ -14,21 +14,21 @@ Timer procTimer; void init() { + Serial.begin(SERIAL_BAUD_RATE); // 115200 by default + Serial.systemDebugOutput(false); // Allow debug output to serial + Serial.println("<-= Sming start =->"); + //SET higher CPU freq & disable wifi sleep system_update_cpu_freq(SYS_CPU_160MHZ); - wifi_set_sleep_type(NONE_SLEEP_T); - - inputchip.begin(); - outputchip.begin(); - Serial.begin(SERIAL_BAUD_RATE); // 115200 by default #ifndef DISABLE_WIFI + wifi_set_sleep_type(NONE_SLEEP_T); WifiStation.enable(false); WifiAccessPoint.enable(false); #endif - Serial.systemDebugOutput(false); // Allow debug output to serial - Serial.println("<-= Sming start =->"); + inputchip.begin(); + outputchip.begin(); inputchip.pinMode(0xFFFF); // Use word-write mode to set all of the pins on inputchip to be inputs inputchip.pullupMode(0xFFFF); // Use word-write mode to Turn on the internal pull-up resistors. diff --git a/samples/PortExpander_MCP23S17/component.mk b/samples/PortExpander_MCP23S17/component.mk index 05753ccf86..3a65fa8666 100644 --- a/samples/PortExpander_MCP23S17/component.mk +++ b/samples/PortExpander_MCP23S17/component.mk @@ -1 +1,3 @@ +COMPONENT_SOC := esp8266 ARDUINO_LIBRARIES := MCP23S17 +DISABLE_NETWORK := 1 diff --git a/samples/Pressure_BMP180/.cproject b/samples/Pressure_BMP180/.cproject deleted file mode 100644 index a0df18b510..0000000000 --- a/samples/Pressure_BMP180/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Pressure_BMP180/.project b/samples/Pressure_BMP180/.project deleted file mode 100644 index 2bd01b9850..0000000000 --- a/samples/Pressure_BMP180/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Pressure_BMP180 - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Pressure_BMP180/app/application.cpp b/samples/Pressure_BMP180/app/application.cpp index 1c01ea99fd..c9eeccd1ef 100644 --- a/samples/Pressure_BMP180/app/application.cpp +++ b/samples/Pressure_BMP180/app/application.cpp @@ -20,7 +20,7 @@ void init() Serial.print("Start reading"); - // Retrive the current pressure in Pascals. + // Retrieve the current pressure in Pascals. long currentPressure = barometer.GetPressure(); // Print out the Pressure. @@ -28,7 +28,7 @@ void init() Serial.print(currentPressure); Serial.print(" Pa"); - // Retrive the current temperature in degrees celcius. + // Retrieve the current temperature in degrees celsius. float currentTemperature = barometer.GetTemperature(); // Print out the Temperature diff --git a/samples/Pressure_BMP180/component.mk b/samples/Pressure_BMP180/component.mk index bc6de35d78..c3cc2d6a9d 100644 --- a/samples/Pressure_BMP180/component.mk +++ b/samples/Pressure_BMP180/component.mk @@ -1 +1,2 @@ ARDUINO_LIBRARIES := BMP180 +DISABLE_NETWORK := 1 diff --git a/samples/Radio_RCSwitch/.cproject b/samples/Radio_RCSwitch/.cproject deleted file mode 100644 index 67c056d24e..0000000000 --- a/samples/Radio_RCSwitch/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Radio_RCSwitch/.project b/samples/Radio_RCSwitch/.project deleted file mode 100644 index 0df079907e..0000000000 --- a/samples/Radio_RCSwitch/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Radio_RCSwitch - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Radio_RCSwitch/component.mk b/samples/Radio_RCSwitch/component.mk index cd2c1300e9..5eafb36405 100644 --- a/samples/Radio_RCSwitch/component.mk +++ b/samples/Radio_RCSwitch/component.mk @@ -1 +1,2 @@ ARDUINO_LIBRARIES := RCSwitch +DISABLE_NETWORK := 1 diff --git a/samples/Radio_nRF24L01/.cproject b/samples/Radio_nRF24L01/.cproject deleted file mode 100644 index 4a4fa36c6a..0000000000 --- a/samples/Radio_nRF24L01/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Radio_nRF24L01/.project b/samples/Radio_nRF24L01/.project deleted file mode 100644 index 1591d8a885..0000000000 --- a/samples/Radio_nRF24L01/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Radio_nRF24L01 - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Radio_nRF24L01/component.mk b/samples/Radio_nRF24L01/component.mk index 9a478c319a..0d123ac87d 100644 --- a/samples/Radio_nRF24L01/component.mk +++ b/samples/Radio_nRF24L01/component.mk @@ -1 +1,3 @@ +COMPONENT_SOC := esp* ARDUINO_LIBRARIES := RF24 +DISABLE_NETWORK := 1 diff --git a/samples/Radio_si4432/.cproject b/samples/Radio_si4432/.cproject deleted file mode 100644 index a81174397f..0000000000 --- a/samples/Radio_si4432/.cproject +++ /dev/null @@ -1,118 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Radio_si4432/.project b/samples/Radio_si4432/.project deleted file mode 100644 index b0c8afa32e..0000000000 --- a/samples/Radio_si4432/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Radio_si4432 - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Radio_si4432/app/application.cpp b/samples/Radio_si4432/app/application.cpp index 08e6f69ce9..792887b940 100644 --- a/samples/Radio_si4432/app/application.cpp +++ b/samples/Radio_si4432/app/application.cpp @@ -3,7 +3,7 @@ Modified by: (github.com/)ADiea Project: Sming for ESP8266 - https://github.com/anakod/Sming License: MIT Date: 15.08.2015 -Descr: Example applicatin for radio module Si4432 aka RF22 driver +Descr: Example application for radio module Si4432 aka RF22 driver Link: http://www.electrodragon.com/w/SI4432_433M-Wireless_Transceiver_Module_%281.5KM_Range,_Shield-Protected%29 */ diff --git a/samples/Radio_si4432/component.mk b/samples/Radio_si4432/component.mk index fdf6ee7962..af654884e7 100644 --- a/samples/Radio_si4432/component.mk +++ b/samples/Radio_si4432/component.mk @@ -1 +1,2 @@ ARDUINO_LIBRARIES := si4432 +DISABLE_NETWORK := 1 diff --git a/samples/SDCard/.cproject b/samples/SDCard/.cproject deleted file mode 100644 index 36d4436471..0000000000 --- a/samples/SDCard/.cproject +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/SDCard/.project b/samples/SDCard/.project deleted file mode 100644 index c9edcd7913..0000000000 --- a/samples/SDCard/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - SDCard - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/SDCard/app/application.cpp b/samples/SDCard/app/application.cpp index b394e8b3ec..7246e4fa0e 100644 --- a/samples/SDCard/app/application.cpp +++ b/samples/SDCard/app/application.cpp @@ -37,7 +37,7 @@ void writeToFile(const String& filename, uint32_t totalBytes, uint32_t bytesPerR return; } - Serial.printf("Write %d kBytes in %d Bytes increment:\r\n", totalBytes / 1024, bytesPerRound); + Serial.printf(_F("Write %u kBytes in %u Bytes increment:\r\n"), totalBytes / 1024, bytesPerRound); for(unsigned i = 0; i < totalBytes; i++) { buf[i] = (i % 10) + '0'; } @@ -54,7 +54,7 @@ void writeToFile(const String& filename, uint32_t totalBytes, uint32_t bytesPerR uint32_t bytesWritten = 0; f_write(&file, buf + i, remainingBytes, &bytesWritten); if(bytesWritten != remainingBytes) { - Serial.printf("Only written %u bytes\n", i + bytesWritten); + Serial.printf(_F("Only written %u bytes\r\n"), i + bytesWritten); break; } i += bytesWritten; @@ -66,9 +66,9 @@ void writeToFile(const String& filename, uint32_t totalBytes, uint32_t bytesPerR unsigned elapsed = timer.elapsedTime(); Serial.print((i / 1024.0f) * 1000000.0f / elapsed); - Serial.println(" kB/s"); + Serial.println(_F(" kB/s")); } else { - Serial.printf("fopen FAIL: %u\n", (unsigned int)fRes); + Serial.printf(_F("fopen FAIL: %u\r\n"), (unsigned int)fRes); } delete[] buf; @@ -80,7 +80,8 @@ void stat_file(char* fname) FRESULT fr = f_stat(fname, &fno); switch(fr) { case FR_OK: { - Serial.printf("%lu\t", fno.fsize); + Serial.print(fno.fsize); + Serial.print('\t'); uint8_t size = 0; if(fno.fattrib & AM_DIR) { @@ -98,9 +99,9 @@ void stat_file(char* fname) Serial.print('\t'); } - Serial.printf("%u/%02u/%02u, %02u:%02u\t", (fno.fdate >> 9) + 1980, (fno.fdate >> 5) & 15, fno.fdate & 31, + Serial.printf(_F("%u/%02u/%02u, %02u:%02u\t"), (fno.fdate >> 9) + 1980, (fno.fdate >> 5) & 15, fno.fdate & 31, fno.ftime >> 11, (fno.ftime >> 5) & 63); - Serial.printf("%c%c%c%c%c\n", (fno.fattrib & AM_DIR) ? 'D' : '-', (fno.fattrib & AM_RDO) ? 'R' : '-', + Serial.printf(_F("%c%c%c%c%c\r\n"), (fno.fattrib & AM_DIR) ? 'D' : '-', (fno.fattrib & AM_RDO) ? 'R' : '-', (fno.fattrib & AM_HID) ? 'H' : '-', (fno.fattrib & AM_SYS) ? 'S' : '-', (fno.fattrib & AM_ARC) ? 'A' : '-'); break; @@ -111,7 +112,7 @@ void stat_file(char* fname) break; default: - Serial.printf("Error(%d)\n", fr); + Serial.printf(_F("Error(%d)\r\n"), fr); } } @@ -120,7 +121,7 @@ void stat_file(char* fname) */ FRESULT ls(const char* path) { - Serial.println("Size\tName\t\tDate\t\tAttributes"); + Serial.println(_F("Size\tName\t\tDate\t\tAttributes")); DIR dir; FRESULT res = f_opendir(&dir, path); /* Open the directory */ @@ -145,14 +146,14 @@ FRESULT ls(const char* path) void listFiles() { - Serial.println("1. Listing files in the root folder"); + Serial.println(_F("1. Listing files in the root folder")); ls("/"); } void readWriteTest() { //2. Open file, write a few bytes, close reopen and read - Serial.println("2. Open file \"test.txt\" and write some data..."); + Serial.println(_F("2. Open file \"test.txt\" and write some data...")); FIL file; FRESULT fRes = f_open(&file, "test.txt", FA_WRITE | FA_CREATE_ALWAYS); @@ -162,20 +163,20 @@ void readWriteTest() f_write(&file, "hello ", 5, &actual); //or using printf for convenience - f_printf(&file, " has %d letters\r\n", actual); + f_printf(&file, _F(" has %d letters\r\n"), actual); if(actual != 5) { - Serial.printf("Only written %d bytes\n", actual); + Serial.printf(_F("Only written %u bytes\r\n"), actual); } f_close(&file); } else { - Serial.printf("fopen FAIL: %d \n", (unsigned int)fRes); + Serial.printf(_F("fopen FAIL: %u\r\n"), (unsigned int)fRes); } } void readTest() { - Serial.println("3. Open file \"test.txt\" and read"); + Serial.println(_F("3. Open file \"test.txt\" and read")); FIL file; FRESULT fRes = f_open(&file, "test.txt", FA_READ); @@ -188,11 +189,11 @@ void readTest() f_read(&file, buffer, sizeof(buffer), &actual); buffer[actual] = 0; - Serial.printf("Read: %s \n", buffer); + Serial.printf(_F("Read: %s\r\n"), buffer); f_close(&file); } else { - Serial.printf("fopen FAIL: %d \n", fRes); + Serial.printf(_F("fopen FAIL: %u\r\n"), fRes); } } @@ -212,7 +213,7 @@ bool speedTest(unsigned num) return false; } - Serial.printf("4.%u: Write speed benchmark\r\n", num + 1); + Serial.printf(_F("4.%u: Write speed benchmark\r\n"), num + 1); auto& test = tests[num]; String filename; @@ -229,7 +230,7 @@ bool sdInit() // SDCardSPI = new SPISoft(PIN_CARD_DO, PIN_CARD_DI, PIN_CARD_CK, 0); SDCardSPI = &SPI; if(!SDCard_begin(PIN_CARD_SS, SPI_FREQ_LIMIT)) { - Serial.println("SPI init failed"); + Serial.println(_F("SPI init failed")); return false; } @@ -258,7 +259,7 @@ void runTest(uint32_t state = 0) break; default: if(!speedTest(state - 5)) { - Serial.println("End of tests"); + Serial.println(_F("End of tests")); return; } } @@ -271,6 +272,6 @@ void init() Serial.begin(SERIAL_BAUD_RATE); // 115200 by default Serial.systemDebugOutput(true); // Allow debug output to serial - Serial.print("\nSDCard example - !!! see code for HW setup !!! \n\n"); + Serial.print(_F("\r\nSDCard example - !!! see code for HW setup !!! \r\n\n")); runTest(); } diff --git a/samples/SDCard/component.mk b/samples/SDCard/component.mk index e93d57393d..b5a80cdda0 100644 --- a/samples/SDCard/component.mk +++ b/samples/SDCard/component.mk @@ -1 +1,3 @@ +COMPONENT_SOC := esp* ARDUINO_LIBRARIES := SDCard +DISABLE_NETWORK := 1 diff --git a/samples/ScreenLCD_5110/.cproject b/samples/ScreenLCD_5110/.cproject deleted file mode 100644 index e8a5545742..0000000000 --- a/samples/ScreenLCD_5110/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/ScreenLCD_5110/.project b/samples/ScreenLCD_5110/.project deleted file mode 100644 index 68b4fc8537..0000000000 --- a/samples/ScreenLCD_5110/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - ScreenLCD_5110 - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/ScreenLCD_5110/component.mk b/samples/ScreenLCD_5110/component.mk index 2855fb3158..ffe0e64f7e 100644 --- a/samples/ScreenLCD_5110/component.mk +++ b/samples/ScreenLCD_5110/component.mk @@ -1 +1,3 @@ +COMPONENT_SOC := esp8266 ARDUINO_LIBRARIES := Adafruit_PCD8544 +DISABLE_NETWORK := 1 diff --git a/samples/ScreenOLED_SSD1306/.cproject b/samples/ScreenOLED_SSD1306/.cproject deleted file mode 100644 index 048c622dd7..0000000000 --- a/samples/ScreenOLED_SSD1306/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/ScreenOLED_SSD1306/.project b/samples/ScreenOLED_SSD1306/.project deleted file mode 100644 index 1887d13d95..0000000000 --- a/samples/ScreenOLED_SSD1306/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - ScreenOLED_SSD1306 - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/ScreenOLED_SSD1306/component.mk b/samples/ScreenOLED_SSD1306/component.mk index 72278b67fd..d9eab68d53 100644 --- a/samples/ScreenOLED_SSD1306/component.mk +++ b/samples/ScreenOLED_SSD1306/component.mk @@ -1 +1,2 @@ ARDUINO_LIBRARIES := Adafruit_SSD1306 +DISABLE_NETWORK := 1 diff --git a/samples/ScreenTFT_ILI9163C/.cproject b/samples/ScreenTFT_ILI9163C/.cproject deleted file mode 100644 index 4a4fa36c6a..0000000000 --- a/samples/ScreenTFT_ILI9163C/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/ScreenTFT_ILI9163C/.project b/samples/ScreenTFT_ILI9163C/.project deleted file mode 100644 index 37792683b9..0000000000 --- a/samples/ScreenTFT_ILI9163C/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - ScreenTFT_ILI9163C - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/ScreenTFT_ILI9163C/component.mk b/samples/ScreenTFT_ILI9163C/component.mk index a6c5efa5b8..49f0125cd1 100644 --- a/samples/ScreenTFT_ILI9163C/component.mk +++ b/samples/ScreenTFT_ILI9163C/component.mk @@ -1 +1,2 @@ ARDUINO_LIBRARIES := TFT_ILI9163C +DISABLE_NETWORK := 1 diff --git a/samples/ScreenTFT_ILI9340-ILI9341/.cproject b/samples/ScreenTFT_ILI9340-ILI9341/.cproject deleted file mode 100644 index 4a4fa36c6a..0000000000 --- a/samples/ScreenTFT_ILI9340-ILI9341/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/ScreenTFT_ILI9340-ILI9341/.project b/samples/ScreenTFT_ILI9340-ILI9341/.project deleted file mode 100644 index da265b88de..0000000000 --- a/samples/ScreenTFT_ILI9340-ILI9341/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - ScreenTFT_ILI9340-ILI9341 - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/ScreenTFT_ILI9340-ILI9341/component.mk b/samples/ScreenTFT_ILI9340-ILI9341/component.mk index 29bda5a46a..c707c73488 100644 --- a/samples/ScreenTFT_ILI9340-ILI9341/component.mk +++ b/samples/ScreenTFT_ILI9340-ILI9341/component.mk @@ -1,2 +1,4 @@ +COMPONENT_SOC := esp* HWCONFIG := spiffs ARDUINO_LIBRARIES := Adafruit_ILI9341 +DISABLE_NETWORK := 1 diff --git a/samples/ScreenTFT_ST7735/.cproject b/samples/ScreenTFT_ST7735/.cproject deleted file mode 100644 index e1450b6031..0000000000 --- a/samples/ScreenTFT_ST7735/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/ScreenTFT_ST7735/.project b/samples/ScreenTFT_ST7735/.project deleted file mode 100644 index 4a2668bcb8..0000000000 --- a/samples/ScreenTFT_ST7735/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - ScreenTFT_ST7735 - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/ScreenTFT_ST7735/component.mk b/samples/ScreenTFT_ST7735/component.mk index cb9740b8f7..9dc2b653a6 100644 --- a/samples/ScreenTFT_ST7735/component.mk +++ b/samples/ScreenTFT_ST7735/component.mk @@ -1,2 +1,4 @@ +COMPONENT_SOC := esp* HWCONFIG := spiffs ARDUINO_LIBRARIES := Adafruit_ST7735 +DISABLE_NETWORK := 1 diff --git a/samples/SmtpClient/.cproject b/samples/SmtpClient/.cproject deleted file mode 100644 index 4a9fd7f0a1..0000000000 --- a/samples/SmtpClient/.cproject +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/SmtpClient/.project b/samples/SmtpClient/.project deleted file mode 100644 index 90f03a2107..0000000000 --- a/samples/SmtpClient/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - SmtpClient - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/SmtpClient/component.mk b/samples/SmtpClient/component.mk index 943f6630c9..a2dcaeebda 100644 --- a/samples/SmtpClient/component.mk +++ b/samples/SmtpClient/component.mk @@ -1,2 +1,3 @@ +COMPONENT_SOC := esp* host HWCONFIG := spiffs ENABLE_SSL ?= 1 diff --git a/samples/SystemClock_NTP/.cproject b/samples/SystemClock_NTP/.cproject deleted file mode 100644 index 856edbd329..0000000000 --- a/samples/SystemClock_NTP/.cproject +++ /dev/null @@ -1,155 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/SystemClock_NTP/.project b/samples/SystemClock_NTP/.project deleted file mode 100644 index 6361377128..0000000000 --- a/samples/SystemClock_NTP/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - SystemClock_NTP - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/SystemClock_NTP/app/application.cpp b/samples/SystemClock_NTP/app/application.cpp index 56ae91dfb0..4ada03d350 100644 --- a/samples/SystemClock_NTP/app/application.cpp +++ b/samples/SystemClock_NTP/app/application.cpp @@ -27,7 +27,7 @@ Timer printTimer; // NtpClient ntpClient ("my_ntp_server", myRequestInterval, onNtpReceive); // Option 3 -// Use this option if you want to start wit autorefresh and autosystemupdate +// Use this option if you want to start with autorefresh and autosystemupdate // No further callback from ntpClient // NtpClient ntpClient("pool.ntp.org", 30); diff --git a/samples/SystemClock_NTP/component.mk b/samples/SystemClock_NTP/component.mk index 2d668a76f1..e1c336e04d 100644 --- a/samples/SystemClock_NTP/component.mk +++ b/samples/SystemClock_NTP/component.mk @@ -1,3 +1,4 @@ +COMPONENT_SOC := esp* host ARDUINO_LIBRARIES = \ Timezone \ SolarCalculator diff --git a/samples/TcpClient_NarodMon/.cproject b/samples/TcpClient_NarodMon/.cproject deleted file mode 100644 index 459f3b4554..0000000000 --- a/samples/TcpClient_NarodMon/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/TcpClient_NarodMon/.project b/samples/TcpClient_NarodMon/.project deleted file mode 100644 index ee6203cb14..0000000000 --- a/samples/TcpClient_NarodMon/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - TcpClient_NarodMon - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/TcpClient_NarodMon/component.mk b/samples/TcpClient_NarodMon/component.mk new file mode 100644 index 0000000000..996e1b20f1 --- /dev/null +++ b/samples/TcpClient_NarodMon/component.mk @@ -0,0 +1 @@ +COMPONENT_SOC := esp* host diff --git a/samples/Telnet_Server/.cproject b/samples/Telnet_Server/.cproject deleted file mode 100644 index 463345789e..0000000000 --- a/samples/Telnet_Server/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Telnet_Server/.project b/samples/Telnet_Server/.project deleted file mode 100644 index aef1d14e81..0000000000 --- a/samples/Telnet_Server/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Telnet_Server - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Telnet_Server/app/application.cpp b/samples/Telnet_Server/app/application.cpp index 08c19c3b87..956c190811 100644 --- a/samples/Telnet_Server/app/application.cpp +++ b/samples/Telnet_Server/app/application.cpp @@ -16,22 +16,22 @@ void checkHeap() { int currentHeap = system_get_free_heap_size(); if(currentHeap != savedHeap) { - Debug.printf("Heap change, current = %d\r\n", currentHeap); + Debug.printf(_F("Heap change, current = %u\r\n"), currentHeap); savedHeap = currentHeap; } } void applicationCommand(String commandLine, CommandOutput* commandOutput) { - commandOutput->printf("Hello from Telnet Example application\r\nYou entered : '"); - commandOutput->printf(commandLine.c_str()); - commandOutput->printf("'\r\n"); - commandOutput->printf("Tokenized commandLine is : \r\n"); + commandOutput->print(_F("Hello from Telnet Example application\r\nYou entered : '")); + commandOutput->print(commandLine.c_str()); + commandOutput->println('\''); + commandOutput->println(_F("Tokenized commandLine is : ")); Vector commandToken; - int numToken = splitString(commandLine, ' ', commandToken); - for(int i = 0; i < numToken; i++) { - commandOutput->printf("%d : %s\r\n", i, commandToken.at(i).c_str()); + unsigned numToken = splitString(commandLine, ' ', commandToken); + for(unsigned i = 0; i < numToken; i++) { + commandOutput->printf(_F("%u : %s\r\n"), i, commandToken.at(i).c_str()); } } @@ -40,19 +40,19 @@ void appheapCommand(String commandLine, CommandOutput* commandOutput) Vector commandToken; int numToken = splitString(commandLine, ' ', commandToken); if(numToken != 2) { - commandOutput->printf("Usage appheap on/off/now\r\n"); + commandOutput->println(_F("Usage appheap on/off/now")); } else if(commandToken[1] == "on") { - commandOutput->printf("Timer heap display started \r\n"); + commandOutput->println(_F("Timer heap display started")); savedHeap = 0; memoryTimer.initializeMs(250, checkHeap).start(); } else if(commandToken[1] == "off") { - commandOutput->printf("Timer heap display stopped \r\n"); + commandOutput->println(_F("Timer heap display stopped")); savedHeap = 0; memoryTimer.stop(); } else if(commandToken[1] == "now") { - commandOutput->printf("Heap current free = %d\r\n", system_get_free_heap_size()); + commandOutput->printf(_F("Heap current free = %u\r\n"), system_get_free_heap_size()); } else { - commandOutput->printf("Usage appheap on/off/now\r\n"); + commandOutput->println(_F("Usage appheap on/off/now")); } } @@ -65,8 +65,8 @@ bool tcpServerClientReceive(TcpClient& client, char* data, int size) { debugf("Application DataCallback : %s, %d bytes \r\n", client.getRemoteIp().toString().c_str(), size); debugf("Data : %s", data); - client.sendString("sendString data\r\n", false); - client.writeString("writeString data\r\n", 0); + client.sendString(F("sendString data\r\n"), false); + client.writeString(F("writeString data\r\n"), 0); if(strcmp(data, "close") == 0) { debugf("Closing client"); client.close(); @@ -74,7 +74,7 @@ bool tcpServerClientReceive(TcpClient& client, char* data, int size) return true; } -void tcpServerClientComplete(TcpClient& client, bool succesfull) +void tcpServerClientComplete(TcpClient& client, bool successful) { debugf("Application CompleteCallback : %s \r\n", client.getRemoteIp().toString().c_str()); } @@ -86,18 +86,18 @@ void startServers() { tcpServer.listen(8023); - Serial.println("\r\n=== TCP SERVER Port 8023 STARTED ==="); + Serial.println(_F("\r\n=== TCP SERVER Port 8023 STARTED ===")); Serial.println(WifiStation.getIP()); - Serial.println("==============================\r\n"); + Serial.println(_F("==============================\r\n")); telnetServer.listen(23); - Serial.println("\r\n=== Telnet SERVER Port 23 STARTED ==="); + Serial.println(_F("\r\n=== Telnet SERVER Port 23 STARTED ===")); Serial.println(WifiStation.getIP()); - Serial.println("==============================\r\n"); + Serial.println(_F("==============================\r\n")); - commandHandler.registerCommand(CommandDelegate("application", "This command is defined by the application\r\n", - "testGroup", applicationCommand)); + commandHandler.registerCommand(CommandDelegate( + F("application"), F("This command is defined by the application\r\n"), F("testGroup"), applicationCommand)); } void connectFail(const String& ssid, MacAddress bssid, WifiDisconnectReason reason) @@ -125,9 +125,9 @@ void init() Debug.setDebug(Serial); Debug.initCommand(); Debug.start(); - Debug.printf("This is the debug output\r\n"); + Debug.println(_F("This is the debug output")); telnetServer.enableDebug(true); /* is default but here to show possibility */ - commandHandler.registerCommand( - CommandDelegate("appheap", "Usage appheap on/off/now for heapdisplay\r\n", "testGroup", appheapCommand)); + commandHandler.registerCommand(CommandDelegate(F("appheap"), F("Usage appheap on/off/now for heapdisplay\r\n"), + F("testGroup"), appheapCommand)); memoryTimer.initializeMs(250, checkHeap).start(); } diff --git a/samples/Telnet_Server/component.mk b/samples/Telnet_Server/component.mk new file mode 100644 index 0000000000..996e1b20f1 --- /dev/null +++ b/samples/Telnet_Server/component.mk @@ -0,0 +1 @@ +COMPONENT_SOC := esp* host diff --git a/samples/Temperature_DS1820/.cproject b/samples/Temperature_DS1820/.cproject deleted file mode 100644 index df016fdffe..0000000000 --- a/samples/Temperature_DS1820/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Temperature_DS1820/.project b/samples/Temperature_DS1820/.project deleted file mode 100644 index d9881de0c6..0000000000 --- a/samples/Temperature_DS1820/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Temperature_DS1820 - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Temperature_DS1820/component.mk b/samples/Temperature_DS1820/component.mk index d5d59373b7..54de4b6623 100644 --- a/samples/Temperature_DS1820/component.mk +++ b/samples/Temperature_DS1820/component.mk @@ -1 +1,2 @@ ARDUINO_LIBRARIES := DS18S20 +DISABLE_NETWORK := 1 diff --git a/samples/UdpServer_Echo/.cproject b/samples/UdpServer_Echo/.cproject deleted file mode 100644 index 5a684f3a20..0000000000 --- a/samples/UdpServer_Echo/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/UdpServer_Echo/.project b/samples/UdpServer_Echo/.project deleted file mode 100644 index 4acadfd77f..0000000000 --- a/samples/UdpServer_Echo/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - UdpServer_Echo - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/UdpServer_Echo/component.mk b/samples/UdpServer_Echo/component.mk new file mode 100644 index 0000000000..996e1b20f1 --- /dev/null +++ b/samples/UdpServer_Echo/component.mk @@ -0,0 +1 @@ +COMPONENT_SOC := esp* host diff --git a/samples/UdpServer_mDNS/.cproject b/samples/UdpServer_mDNS/.cproject deleted file mode 100644 index e6469c9e2f..0000000000 --- a/samples/UdpServer_mDNS/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/UdpServer_mDNS/.project b/samples/UdpServer_mDNS/.project deleted file mode 100644 index fc968b3b84..0000000000 --- a/samples/UdpServer_mDNS/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - UdpServer_mDNS - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/UdpServer_mDNS/component.mk b/samples/UdpServer_mDNS/component.mk index 331b317ed9..5d9e79ee5e 100644 --- a/samples/UdpServer_mDNS/component.mk +++ b/samples/UdpServer_mDNS/component.mk @@ -1,3 +1,4 @@ +COMPONENT_SOC := esp* host HWCONFIG := spiffs SPIFF_FILES := COMPONENT_DEPENDS += MDNS diff --git a/samples/Ultrasonic_HCSR04/.cproject b/samples/Ultrasonic_HCSR04/.cproject deleted file mode 100644 index c05a0940d8..0000000000 --- a/samples/Ultrasonic_HCSR04/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Ultrasonic_HCSR04/.project b/samples/Ultrasonic_HCSR04/.project deleted file mode 100644 index 8402f0ff12..0000000000 --- a/samples/Ultrasonic_HCSR04/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Ultrasonic_HCSR04 - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Ultrasonic_HCSR04/component.mk b/samples/Ultrasonic_HCSR04/component.mk index 793a94abd4..1b50775e24 100644 --- a/samples/Ultrasonic_HCSR04/component.mk +++ b/samples/Ultrasonic_HCSR04/component.mk @@ -1 +1,2 @@ ARDUINO_LIBRARIES := Ultrasonic +DISABLE_NETWORK := 1 diff --git a/samples/WebcamServer/.cproject b/samples/WebcamServer/.cproject deleted file mode 100644 index 0d63e8af6b..0000000000 --- a/samples/WebcamServer/.cproject +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - - all - true - true - true - - - make - - clean - true - true - true - - - - diff --git a/samples/WebcamServer/.project b/samples/WebcamServer/.project deleted file mode 100644 index e30182afc1..0000000000 --- a/samples/WebcamServer/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - WebcamServer - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/WebcamServer/component.mk b/samples/WebcamServer/component.mk index 5acc510571..b42229fefe 100644 --- a/samples/WebcamServer/component.mk +++ b/samples/WebcamServer/component.mk @@ -1,3 +1,4 @@ +COMPONENT_SOC := esp* host ARDUINO_LIBRARIES := WebCam HWCONFIG := spiffs SPIFF_FILES = web/build diff --git a/samples/Websocket_Client/.cproject b/samples/Websocket_Client/.cproject deleted file mode 100644 index 459f3b4554..0000000000 --- a/samples/Websocket_Client/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Websocket_Client/.project b/samples/Websocket_Client/.project deleted file mode 100644 index 6ad06a449f..0000000000 --- a/samples/Websocket_Client/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Websocket_Client - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Websocket_Client/README.rst b/samples/Websocket_Client/README.rst index bdb1406b5b..141fe2fa58 100644 --- a/samples/Websocket_Client/README.rst +++ b/samples/Websocket_Client/README.rst @@ -7,4 +7,4 @@ The client tries to connect to *echo.websocket.org*. It sents 10 messages then client connection is closed. It reconnects and sends 25 messages and continues doing same. -This demo shows connecton, closing and reconnection methods of WebsocketClient. +This demo shows connection, closing and reconnection methods of WebsocketClient. diff --git a/samples/Websocket_Client/app/application.cpp b/samples/Websocket_Client/app/application.cpp index 4c7464f496..4cb39dde4f 100644 --- a/samples/Websocket_Client/app/application.cpp +++ b/samples/Websocket_Client/app/application.cpp @@ -6,7 +6,7 @@ * It sents 25 messages then client connection is closed. * It reconnects and sends 25 messages and continues doing same. * - * This demo shows connecton, closing , reconnection methods of + * This demo shows connection, closing , reconnection methods of * websocket client. */ #include @@ -45,25 +45,26 @@ void wsMessageSent(); void wsConnected(WebsocketConnection& wsConnection) { - Serial.printf(_F("Start sending messages every %u second(s)...\n"), MESSAGE_INTERVAL); + Serial.printf(_F("Start sending messages every %u second(s)...\r\n"), MESSAGE_INTERVAL); msgTimer.initializeMs(MESSAGE_INTERVAL * 1000, wsMessageSent); msgTimer.start(); } void wsMessageReceived(WebsocketConnection& wsConnection, const String& message) { - Serial.printf(_F("WebSocket message received: %s\n"), message.c_str()); - Serial.printf(_F("Free Heap: %d\n"), system_get_free_heap_size()); + Serial.printf(_F("WebSocket message received: %s\r\n"), message.c_str()); + Serial.printf(_F("Free Heap: %u\r\n"), system_get_free_heap_size()); } void wsBinReceived(WebsocketConnection& wsConnection, uint8_t* data, size_t size) { Serial.println(_F("WebSocket BINARY received")); for(uint8_t i = 0; i < size; i++) { - Serial.printf("wsBin[%u] = 0x%02X\n", i, data[i]); + Serial.printf("wsBin[%u] = 0x%02X\r\n", i, data[i]); } - Serial.printf("Free Heap: %d\n", system_get_free_heap_size()); + Serial.print(_F("Free Heap: ")); + Serial.println(system_get_free_heap_size()); } void restart() @@ -76,7 +77,7 @@ void restart() void wsDisconnected(WebsocketConnection& wsConnection) { - Serial.printf(_F("Restarting websocket client after %d seconds\n"), RESTART_PERIOD); + Serial.printf(_F("Restarting websocket client after %u seconds\r\n"), RESTART_PERIOD); msgTimer.setCallback(restart); msgTimer.setIntervalMs(RESTART_PERIOD * 1000); msgTimer.startOnce(); @@ -107,7 +108,7 @@ void wsMessageSent() buf[1] = msg_cnt++; Serial.println(_F("Sending websocket binary buffer")); for(uint8_t i = 0; i < 3; i++) { - Serial.printf("wsBin[%u] = 0x%02X\n", i, buf[i]); + Serial.printf("wsBin[%u] = 0x%02X\r\n", i, buf[i]); } wsClient.sendBinary(buf, 3); diff --git a/samples/Websocket_Client/component.mk b/samples/Websocket_Client/component.mk index 38bc642725..1ca12e2921 100644 --- a/samples/Websocket_Client/component.mk +++ b/samples/Websocket_Client/component.mk @@ -1,3 +1,4 @@ +COMPONENT_SOC := esp* host HWCONFIG := standard-4m # Uncomment the option below if you want SSL support diff --git a/samples/Wifi_Sniffer/.cproject b/samples/Wifi_Sniffer/.cproject deleted file mode 100644 index 67c056d24e..0000000000 --- a/samples/Wifi_Sniffer/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/samples/Wifi_Sniffer/.project b/samples/Wifi_Sniffer/.project deleted file mode 100644 index a52462885d..0000000000 --- a/samples/Wifi_Sniffer/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - Wifi_Sniffer - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/samples/Wifi_Sniffer/component.mk b/samples/Wifi_Sniffer/component.mk new file mode 100644 index 0000000000..e243360e9c --- /dev/null +++ b/samples/Wifi_Sniffer/component.mk @@ -0,0 +1 @@ +COMPONENT_SOC := esp8266 diff --git a/tests/HostTests/.cproject b/tests/HostTests/.cproject deleted file mode 100644 index 67c056d24e..0000000000 --- a/tests/HostTests/.cproject +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - make - -f ${ProjDirPath}/Makefile - all - true - true - true - - - make - -f ${ProjDirPath}/Makefile - clean - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flash - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashonefile - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashinit - true - true - true - - - make - -f ${ProjDirPath}/Makefile - flashboot - true - true - true - - - make - -f ${ProjDirPath}/Makefile - rebuild - true - true - true - - - - - - - - - - - - - - - - - - - - diff --git a/tests/HostTests/.project b/tests/HostTests/.project deleted file mode 100644 index 0102fc9915..0000000000 --- a/tests/HostTests/.project +++ /dev/null @@ -1,28 +0,0 @@ - - - HostTests - - - SmingFramework - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.core.ccnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/tests/HostTests/Kconfig b/tests/HostTests/Kconfig new file mode 100644 index 0000000000..3a3127137b --- /dev/null +++ b/tests/HostTests/Kconfig @@ -0,0 +1,13 @@ +menu "HostTests application" + config TEST_GROUP_INTERVAL + int "Time in milliseconds to pause after a test group has completed" + default 500 + + config RESTART_DELAY + int "Time in milliseconds to wait before re-starting all tests" + default 0 if $SMING_ARCH = Host + default 10000 if $SMING_ARCH != Host + help + Set to 0 to perform a system restart after all tests have completed + +endmenu diff --git a/tests/HostTests/component.mk b/tests/HostTests/component.mk index 0518851e86..741d7ea035 100644 --- a/tests/HostTests/component.mk +++ b/tests/HostTests/component.mk @@ -1,4 +1,10 @@ +ifeq ($(SMING_ARCH),Rp2040) +HWCONFIG = host-tests-1m +DISABLE_NETWORK := 1 +else HWCONFIG = host-tests +endif + DEBUG_VERBOSE_LEVEL = 2 COMPONENT_INCDIRS := include @@ -7,6 +13,12 @@ COMPONENT_SRCDIRS := \ modules \ Arch/$(SMING_ARCH) +ifneq ($(DISABLE_NETWORK),1) +COMPONENT_SRCDIRS += \ + modules/Network \ + modules/Network/Arch/$(SMING_ARCH) +endif + ARDUINO_LIBRARIES := \ SmingTest \ ArduinoJson5 \ @@ -54,4 +66,4 @@ $(SPIFFSGEN_BIN): clean: resource-clean .PHONY: resource-clean resource-clean: - rm -f $(SPIFFSGEN_BIN) + $(Q) rm -f $(SPIFFSGEN_BIN) diff --git a/tests/HostTests/host-tests-1m.hw b/tests/HostTests/host-tests-1m.hw new file mode 100644 index 0000000000..3ad4348efc --- /dev/null +++ b/tests/HostTests/host-tests-1m.hw @@ -0,0 +1,17 @@ +{ + "name": "Host Tests (1M flash)", + "base_config": "host-tests", + "options": [ + "1m" + ], + "partitions": { + "fwfs0": { + "address": "0x000c0000", + "size": "128K" + }, + "spiffs0": { + "size": "0x10000", + "address": "0x000e0000" + } + } +} diff --git a/tests/HostTests/include/modules.h b/tests/HostTests/include/modules.h index 676fea8fc8..9a87341b3f 100644 --- a/tests/HostTests/include/modules.h +++ b/tests/HostTests/include/modules.h @@ -1,16 +1,24 @@ // List of test modules to register +#ifdef DISABLE_NETWORK +#define XX_NET(test) +#else +#define XX_NET(test) XX(test) +#endif + // Architecture-specific test modules #ifdef ARCH_HOST #define ARCH_TEST_MAP(XX) \ - XX(Hosted) \ - XX(HttpRequest) \ - XX(TcpClient) + XX_NET(Hosted) \ + XX_NET(HttpRequest) \ + XX_NET(TcpClient) #else #define ARCH_TEST_MAP(XX) #endif #define TEST_MAP(XX) \ + XX(System) \ + XX(SpiFlash) \ XX(Libc) \ XX(PreCache) \ XX(BitSet) \ @@ -23,15 +31,14 @@ XX(TemplateStream) \ XX(Serial) \ XX(ObjectMap) \ - XX(Base64) \ + XX_NET(Base64) \ XX(DateTime) \ - XX(Http) \ - XX(Url) \ + XX_NET(Http) \ + XX_NET(Url) \ XX(ArduinoJson5) \ XX(ArduinoJson6) \ XX(Storage) \ XX(Files) \ - XX(SpiFlash) \ XX(Spiffs) \ XX(Rational) \ XX(Clocks) \ diff --git a/tests/HostTests/modules/ArduinoJson6.cpp b/tests/HostTests/modules/ArduinoJson6.cpp index 2bc19a64c9..e56d813818 100644 --- a/tests/HostTests/modules/ArduinoJson6.cpp +++ b/tests/HostTests/modules/ArduinoJson6.cpp @@ -269,29 +269,29 @@ class JsonTest6 : public TestGroup } } - void __attribute__((noinline)) loadBuffer(const char* buffer, size_t length) + void __noinline loadBuffer(const char* buffer, size_t length) { TEST_ASSERT(Json::deserialize(doc, buffer, length)); } - void __attribute__((noinline)) loadFlashString() + void __noinline loadFlashString() { TEST_ASSERT(Json::deserialize(doc, Resource::test_json)); } - void __attribute__((noinline)) loadFlashStringViaStream(bool useFlashRead) + void __noinline loadFlashStringViaStream(bool useFlashRead) { FSTR::Stream stream(Resource::test_json, useFlashRead); TEST_ASSERT(Json::deserialize(doc, stream)); } - void __attribute__((noinline)) loadStream(IDataSourceStream& stream) + void __noinline loadStream(IDataSourceStream& stream) { stream.seekFrom(0, SeekOrigin::Start); TEST_ASSERT(Json::deserialize(doc, stream)); } - void __attribute__((noinline)) loadFile(const char* filename) + void __noinline loadFile(const char* filename) { FileStream fs(filename); loadStream(fs); diff --git a/tests/HostTests/modules/BitSet.cpp b/tests/HostTests/modules/BitSet.cpp index 6833578771..4f0b85a85b 100644 --- a/tests/HostTests/modules/BitSet.cpp +++ b/tests/HostTests/modules/BitSet.cpp @@ -1,5 +1,6 @@ #include #include +#include #define FRUIT_ELEMENT_MAP(XX) \ XX(apple) \ diff --git a/tests/HostTests/modules/Clocks.cpp b/tests/HostTests/modules/Clocks.cpp index a1d251483a..331fe55415 100644 --- a/tests/HostTests/modules/Clocks.cpp +++ b/tests/HostTests/modules/Clocks.cpp @@ -267,7 +267,7 @@ class BenchmarkPolledTimer : public TestGroup static constexpr unsigned TIMEOUT_MS = 100; - unsigned __attribute__((noinline)) millis_loop() + unsigned __noinline millis_loop() { unsigned loopCount = 0; unsigned start = millis(); @@ -277,7 +277,7 @@ class BenchmarkPolledTimer : public TestGroup return loopCount; } - unsigned __attribute__((noinline)) micros_loop() + unsigned __noinline micros_loop() { unsigned loopCount = 0; unsigned start = micros(); @@ -287,7 +287,7 @@ class BenchmarkPolledTimer : public TestGroup return loopCount; } - unsigned __attribute__((noinline)) polledTimer_loop() + unsigned __noinline polledTimer_loop() { unsigned loopCount = 0; OneShotFastMs timer(TIMEOUT_MS); @@ -423,9 +423,8 @@ template void testTimer1() // uint64_t refticks = timer1.timeToTicksRef(time); auto check = [time, refticks](const char* tag, TimeType ticks) { - if(refticks != ticks) { - int64_t diff = int64_t(ticks) - int64_t(refticks); - + int64_t diff = int64_t(ticks) - int64_t(refticks); + if(abs(diff) > 2) { Serial.print("time = "); Serial.print(time); Serial.print(", refticks = "); diff --git a/tests/HostTests/modules/Network/Arch/Host/Hosted.cpp b/tests/HostTests/modules/Network/Arch/Host/Hosted.cpp new file mode 100644 index 0000000000..c77f9b54cb --- /dev/null +++ b/tests/HostTests/modules/Network/Arch/Host/Hosted.cpp @@ -0,0 +1,155 @@ +#include + +#include +#include +#include +#include +#include +#include + +using namespace simpleRPC; + +static uint32_t plusCommand(uint8_t a, uint16_t b) +{ + return a + b; +}; + +class HostedTest : public TestGroup +{ +public: + using RemoteCommands = HashMap; + + HostedTest() : TestGroup(_F("Hosted")) + { + } + + void execute() override + { + char packet[] = { + 0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x52, 0x50, 0x43, 0x00, 0x03, 0x00, 0x00, 0x3c, 0x49, 0x00, 0x3a, 0x20, + 0x48, 0x20, 0x42, 0x3b, 0x70, 0x69, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x3a, 0x20, 0x53, 0x65, 0x74, 0x73, 0x20, + 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x64, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x70, 0x69, + 0x6e, 0x2e, 0x20, 0x40, 0x70, 0x69, 0x6e, 0x3a, 0x20, 0x50, 0x69, 0x6e, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, + 0x72, 0x2c, 0x20, 0x40, 0x6d, 0x6f, 0x64, 0x65, 0x3a, 0x20, 0x4d, 0x6f, 0x64, 0x65, 0x20, 0x74, 0x79, 0x70, + 0x65, 0x2e, 0x00, 0x42, 0x3a, 0x20, 0x48, 0x3b, 0x64, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x52, 0x65, 0x61, + 0x64, 0x3a, 0x20, 0x52, 0x65, 0x61, 0x64, 0x20, 0x64, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x70, 0x69, + 0x6e, 0x2e, 0x20, 0x40, 0x70, 0x69, 0x6e, 0x3a, 0x20, 0x50, 0x69, 0x6e, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, + 0x72, 0x2e, 0x20, 0x40, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x3a, 0x20, 0x50, 0x69, 0x6e, 0x20, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x2e, 0x00, 0x3a, 0x20, 0x48, 0x20, 0x42, 0x3b, 0x64, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, + 0x57, 0x72, 0x69, 0x74, 0x65, 0x3a, 0x20, 0x57, 0x72, 0x69, 0x74, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, + 0x64, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x20, 0x70, 0x69, 0x6e, 0x2e, 0x20, 0x40, 0x70, 0x69, 0x6e, 0x3a, + 0x20, 0x50, 0x69, 0x6e, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x2e, 0x20, 0x40, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x20, 0x50, 0x69, 0x6e, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x00, 0x00}; + + ParserSettings settings; + settings.startMethods = ParserSettings::SimpleMethod(&HostedTest::startMethods, this); + settings.startMethod = ParserSettings::SimpleMethod(&HostedTest::startMethod, this); + settings.methodName = ParserSettings::CharMethod(&HostedTest::methodName, this); + settings.endMethod = ParserSettings::SimpleMethod(&HostedTest::endMethod, this); + settings.endMethods = ParserSettings::SimpleMethod(&HostedTest::endMethods, this); + settings.state = ParserState::ready; + + TEST_CASE("simpleRPC::parse()") + { + REQUIRE(parse(settings, packet, sizeof(packet)) == ParserResult::finished); + REQUIRE(commands.count() == 3); + REQUIRE(commands["digitalWrite"] == 2); + REQUIRE(commands["pinMode"] != 2); + REQUIRE(commands["pinMode"] == 0); + } + + if(!WifiStation.isConnected()) { + Serial.println("No network, skipping tests"); + return; + } + + // RPC Server + server = new TcpServer(); + server->listen(4031); + server->setTimeOut(USHRT_MAX); // disable connection timeout + server->setKeepAlive(USHRT_MAX); // disable connection timeout + + Hosted::Transport::TcpServerTransport transport(*server); + transport.onData([](Stream& stream) { + // clang-format off + interface(stream, + /* + * Below we are exporting the following remote commands: + * - pinMode + * - digitalRead + * - digitalWrite + * You can add more commands here. For every command you should specify command and text description in the format below. + * For more information read the SimpleRPC interface API: https://simplerpc.readthedocs.io/en/latest/api/interface.html + */ + pinMode, "pinMode: Sets mode of digital pin. @pin: Pin number, @mode: Mode type.", + digitalRead, "digitalRead: Read digital pin. @pin: Pin number. @return: Pin value.", + plusCommand, "plusCommand: Sum two numbers. @a: number one. @b: number two." + ); + // clang-format on + + return true; + }); + + // RPC Client + + client.connect(WifiStation.getIP(), 4031); + Hosted::Transport::TcpClientStream stream(client, 1024); + + Hosted::Client hostedClient(stream); + + TEST_CASE("Client::getRemoteCommands()") + { + REQUIRE(hostedClient.getRemoteCommands() == true); + REQUIRE(hostedClient.getFunctionId("plusCommand") == 2); + } + + TEST_CASE("Client::send and wait()") + { + ElapseTimer timer; + + REQUIRE(hostedClient.send("plusCommand", uint8_t(3), uint16_t(2)) == true); + REQUIRE(hostedClient.wait() == 5); + + debug_i("PlusCommand Roundtrip Time: %s", timer.elapsedTime().toString().c_str()); + } + } + +private: + RemoteCommands commands; + uint8_t methodPosition = 0; + String parsedCommand; + + TcpServer* server{nullptr}; + TcpClient client{false}; + Hosted::Transport::TcpClientStream* stream{nullptr}; + + void startMethods() + { + methodPosition = 0; + commands.clear(); + } + + void startMethod() + { + parsedCommand = ""; + } + + void methodName(char ch) + { + parsedCommand += ch; + } + + void endMethod() + { + commands[parsedCommand] = methodPosition++; + } + + void endMethods() + { + } +}; + +void REGISTER_TEST(Hosted) +{ + registerGroup(); +} diff --git a/tests/HostTests/Arch/Host/HttpRequest.cpp b/tests/HostTests/modules/Network/Arch/Host/HttpRequest.cpp similarity index 100% rename from tests/HostTests/Arch/Host/HttpRequest.cpp rename to tests/HostTests/modules/Network/Arch/Host/HttpRequest.cpp diff --git a/tests/HostTests/modules/Network/Arch/Host/TcpClient.cpp b/tests/HostTests/modules/Network/Arch/Host/TcpClient.cpp new file mode 100644 index 0000000000..0a9a9383ef --- /dev/null +++ b/tests/HostTests/modules/Network/Arch/Host/TcpClient.cpp @@ -0,0 +1,102 @@ +#include + +#include +#include +#include +#include + +class TcpClientTest : public TestGroup +{ +public: + TcpClientTest() : TestGroup(_F("TcpClient")) + { + } + + void execute() override + { + if(!WifiStation.isConnected()) { + Serial.println("No network, skipping tests"); + return; + } + + constexpr int port = 9876; + String inputData = "This is very long and complex text that will be sent using multiple complicated streams."; + + // Tcp Server + server = new TcpServer( + [this](TcpClient& client, char* data, int size) -> bool { + // on data + return receivedData.concat(data, size); + }, + [this, inputData](TcpClient& client, bool successful) { + // on client close + if(finished) { + return; + } + REQUIRE(successful == true); + REQUIRE(receivedData == inputData); + finished = true; + shutdown(); + }); + server->listen(port); + server->setTimeOut(USHRT_MAX); // disable connection timeout + server->setKeepAlive(USHRT_MAX); // disable connection timeout + + // Tcp Client + bool connected = client.connect(WifiStation.getIP(), port); + debug_d("Connected: %d", connected); + + TEST_CASE("TcpClient::send stream") + { + size_t offset = 0; + + // Send text using bytes + client.send(inputData.c_str(), 5); + offset += 5; + + // send data using more bytes + client.send(inputData.c_str() + offset, 7); + offset += 7; + + // send data as stream + auto stream1 = new MemoryDataStream(); + stream1->write(inputData.c_str() + offset, 3); + client.send(stream1); + offset += 3; + client.commit(); + + // more stream + auto stream2 = new LimitedMemoryStream(4); + stream2->write(reinterpret_cast(inputData.c_str()) + offset, 4); + client.send(stream2); + offset += 4; + + // and finally the rest of the bytes + String rest = inputData.substring(offset); + client.send(rest.c_str(), rest.length()); + client.setTimeOut(1); + + pending(); + } + } + + void shutdown() + { + server->shutdown(); + server = nullptr; + timer.initializeMs<1000>([this]() { complete(); }); + timer.startOnce(); + } + +private: + String receivedData; + TcpServer* server{nullptr}; + TcpClient client{false}; + Timer timer; + volatile bool finished = false; +}; + +void REGISTER_TEST(TcpClient) +{ + registerGroup(); +} diff --git a/tests/HostTests/modules/Base64.cpp b/tests/HostTests/modules/Network/Base64.cpp similarity index 80% rename from tests/HostTests/modules/Base64.cpp rename to tests/HostTests/modules/Network/Base64.cpp index 0c4cdd58b1..e97eee837e 100644 --- a/tests/HostTests/modules/Base64.cpp +++ b/tests/HostTests/modules/Network/Base64.cpp @@ -1,5 +1,7 @@ #include +#include +#include #include class Base64Test : public TestGroup @@ -10,6 +12,12 @@ class Base64Test : public TestGroup } void execute() override + { + libTests(); + streamTests(); + } + + void libTests() { String user("donkey"); String pass("kingpin"); @@ -69,6 +77,21 @@ class Base64Test : public TestGroup delete[] inbuf; } } + + void streamTests() + { + TEST_CASE("Base64OutputStream / StreamTransformer") + { + auto src = new FSTR::Stream(Resource::image_png); + Base64OutputStream base64stream(src); + MemoryDataStream output; + output.copyFrom(&base64stream); + String s; + REQUIRE(output.moveString(s)); + s = base64_decode(s); + REQUIRE(Resource::image_png == s); + } + } }; void REGISTER_TEST(Base64) diff --git a/tests/HostTests/modules/Http.cpp b/tests/HostTests/modules/Network/Http.cpp similarity index 100% rename from tests/HostTests/modules/Http.cpp rename to tests/HostTests/modules/Network/Http.cpp diff --git a/tests/HostTests/modules/Url.cpp b/tests/HostTests/modules/Network/Url.cpp similarity index 100% rename from tests/HostTests/modules/Url.cpp rename to tests/HostTests/modules/Network/Url.cpp diff --git a/tests/HostTests/modules/SpiFlash.cpp b/tests/HostTests/modules/SpiFlash.cpp index 210ab55a7f..827252553f 100644 --- a/tests/HostTests/modules/SpiFlash.cpp +++ b/tests/HostTests/modules/SpiFlash.cpp @@ -70,8 +70,16 @@ class SpiFlashTest : public TestGroup void execute() override { - TEST_CASE("Query Bootloader Info") + TEST_CASE("Query flash info") { + auto flash_id = spi_flash_get_id(); + REQUIRE_NEQ(flash_id, 0); + debug_i("flash_id = 0x%08x", flash_id); + + auto flash_size = flashmem_get_size_bytes(); + REQUIRE_NEQ(flash_size, 0); + debug_i("flash_size = 0x%08x bytes, %u MBytes", flash_size, flash_size / 0x100000); + auto info = flashmem_get_info(); auto modeStr = modeToString(SPIFlashMode(info.mode)); auto speedStr = speedToString(SPIFlashSpeed(info.speed)); diff --git a/tests/HostTests/modules/Stream.cpp b/tests/HostTests/modules/Stream.cpp index d77afc8f8e..cedb08312b 100644 --- a/tests/HostTests/modules/Stream.cpp +++ b/tests/HostTests/modules/Stream.cpp @@ -1,13 +1,16 @@ #include #include #include -#include -#include +#include #include #include #include #include +#ifndef DISABLE_NETWORK +#include +#endif + DEFINE_FSTR_LOCAL(template1, "Stream containing {var1}, {var2} and {var3}. {} {{}} {{12345") DEFINE_FSTR_LOCAL(template1_1, "Stream containing value #1, value #2 and {var3}. {} {{}} {{12345") DEFINE_FSTR_LOCAL(template1_2, "Stream containing value #1, value #2 and [value #3]. {} {{}} {{12345") @@ -80,16 +83,19 @@ class StreamTest : public TestGroup REQUIRE(strlen(s.c_str()) == s.length()); } - TEST_CASE("Base64OutputStream / StreamTransformer") +#ifndef DISABLE_NETWORK + + TEST_CASE("ChunkedStream / StreamTransformer") { - auto src = new FSTR::Stream(Resource::image_png); - Base64OutputStream base64stream(src); + DEFINE_FSTR_LOCAL(FS_INPUT, "Some test data"); + DEFINE_FSTR_LOCAL(FS_OUTPUT, "e\r\nSome test data\r\n0\r\n\r\n"); + ChunkedStream chunked(new FlashMemoryStream(FS_INPUT)); MemoryDataStream output; - output.copyFrom(&base64stream); + output.copyFrom(&chunked); String s; REQUIRE(output.moveString(s)); - s = base64_decode(s); - REQUIRE(Resource::image_png == s); + m_printHex("OUTPUT", s.c_str(), s.length()); + REQUIRE(FS_OUTPUT == s); } TEST_CASE("ChunkedStream / StreamTransformer") @@ -132,6 +138,7 @@ class StreamTest : public TestGroup REQUIRE(mem.moveString(s)); REQUIRE(Resource::multipart_result == s); } +#endif TEST_CASE("XorOutputStream") { @@ -191,7 +198,7 @@ class StreamTest : public TestGroup } for(unsigned i = 0; i < list.count(); i++) { - size_t bufferSize = 5; + constexpr size_t bufferSize{5}; char buffer[bufferSize]{}; auto element = list[i]; diff --git a/tests/HostTests/modules/String.cpp b/tests/HostTests/modules/String.cpp index adb9831b92..42d07457f7 100644 --- a/tests/HostTests/modules/String.cpp +++ b/tests/HostTests/modules/String.cpp @@ -102,6 +102,13 @@ class StringTest : public TestGroup REQUIRE(FS_Text4 == text); } + TEST_CASE("replace, increase length with first char (Bug 24/10/2021)") + { + String s = F("abcdefa"); + s.replace("a", "aa"); + REQUIRE(F("aabcdefaa") == s); + } + TEST_CASE("content check (manual inspection)") { DEFINE_FSTR_LOCAL(test, "This is a some test data \1\2\3 Not all ASCII\0" diff --git a/tests/HostTests/modules/System.cpp b/tests/HostTests/modules/System.cpp new file mode 100644 index 0000000000..23f6fac395 --- /dev/null +++ b/tests/HostTests/modules/System.cpp @@ -0,0 +1,78 @@ +#include +#include + +/* + * Various system functions must be available for all architectures. + */ +class SystemTest : public TestGroup +{ +public: + SystemTest() : TestGroup(_F("System")) + { + } + + void execute() override + { + TEST_CASE("Heap") + { + REQUIRE_NEQ(system_get_free_heap_size(), 0); + } + + TEST_CASE("Identification") + { + REQUIRE_NEQ(String(system_get_sdk_version()), nullptr); + + auto chip_id = system_get_chip_id(); + REQUIRE_NEQ(chip_id, 0); + debug_i("chip_id = 0x%08x", chip_id); + } + + TEST_CASE("Clocks") + { + debug_i("CPU running at %u MHz", System.getCpuFrequency()); + } + + TEST_CASE("Watchdog functions available") + { + system_soft_wdt_stop(); + system_soft_wdt_restart(); + system_soft_wdt_feed(); + } + +#ifndef ARCH_HOST + TEST_CASE("System restart") + { + auto info = system_get_rst_info(); + REQUIRE_NEQ(uint32_t(info), 0); + debug_i("Reason 0x%08x", info->reason); + + switch(info->reason) { + case REASON_DEFAULT_RST: + debug_i("Hanging to check watchdog reboots system...\n\n"); + for(;;) { + } + break; + + case REASON_SOFT_WDT_RST: + debug_i("Reset by watchdog, rebooting...\n\n"); + System.restart(1000); + pending(); + break; + + case REASON_SOFT_RESTART: + debug_i("Reset by software. Continuing...\n\n"); + break; + + default: + // Could be exception, deep sleep, etc. + debug_i("Restarted for some other reason...\n\n"); + } + } +#endif + } +}; + +void REGISTER_TEST(System) +{ + registerGroup(); +} diff --git a/tests/HostTests/modules/TemplateStream.cpp b/tests/HostTests/modules/TemplateStream.cpp index f98d145ccc..eb618e0625 100644 --- a/tests/HostTests/modules/TemplateStream.cpp +++ b/tests/HostTests/modules/TemplateStream.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #ifdef ARCH_HOST #include @@ -16,6 +17,18 @@ DEFINE_FSTR_LOCAL(template1_2, "Stream containing value #1, value #2 and [value DEFINE_FSTR_LOCAL(template2, "This text should {disable}not {var1} really {var2:hello} again {enable}be missing.") DEFINE_FSTR_LOCAL(template2_1, "This text should be missing.") +DEFINE_FSTR_LOCAL(template3, "{title}
    0..255- the value is very dependent on the LCD. However, BACKLIGHT_OFF will be interpreted as off and BACKLIGHT_ON will drive the backlight on.
    {$record}{file_id}{icon} {name}{!mime_type:name}{modified}