├── debug.txt ├── sample_lib ├── folder1 │ ├── file1.c │ └── Makefile ├── folder2 │ ├── file2.c │ └── Makefile └── Makefile ├── .gitignore ├── include ├── driver ├── esphttpd ├── sdio_slv.h ├── user_config.h └── i2s_reg.h ├── libesphttpd ├── mkupgimg │ ├── Makefile │ └── mkupgimg.c ├── include │ ├── user_config.h │ ├── captdns.h │ ├── webpages-espfs.h │ ├── httpdespfs.h │ ├── cgiwifi.h │ ├── cgiflash.h │ ├── auth.h │ ├── espfs.h │ ├── esp8266.h │ ├── sha1.h │ ├── cgiwebsocket.h │ ├── platform.h │ ├── espmissingincludes.h │ └── httpd.h ├── espfs │ ├── mkespfsimage │ │ ├── heatshrink_encoder.c │ │ ├── Makefile │ │ └── main.c │ ├── espfstest │ │ ├── Makefile │ │ └── main.c │ ├── heatshrink_decoder.c │ ├── heatshrink_config_custom.h │ ├── espfsformat.h │ └── espfs.c ├── webpages.espfs.ld ├── core │ ├── base64.h │ ├── httpd-platform.h │ ├── auth.c │ ├── httpd-nonos.c │ ├── base64.c │ ├── sha1.c │ ├── httpdespfs.c │ └── httpd-freertos.c ├── lib │ └── heatshrink │ │ ├── heatshrink_common.h │ │ ├── LICENSE │ │ ├── heatshrink_config.h │ │ ├── Makefile │ │ ├── enc_sm.dot │ │ ├── README.md │ │ ├── dec_sm.dot │ │ ├── heatshrink_encoder.h │ │ ├── heatshrink_decoder.h │ │ └── test_heatshrink_static.c ├── Makefile └── util │ └── cgiflash.c ├── esphttpdconfig.mk ├── setenv ├── user ├── cgi-test.h ├── reprap_core.h ├── sigmadelta.h ├── maskedtransportdelay.h ├── buffered_sw_pwm.h ├── Makefile ├── stepper.h ├── cgi-test.c ├── reprap_core.cpp ├── throttle.h └── user_main.cpp ├── driver_lib ├── include │ ├── i2s_freertos.h │ ├── hw_timer.h │ ├── uart.h │ └── gpio.h ├── Makefile ├── hw_timer.c └── gpio.c ├── other_tools └── cppchk.sh ├── README.md ├── html ├── echo_controller.js ├── index.html └── bhaskara_controller.js ├── flash ├── Makefile ├── gen_misc.bat └── gen_misc.sh /debug.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sample_lib/folder1/file1.c: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /sample_lib/folder2/file2.c: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/.output 2 | bin/* 3 | -------------------------------------------------------------------------------- /include/driver: -------------------------------------------------------------------------------- 1 | ../driver_lib/include/ -------------------------------------------------------------------------------- /include/esphttpd: -------------------------------------------------------------------------------- 1 | ../libesphttpd/include/ -------------------------------------------------------------------------------- /libesphttpd/mkupgimg/Makefile: -------------------------------------------------------------------------------- 1 | mkupgimg: mkupgimg.c 2 | $(CC) -o $@ $^ 3 | 4 | clean: 5 | rm -f mkupgimg 6 | -------------------------------------------------------------------------------- /libesphttpd/include/user_config.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | 5 | 6 | #ifdef __cplusplus 7 | } 8 | #endif 9 | -------------------------------------------------------------------------------- /esphttpdconfig.mk: -------------------------------------------------------------------------------- 1 | SDK_BASE ?= /opt/espressif/ESP8266_NONOS_SDK_V1.5.4 2 | SDK_PATH ?= /opt/espressif/ESP8266_RTOS_SDK 3 | FREERTOS ?= yes 4 | HTTPD_MAX_CONNECTIONS ?= 16 5 | -------------------------------------------------------------------------------- /setenv: -------------------------------------------------------------------------------- 1 | export PATH=/opt/espressif/xtensa-lx106-elf/bin:/opr/espressif/esptool:$PATH 2 | export SDK_PATH=/opt/espressif/ESP8266_RTOS_SDK_CPP/ 3 | export ESPTOOL=/opt/espressif/esptool/esptool.py 4 | export BIN_PATH=$PWD/bin/ 5 | -------------------------------------------------------------------------------- /libesphttpd/espfs/mkespfsimage/heatshrink_encoder.c: -------------------------------------------------------------------------------- 1 | //Stupid wraparound include to make sure object file doesn't end up in heatshrink dir 2 | #ifdef ESPFS_HEATSHRINK 3 | #include "../lib/heatshrink/heatshrink_encoder.c" 4 | #endif -------------------------------------------------------------------------------- /libesphttpd/include/captdns.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | #ifndef CAPTDNS_H 5 | #define CAPTDNS_H 6 | void ICACHE_FLASH_ATTR captdnsInit(void); 7 | 8 | #endif 9 | #ifdef __cplusplus 10 | } 11 | #endif 12 | -------------------------------------------------------------------------------- /libesphttpd/include/webpages-espfs.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | extern char webpages_espfs_start[]; 5 | extern char webpages_espfs_end[]; 6 | extern int webpages_espfs_size; 7 | 8 | #ifdef __cplusplus 9 | } 10 | #endif 11 | -------------------------------------------------------------------------------- /user/cgi-test.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | #ifndef CGI_TEST_H 5 | #define CGI_TEST_H 6 | 7 | #include 8 | 9 | int cgiTestbed(HttpdConnData *connData); 10 | 11 | #endif 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | -------------------------------------------------------------------------------- /user/reprap_core.h: -------------------------------------------------------------------------------- 1 | #ifndef REPRAP_CORE_H 2 | #define REPRAP_CORE_H 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | void reprap_core_task(void *nada); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /libesphttpd/webpages.espfs.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT("elf32-xtensa-le") 2 | 3 | 4 | SECTIONS 5 | { 6 | .irom0.literal : ALIGN(4) SUBALIGN(4) { 7 | webpages_espfs_start = .; 8 | *(*) 9 | webpages_espfs_end = .; 10 | webpages_espfs_size = webpages_espfs_end - webpages_espfs_start; 11 | } 12 | } -------------------------------------------------------------------------------- /libesphttpd/include/httpdespfs.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | #ifndef HTTPDESPFS_H 5 | #define HTTPDESPFS_H 6 | 7 | #include "httpd.h" 8 | 9 | int cgiEspFsHook(HttpdConnData *connData); 10 | int ICACHE_FLASH_ATTR cgiEspFsTemplate(HttpdConnData *connData); 11 | 12 | #endif 13 | #ifdef __cplusplus 14 | } 15 | #endif 16 | -------------------------------------------------------------------------------- /libesphttpd/core/base64.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | #ifndef BASE64_H 5 | #define BASE64_H 6 | 7 | int base64_decode(size_t in_len, const char *in, size_t out_len, unsigned char *out); 8 | int base64_encode(size_t in_len, const unsigned char *in, size_t out_len, char *out); 9 | #endif 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | -------------------------------------------------------------------------------- /libesphttpd/espfs/espfstest/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-I../../lib/heatshrink -I.. -std=gnu99 -DESPFS_HEATSHRINK 2 | 3 | espfstest: main.o espfs.o heatshrink_decoder.o 4 | $(CC) -o $@ $^ 5 | 6 | espfs.o: ../espfs.c 7 | $(CC) $(CFLAGS) -c $^ -o $@ 8 | 9 | heatshrink_decoder.o: ../heatshrink_decoder.c 10 | $(CC) $(CFLAGS) -c $^ -o $@ 11 | 12 | clean: 13 | rm -f *.o espfstest 14 | -------------------------------------------------------------------------------- /libesphttpd/espfs/heatshrink_decoder.c: -------------------------------------------------------------------------------- 1 | #include "espfs.h" 2 | #ifdef ESPFS_HEATSHRINK 3 | //Stupid wrapper so we don't have to move c-files around 4 | //Also loads httpd-specific config. 5 | 6 | #ifdef __ets__ 7 | //esp build 8 | 9 | #include 10 | 11 | #endif 12 | 13 | #include "heatshrink_config_custom.h" 14 | #include "../lib/heatshrink/heatshrink_decoder.c" 15 | 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /libesphttpd/core/httpd-platform.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | #ifndef HTTPD_PLATFORM_H 5 | #define HTTPD_PLATFORM_H 6 | 7 | int httpdPlatSendData(ConnTypePtr conn, char *buff, int len); 8 | void httpdPlatDisconnect(ConnTypePtr conn); 9 | void httpdPlatDisableTimeout(ConnTypePtr conn); 10 | void httpdPlatInit(int port, int maxConnCt); 11 | void httpdPlatLock(); 12 | void httpdPlatUnlock(); 13 | 14 | #endif 15 | #ifdef __cplusplus 16 | } 17 | #endif 18 | -------------------------------------------------------------------------------- /libesphttpd/include/cgiwifi.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | #ifndef CGIWIFI_H 5 | #define CGIWIFI_H 6 | 7 | #include "httpd.h" 8 | 9 | int cgiWiFiScan(HttpdConnData *connData); 10 | int tplWlan(HttpdConnData *connData, char *token, void **arg); 11 | int cgiWiFi(HttpdConnData *connData); 12 | int cgiWiFiConnect(HttpdConnData *connData); 13 | int cgiWiFiSetMode(HttpdConnData *connData); 14 | int cgiWiFiConnStatus(HttpdConnData *connData); 15 | 16 | #endif 17 | #ifdef __cplusplus 18 | } 19 | #endif 20 | -------------------------------------------------------------------------------- /user/sigmadelta.h: -------------------------------------------------------------------------------- 1 | #ifndef SIGMADELTA_H 2 | #define SIGMADELTA_H 3 | 4 | #include 5 | 6 | class SigmaDeltaModulator { 7 | uint32_t d, T; 8 | int32_t acc; 9 | public: 10 | void set(uint32_t duty, uint32_t period) { 11 | d = duty; 12 | T = period; 13 | } 14 | 15 | bool step() { 16 | acc += d; 17 | if (acc > 0) { 18 | acc -= T; 19 | return true; 20 | } 21 | return false; 22 | } 23 | }; 24 | 25 | #endif // SIGMADELTA_H 26 | 27 | -------------------------------------------------------------------------------- /libesphttpd/espfs/mkespfsimage/Makefile: -------------------------------------------------------------------------------- 1 | GZIP_COMPRESSION ?= no 2 | USE_HEATSHRINK ?= yes 3 | 4 | CFLAGS=-I../../lib/heatshrink -I../../include -I.. -std=gnu99 5 | ifeq ("$(GZIP_COMPRESSION)","yes") 6 | CFLAGS += -DESPFS_GZIP 7 | endif 8 | 9 | ifeq ("$(USE_HEATSHRINK)","yes") 10 | CFLAGS += -DESPFS_HEATSHRINK 11 | endif 12 | 13 | OBJS=main.o heatshrink_encoder.o 14 | TARGET=mkespfsimage 15 | 16 | $(TARGET): $(OBJS) 17 | ifeq ("$(GZIP_COMPRESSION)","yes") 18 | $(CC) -o $@ $^ -lz 19 | else 20 | $(CC) -o $@ $^ 21 | endif 22 | 23 | clean: 24 | rm -f $(TARGET) $(OBJS) -------------------------------------------------------------------------------- /libesphttpd/include/cgiflash.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | #ifndef CGIFLASH_H 5 | #define CGIFLASH_H 6 | 7 | #include "httpd.h" 8 | 9 | #define CGIFLASH_TYPE_FW 0 10 | #define CGIFLASH_TYPE_ESPFS 1 11 | 12 | typedef struct { 13 | int type; 14 | int fw1Pos; 15 | int fw2Pos; 16 | int fwSize; 17 | char *tagName; 18 | } CgiUploadFlashDef; 19 | 20 | int cgiGetFirmwareNext(HttpdConnData *connData); 21 | int cgiUploadFirmware(HttpdConnData *connData); 22 | int cgiRebootFirmware(HttpdConnData *connData); 23 | 24 | #endif 25 | 26 | #ifdef __cplusplus 27 | } 28 | #endif 29 | -------------------------------------------------------------------------------- /driver_lib/include/i2s_freertos.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | #ifndef _I2S_FREERTOS_H_ 5 | #define _I2S_FREERTOS_H_ 6 | 7 | //Parameters for the I2S DMA behaviour 8 | #define I2SDMABUFCNT (14) //Number of buffers in the I2S circular buffer 9 | #define I2SDMABUFLEN (32*2) //Length of one buffer, in 32-bit words. 10 | 11 | 12 | void ICACHE_FLASH_ATTR i2sInit(); 13 | void i2sSetRate(int rate, int lockBitcount); 14 | void i2sPushSample(unsigned int sample); 15 | uint32_t *i2sGetBuffer(); 16 | long ICACHE_FLASH_ATTR i2sGetUnderrunCnt(); 17 | 18 | 19 | #endif 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | -------------------------------------------------------------------------------- /other_tools/cppchk.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | fix="false" 3 | [ "$1" == "--fix" ] && fix="true" 4 | 5 | find . -iname "*.h" | while read F; do 6 | grep -q "extern \"C\"" "$F" \ 7 | && echo "$F is ok." \ 8 | || { 9 | echo -n "$F is missing C++ protection" 10 | if $fix; then 11 | echo ", adding..." 12 | 13 | DATA="$( 14 | echo "#ifdef __cplusplus" 15 | echo "extern \"C\" {" 16 | echo "#endif" 17 | 18 | cat "$F" 19 | 20 | echo "" 21 | echo "#ifdef __cplusplus" 22 | echo "}" 23 | echo "#endif" 24 | )" 25 | 26 | echo "$DATA" > "$F" 27 | else 28 | echo "." 29 | fi 30 | } 31 | done 32 | -------------------------------------------------------------------------------- /libesphttpd/include/auth.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | #ifndef AUTH_H 5 | #define AUTH_H 6 | 7 | #include "httpd.h" 8 | 9 | #ifndef HTTP_AUTH_REALM 10 | #define HTTP_AUTH_REALM "Protected" 11 | #endif 12 | 13 | #define HTTPD_AUTH_SINGLE 0 14 | #define HTTPD_AUTH_CALLBACK 1 15 | 16 | #define AUTH_MAX_USER_LEN 32 17 | #define AUTH_MAX_PASS_LEN 32 18 | 19 | //Parameter given to authWhatever functions. This callback returns the usernames/passwords the device 20 | //has. 21 | typedef int (* AuthGetUserPw)(HttpdConnData *connData, int no, char *user, int userLen, char *pass, int passLen); 22 | 23 | int ICACHE_FLASH_ATTR authBasic(HttpdConnData *connData); 24 | 25 | #endif 26 | #ifdef __cplusplus 27 | } 28 | #endif 29 | -------------------------------------------------------------------------------- /libesphttpd/lib/heatshrink/heatshrink_common.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | #ifndef HEATSHRINK_H 5 | #define HEATSHRINK_H 6 | 7 | #define HEATSHRINK_AUTHOR "Scott Vokes " 8 | #define HEATSHRINK_URL "https://github.com/atomicobject/heatshrink" 9 | 10 | /* Version 0.3.1 */ 11 | #define HEATSHRINK_VERSION_MAJOR 0 12 | #define HEATSHRINK_VERSION_MINOR 3 13 | #define HEATSHRINK_VERSION_PATCH 1 14 | 15 | #define HEATSHRINK_MIN_WINDOW_BITS 4 16 | #define HEATSHRINK_MAX_WINDOW_BITS 15 17 | 18 | #define HEATSHRINK_MIN_LOOKAHEAD_BITS 2 19 | 20 | #define HEATSHRINK_LITERAL_MARKER 0x01 21 | #define HEATSHRINK_BACKREF_MARKER 0x00 22 | 23 | #endif 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | -------------------------------------------------------------------------------- /libesphttpd/include/espfs.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | #ifndef ESPFS_H 5 | #define ESPFS_H 6 | 7 | // This define is done in Makefile. If you do not use default Makefile, uncomment 8 | // to be able to use Heatshrink-compressed espfs images. 9 | //#define ESPFS_HEATSHRINK 10 | 11 | typedef enum { 12 | ESPFS_INIT_RESULT_OK, 13 | ESPFS_INIT_RESULT_NO_IMAGE, 14 | ESPFS_INIT_RESULT_BAD_ALIGN, 15 | } EspFsInitResult; 16 | 17 | typedef struct EspFsFile EspFsFile; 18 | 19 | EspFsInitResult espFsInit(void *flashAddress); 20 | EspFsFile *espFsOpen(char *fileName); 21 | int espFsFlags(EspFsFile *fh); 22 | int espFsRead(EspFsFile *fh, char *buff, int len); 23 | void espFsClose(EspFsFile *fh); 24 | 25 | 26 | #endif 27 | #ifdef __cplusplus 28 | } 29 | #endif 30 | -------------------------------------------------------------------------------- /user/maskedtransportdelay.h: -------------------------------------------------------------------------------- 1 | #ifndef TRANSPORTDELAY_H 2 | #define TRANSPORTDELAY_H 3 | 4 | /// Transport delay buffer for selected bits of integgers. 5 | /** @param T type of data in the buffer. 6 | * @param N number os samples todelay. 7 | * @param M bitmask selecting which bits will be delayed. Set=delayed. 8 | */ 9 | template class MaskedTransportDelay { 10 | T buff[N]; //!< Delay buffer 11 | T *p; //!< Current sample pointer 12 | 13 | public: 14 | MaskedTransportDelay() : p(buff+N) {} 15 | T operator() (T x) { 16 | // Advance pointer 17 | if (p == buff) p += N-1; 18 | else p--; 19 | 20 | // Exchange data 21 | T y = *p; 22 | *p = x; 23 | 24 | return y & M | x & ~M; 25 | } 26 | }; 27 | 28 | #endif // TRANSPORTDELAY_H 29 | 30 | -------------------------------------------------------------------------------- /libesphttpd/include/esp8266.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | // Combined include file for esp8266 5 | // Actually misnamed, as it also works for ESP32. 6 | // ToDo: Figure out better name 7 | 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #ifdef FREERTOS 15 | #include 16 | 17 | #ifdef ESP32 18 | #include 19 | #else 20 | #include 21 | #endif 22 | 23 | #else 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #endif 36 | 37 | #include "platform.h" 38 | #include "espmissingincludes.h" 39 | 40 | 41 | #ifdef __cplusplus 42 | } 43 | #endif 44 | -------------------------------------------------------------------------------- /libesphttpd/lib/heatshrink/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Scott Vokes 2 | All rights reserved. 3 | 4 | Permission to use, copy, modify, and/or distribute this software for any 5 | purpose with or without fee is hereby granted, provided that the above 6 | copyright notice and this permission notice appear in all copies. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ESP_RTOS_REPRAP 2 | =============== 3 | 4 | A proof of concept: ESP8266 alone is more than enough to run steppers, servos and PWMs. There is no need for an auxiliary, slow, ATMEGA. 5 | 6 | [Youtube](https://www.youtube.com/watch?v=tURU9UKbYXw) video of it in action. 7 | [RepRap Forum](http://forums.reprap.org/read.php?2,594898) discussion. 8 | 9 | Setting Up 10 | ---------- 11 | 12 | 1. You will need a linux machine. 13 | 2. Clone this repository, then create an empty bin directory. 14 | 3. Follow the remaining instructions [here](https://github.com/lhartmann/esp_rtos_zero). 15 | 16 | Hardware 17 | -------- 18 | 19 | * A breakout for ESP8266 that includes I2S pins. I used NodeMCU, ESP12 would do, ESP01 would not. 20 | * 32-bit buffered output shift register: [Shift-out-32-HC595](https://github.com/lhartmann/Shift-out-32-HC595). 21 | * A4988 or DRV8833 stepper drivers. 22 | -------------------------------------------------------------------------------- /user/buffered_sw_pwm.h: -------------------------------------------------------------------------------- 1 | #ifndef BUFFERED_SW_PWM_H 2 | #define BUFFERED_SW_PWM_H 3 | 4 | #include 5 | 6 | class BufferedSoftwarePwm { 7 | uint32_t d, T; 8 | 9 | uint32_t i; 10 | 11 | uint32_t bd, bT; 12 | public: 13 | 14 | void set(uint32_t duty, uint32_t period) { 15 | // Begin crytical section 16 | bd = duty; 17 | bT = period; 18 | // End crytical section 19 | } 20 | void setPeriod(uint32_t period) { 21 | set(bd, period); 22 | } 23 | void setDuty(uint32_t duty) { 24 | set(duty, bT); 25 | } 26 | 27 | bool step() { 28 | if (++i == T) { 29 | d = bd; 30 | T = bT; 31 | i = 0; 32 | } 33 | return i < d; 34 | } 35 | 36 | bool period_completed() const { 37 | return i == 0; 38 | } 39 | }; 40 | 41 | #endif // BUFFERED_SW_PWM_H 42 | 43 | -------------------------------------------------------------------------------- /libesphttpd/lib/heatshrink/heatshrink_config.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | #ifndef HEATSHRINK_CONFIG_H 5 | #define HEATSHRINK_CONFIG_H 6 | 7 | /* Should functionality assuming dynamic allocation be used? */ 8 | #define HEATSHRINK_DYNAMIC_ALLOC 1 9 | 10 | #if HEATSHRINK_DYNAMIC_ALLOC 11 | /* Optional replacement of malloc/free */ 12 | #define HEATSHRINK_MALLOC(SZ) malloc(SZ) 13 | #define HEATSHRINK_FREE(P, SZ) free(P) 14 | #else 15 | /* Required parameters for static configuration */ 16 | #define HEATSHRINK_STATIC_INPUT_BUFFER_SIZE 32 17 | #define HEATSHRINK_STATIC_WINDOW_BITS 8 18 | #define HEATSHRINK_STATIC_LOOKAHEAD_BITS 4 19 | #endif 20 | 21 | /* Turn on logging for debugging. */ 22 | #define HEATSHRINK_DEBUGGING_LOGS 0 23 | 24 | /* Use indexing for faster compression. (This requires additional space.) */ 25 | #define HEATSHRINK_USE_INDEX 1 26 | 27 | #endif 28 | 29 | #ifdef __cplusplus 30 | } 31 | #endif 32 | -------------------------------------------------------------------------------- /libesphttpd/include/sha1.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | /* header */ 5 | 6 | #ifndef __SHA1_H__ 7 | #define __SHA1_H__ 8 | 9 | #define HASH_LENGTH 20 10 | #define BLOCK_LENGTH 64 11 | 12 | typedef struct sha1nfo { 13 | uint32_t buffer[BLOCK_LENGTH/4]; 14 | uint32_t state[HASH_LENGTH/4]; 15 | uint32_t byteCount; 16 | uint8_t bufferOffset; 17 | uint8_t keyBuffer[BLOCK_LENGTH]; 18 | uint8_t innerHash[HASH_LENGTH]; 19 | } sha1nfo; 20 | 21 | /* public API - prototypes - TODO: doxygen*/ 22 | 23 | /** 24 | */ 25 | void sha1_init(sha1nfo *s); 26 | /** 27 | */ 28 | void sha1_writebyte(sha1nfo *s, uint8_t data); 29 | /** 30 | */ 31 | void sha1_write(sha1nfo *s, const char *data, size_t len); 32 | /** 33 | */ 34 | uint8_t* sha1_result(sha1nfo *s); 35 | /** 36 | */ 37 | void sha1_initHmac(sha1nfo *s, const uint8_t* key, int keyLength); 38 | /** 39 | */ 40 | uint8_t* sha1_resultHmac(sha1nfo *s); 41 | 42 | #endif 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif 47 | -------------------------------------------------------------------------------- /libesphttpd/espfs/heatshrink_config_custom.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | //Heatshrink config for the decompressor. 5 | #ifndef HEATSHRINK_CONFIG_H 6 | #define HEATSHRINK_CONFIG_H 7 | 8 | /* Should functionality assuming dynamic allocation be used? */ 9 | #define HEATSHRINK_DYNAMIC_ALLOC 1 10 | 11 | #if HEATSHRINK_DYNAMIC_ALLOC 12 | /* Optional replacement of malloc/free */ 13 | #define HEATSHRINK_MALLOC(SZ) malloc(SZ) 14 | #define HEATSHRINK_FREE(P, SZ) free(P) 15 | #else 16 | /* Required parameters for static configuration */ 17 | #define HEATSHRINK_STATIC_INPUT_BUFFER_SIZE 32 18 | #define HEATSHRINK_STATIC_WINDOW_BITS 8 19 | #define HEATSHRINK_STATIC_LOOKAHEAD_BITS 4 20 | #endif 21 | 22 | /* Turn on logging for debugging. */ 23 | #define HEATSHRINK_DEBUGGING_LOGS 0 24 | 25 | /* Use indexing for faster compression. (This requires additional space.) */ 26 | #define HEATSHRINK_USE_INDEX 1 27 | 28 | #endif 29 | 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | -------------------------------------------------------------------------------- /html/echo_controller.js: -------------------------------------------------------------------------------- 1 | function EchoController($scope) { 2 | $scope.messageCount = 0; 3 | $scope.log = new Array(); 4 | 5 | function logPrint(msg) { 6 | var entry = { 7 | time: Date(), 8 | text: msg 9 | }; 10 | 11 | $scope.log.splice(0, 0, entry); 12 | 13 | if ($scope.log.length > 100) 14 | $scope.log.splice(100, $scope.log.length - 100); 15 | } 16 | 17 | logPrint("Started."); 18 | 19 | var ws = new WebSocket('ws://192.168.1.98/websocket/echo.cgi', ['soap', 'xmpp']); 20 | 21 | ws.onopen = function(e) { 22 | logPrint("Connection successful."); 23 | $scope.$apply(); 24 | } 25 | 26 | ws.onerror = function(e) { 27 | logPrint("Connection failed."); 28 | $scope.$apply(); 29 | } 30 | 31 | ws.onmessage = function(e) { 32 | $scope.messageCount++; 33 | logPrint("Got: "+e.data); 34 | $scope.$apply(); 35 | } 36 | 37 | document.getElementById("frmMessage").onsubmit = function() { 38 | ws.send($scope.message); 39 | logPrint("Sent: "+$scope.message); 40 | $scope.message = ""; 41 | $scope.$apply(); 42 | return false; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /flash: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | [ -n "$1" ] && ESPPORT="$1" 3 | 4 | if [ -z "$ESPPORT" ]; then 5 | ESPPORT=() 6 | 7 | # Find out what port is the NodeMCU by looking for CH341. 8 | for i in /sys/class/tty/ttyUSB*/device/driver; do 9 | DRIVER="$(basename "$(readlink $i)")" 10 | if [ "$DRIVER" == "ch341-uart" ]; then 11 | ESPPORT[${#ESPPORT[@]}]=$(echo $i | grep -o ttyUSB.) 12 | fi 13 | done 14 | 15 | if [ "${#ESPPORT[@]}" -gt 1 ]; then 16 | echo "Multiple CH341 ports detected, please choose one or set ESPPORT before running this script." 17 | select i in "${ESPPORT[@]}"; do 18 | ESPPORT="/$i" 19 | break 20 | done 21 | fi 22 | 23 | if [ -z "$ESPPORT" ]; then 24 | echo "Failed to find any CH341 usb-serial ports." 25 | echo "Please set ESPPORT to /dev/something or run:" 26 | echo "$0 " 27 | exit 1 28 | fi 29 | 30 | ESPPORT="/dev/$ESPPORT" 31 | fi 32 | 33 | $ESPTOOL \ 34 | --port $ESPPORT --baud 230400 \ 35 | write_flash \ 36 | --flash_freq 40m \ 37 | --flash_mode qio \ 38 | --flash_size 32m \ 39 | 0x00000 $BIN_PATH/eagle.flash.bin \ 40 | 0x20000 $BIN_PATH/eagle.irom0text.bin 41 | -------------------------------------------------------------------------------- /libesphttpd/espfs/espfsformat.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | #ifndef ESPROFSFORMAT_H 5 | #define ESPROFSFORMAT_H 6 | 7 | /* 8 | Stupid cpio-like tool to make read-only 'filesystems' that live on the flash SPI chip of the module. 9 | Can (will) use lzf compression (when I come around to it) to make shit quicker. Aligns names, files, 10 | headers on 4-byte boundaries so the SPI abstraction hardware in the ESP8266 doesn't crap on itself 11 | when trying to do a <4byte or unaligned read. 12 | */ 13 | 14 | /* 15 | The idea 'borrows' from cpio: it's basically a concatenation of {header, filename, file} data. 16 | Header, filename and file data is 32-bit aligned. The last file is indicated by data-less header 17 | with the FLAG_LASTFILE flag set. 18 | */ 19 | 20 | 21 | #define FLAG_LASTFILE (1<<0) 22 | #define FLAG_GZIP (1<<1) 23 | #define COMPRESS_NONE 0 24 | #define COMPRESS_HEATSHRINK 1 25 | #define ESPFS_MAGIC 0x73665345 26 | 27 | typedef struct { 28 | int32_t magic; 29 | int8_t flags; 30 | int8_t compression; 31 | int16_t nameLen; 32 | int32_t fileLenComp; 33 | int32_t fileLenDecomp; 34 | } __attribute__((packed)) EspFsHeader; 35 | 36 | #endif 37 | #ifdef __cplusplus 38 | } 39 | #endif 40 | -------------------------------------------------------------------------------- /html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Websocket Test 4 | 5 | 6 | 7 |
8 |

Remote Bhaskara Test

9 |
10 |

For a*x^2 + b*x + c = 0, enter:

11 |

a :

12 |

b :

13 |

c :

14 |

15 |

{{a}} x^2 + {{b}} x + {{c}} = 0

16 |

x1={{firstValidRoot}}, x2={{secondValidRoot}}

17 |
18 |
19 | 20 | 21 |
22 |

Websocket Echo Test

23 | 24 |
25 |

Enter message:

26 |

Total messages sent: {{messageCount}}

27 |
28 | 29 | 30 | 31 | 32 | 33 | 34 |
{{entry.time}}{{entry.text}}
35 |
36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /libesphttpd/include/cgiwebsocket.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | #ifndef CGIWEBSOCKET_H 5 | #define CGIWEBSOCKET_H 6 | 7 | #include "httpd.h" 8 | 9 | #define WEBSOCK_FLAG_NONE 0 10 | #define WEBSOCK_FLAG_CONT (1<<0) //Set if the data is not the final data in the message; more follows 11 | #define WEBSOCK_FLAG_BIN (1<<1) //Set if the data is binary instead of text 12 | 13 | 14 | 15 | typedef struct Websock Websock; 16 | typedef struct WebsockPriv WebsockPriv; 17 | 18 | typedef void(*WsConnectedCb)(Websock *ws); 19 | typedef void(*WsRecvCb)(Websock *ws, char *data, int len, int flags); 20 | typedef void(*WsSentCb)(Websock *ws); 21 | typedef void(*WsCloseCb)(Websock *ws); 22 | 23 | struct Websock { 24 | void *userData; 25 | HttpdConnData *conn; 26 | uint8_t status; 27 | WsRecvCb recvCb; 28 | WsSentCb sentCb; 29 | WsCloseCb closeCb; 30 | WebsockPriv *priv; 31 | }; 32 | 33 | int ICACHE_FLASH_ATTR cgiWebsocket(HttpdConnData *connData); 34 | int ICACHE_FLASH_ATTR cgiWebsocketSend(Websock *ws, char *data, int len, int flags); 35 | void ICACHE_FLASH_ATTR cgiWebsocketClose(Websock *ws, int reason); 36 | int ICACHE_FLASH_ATTR cgiWebSocketRecv(HttpdConnData *connData, char *data, int len); 37 | int ICACHE_FLASH_ATTR cgiWebsockBroadcast(char *resource, char *data, int len, int flags); 38 | 39 | 40 | #endif 41 | #ifdef __cplusplus 42 | } 43 | #endif 44 | -------------------------------------------------------------------------------- /libesphttpd/include/platform.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | #ifndef PLATFORM_H 5 | #define PLATFORM_H 6 | 7 | #ifdef FREERTOS 8 | //#include "esp_timer.h" 9 | typedef struct RtosConnType RtosConnType; 10 | typedef RtosConnType* ConnTypePtr; 11 | #if 0 12 | //Unfortunately, this does not always work... the latest esp32 sdk, for example, breaks this. 13 | #define httpd_printf(fmt, ...) do { \ 14 | static const char flash_str[] ICACHE_RODATA_ATTR STORE_ATTR = fmt; \ 15 | printf(flash_str, ##__VA_ARGS__); \ 16 | } while(0) 17 | #else 18 | #define httpd_printf(fmt, ...) os_printf(fmt, ##__VA_ARGS__) 19 | #endif 20 | #else 21 | #define printf(...) os_printf(__VA_ARGS__) 22 | #define sprintf(str, ...) os_sprintf(str, __VA_ARGS__) 23 | #define strcpy(a, b) os_strcpy(a, b) 24 | #define strncpy(a, b, c) os_strncpy(a, b, c) 25 | #define strcmp(a, b) os_strcmp(a, b) 26 | #define strncmp(a, b, c) os_strncmp(a, b, c) 27 | #define malloc(x) os_malloc(x) 28 | #define free(x) os_free(x) 29 | #define memset(x, a, b) os_memset(x, a, b) 30 | #define memcpy(x, a, b) os_memcpy(x, a, b) 31 | #define strcat(a, b) os_strcat(a, b) 32 | #define strstr(a, b) os_strstr(a, b) 33 | #define strlen(a) os_strlen(a) 34 | #define memcmp(a, b, c) os_memcmp(a, b, c) 35 | typedef struct espconn* ConnTypePtr; 36 | #define httpd_printf(format, ...) os_printf(format, ##__VA_ARGS__) 37 | #endif 38 | 39 | 40 | 41 | #endif 42 | #ifdef __cplusplus 43 | } 44 | #endif 45 | -------------------------------------------------------------------------------- /html/bhaskara_controller.js: -------------------------------------------------------------------------------- 1 | function BhaskaraController($scope) { 2 | $scope.firstValidRoot = 0; 3 | $scope.secondValidRoot = 0; 4 | 5 | console.log("BHWS: Starting setup..."); 6 | 7 | var ws = new WebSocket('ws://192.168.1.98/websocket/bhaskara.cgi', ['soap', 'xmpp']); 8 | 9 | ws.onopen = function(e) { 10 | } 11 | 12 | ws.onerror = function(e) { 13 | } 14 | 15 | ws.onmessage = function(e) { 16 | console.log("BHWS: Got response: ", e); 17 | var data = JSON.parse(e.data); 18 | 19 | if (data && data.isComplex) { 20 | $scope.firstValidRoot = data.real + "+" + data.imag + "i"; 21 | $scope.secondValidRoot = data.real + "-" + data.imag + "i"; 22 | } else { 23 | $scope.firstValidRoot = data.x1; 24 | $scope.secondValidRoot = data.x2; 25 | } 26 | 27 | $scope.$apply(); 28 | } 29 | 30 | document.getElementById("frmBhaskara").addEventListener("submit", function() { 31 | console.log("BHWS: Preparing to send data..."); 32 | var msg = { 33 | a: $scope.a, 34 | b: $scope.b, 35 | c: $scope.c 36 | }; 37 | console.log("BHWS: Sending data: ", msg); 38 | ws.send(JSON.stringify(msg)); 39 | return true; 40 | }); 41 | 42 | document.getElementById("btnTest").addEventListener("click", function(e) { 43 | console.log("$scope.firstValidRoot = ", $scope.firstValidRoot); 44 | console.log("$scope.secondValidRoot = ", $scope.secondValidRoot); 45 | }); 46 | 47 | console.log("BHWS: Setup completed."); 48 | } 49 | -------------------------------------------------------------------------------- /libesphttpd/lib/heatshrink/Makefile: -------------------------------------------------------------------------------- 1 | PROJECT = heatshrink 2 | #OPTIMIZE = -O0 3 | #OPTIMIZE = -Os 4 | OPTIMIZE = -O3 5 | WARN = -Wall -Wextra -pedantic #-Werror 6 | CFLAGS += -std=c99 -g ${WARN} ${OPTIMIZE} 7 | CFLAGS += -Wmissing-prototypes 8 | CFLAGS += -Wstrict-prototypes 9 | CFLAGS += -Wmissing-declarations 10 | 11 | # If libtheft is available, build additional property-based tests. 12 | # Uncomment these to use it in test_heatshrink_dynamic. 13 | #CFLAGS += -DHEATSHRINK_HAS_THEFT 14 | #LDFLAGS += -ltheft 15 | 16 | all: 17 | @echo "For tests, make test_heatshrink_dynamic (default) or change the" 18 | @echo "config.h to disable static memory and build test_heatshrink_static." 19 | @echo "For the standalone command-line tool, make heatshrink." 20 | 21 | ${PROJECT}: heatshrink.c 22 | 23 | OBJS= heatshrink_encoder.o \ 24 | heatshrink_decoder.o \ 25 | 26 | heatshrink: ${OBJS} 27 | test_heatshrink_dynamic: ${OBJS} test_heatshrink_dynamic_theft.o 28 | test_heatshrink_static: ${OBJS} 29 | 30 | *.o: Makefile heatshrink_config.h 31 | 32 | heatshrink_decoder.o: heatshrink_decoder.h heatshrink_common.h 33 | heatshrink_encoder.o: heatshrink_encoder.h heatshrink_common.h 34 | 35 | tags: TAGS 36 | 37 | TAGS: 38 | etags *.[ch] 39 | 40 | diagrams: dec_sm.png enc_sm.png 41 | 42 | dec_sm.png: dec_sm.dot 43 | dot -o $@ -Tpng $< 44 | 45 | enc_sm.png: enc_sm.dot 46 | dot -o $@ -Tpng $< 47 | 48 | clean: 49 | rm -f ${PROJECT} test_heatshrink_{dynamic,static} *.o *.core {dec,enc}_sm.png TAGS 50 | -------------------------------------------------------------------------------- /include/sdio_slv.h: -------------------------------------------------------------------------------- 1 | #ifndef SDIO_SLAVE_H 2 | #define SDIO_SLAVE_H 3 | #include "slc_register.h" 4 | #include "c_types.h" 5 | 6 | //#include "user_interface.h" 7 | struct sdio_queue 8 | { 9 | uint32 blocksize:12; 10 | uint32 datalen:12; 11 | uint32 unused:5; 12 | uint32 sub_sof:1; 13 | uint32 eof:1; 14 | uint32 owner:1; 15 | 16 | uint32 buf_ptr; 17 | uint32 next_link_ptr; 18 | }; 19 | 20 | struct sdio_slave_status_element 21 | { 22 | uint32 wr_busy:1; 23 | uint32 rd_empty :1; 24 | uint32 comm_cnt :3; 25 | uint32 intr_no :3; 26 | uint32 rx_length:16; 27 | uint32 res:8; 28 | }; 29 | 30 | union sdio_slave_status 31 | { 32 | struct sdio_slave_status_element elm_value; 33 | uint32 word_value; 34 | }; 35 | 36 | #define RX_AVAILIBLE 2 37 | #define TX_AVAILIBLE 1 38 | #define INIT_STAGE 0 39 | 40 | #define SDIO_QUEUE_LEN 8 41 | #define MOSI 0 42 | #define MISO 1 43 | #define SDIO_DATA_ERROR 6 44 | 45 | #define SLC_INTEREST_EVENT (SLC_TX_EOF_INT_ENA | SLC_RX_EOF_INT_ENA | SLC_RX_UDF_INT_ENA | SLC_TX_DSCR_ERR_INT_ENA) 46 | #define TRIG_TOHOST_INT() SET_PERI_REG_MASK(SLC_INTVEC_TOHOST , BIT0);\ 47 | CLEAR_PERI_REG_MASK(SLC_INTVEC_TOHOST , BIT0) 48 | 49 | /* 50 | void sdio_slave_init(void); 51 | void sdio_slave_isr(void *para); 52 | void sdio_task_init(void); 53 | void sdio_err_task(os_event_t *e); 54 | void rx_buff_load_done(uint16 rx_len); 55 | void tx_buff_handle_done(void); 56 | void rx_buff_read_done(void); 57 | void tx_buff_write_done(void); 58 | */ 59 | #endif 60 | -------------------------------------------------------------------------------- /include/user_config.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | /* 5 | * ESPRSSIF MIT License 6 | * 7 | * Copyright (c) 2015 8 | * 9 | * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, 10 | * it is free of charge, to any person obtaining a copy of this software and associated 11 | * documentation files (the "Software"), to deal in the Software without restriction, including 12 | * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished 14 | * to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be included in all copies or 17 | * substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 21 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 22 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 23 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | * 26 | */ 27 | 28 | #ifndef __USER_CONFIG_H__ 29 | #define __USER_CONFIG_H__ 30 | 31 | #endif 32 | 33 | 34 | #ifdef __cplusplus 35 | } 36 | #endif 37 | -------------------------------------------------------------------------------- /driver_lib/Makefile: -------------------------------------------------------------------------------- 1 | 2 | ############################################################# 3 | # Required variables for each makefile 4 | # Discard this section from all parent makefiles 5 | # Expected variables (with automatic defaults): 6 | # CSRCS (all "C" files in the dir) 7 | # SUBDIRS (all subdirs with a Makefile) 8 | # GEN_LIBS - list of libs to be generated () 9 | # GEN_IMAGES - list of images to be generated () 10 | # COMPONENTS_xxx - a list of libs/objs in the form 11 | # subdir/lib to be extracted and rolled up into 12 | # a generated lib/image xxx.a () 13 | # 14 | ifndef PDIR 15 | GEN_LIBS = libdriver.a 16 | endif 17 | 18 | 19 | ############################################################# 20 | # Configuration i.e. compile options etc. 21 | # Target specific stuff (defines etc.) goes in here! 22 | # Generally values applying to a tree are captured in the 23 | # makefile at its root level - these are then overridden 24 | # for a subtree within the makefile rooted therein 25 | # 26 | #DEFINES += 27 | 28 | ############################################################# 29 | # Recursion Magic - Don't touch this!! 30 | # 31 | # Each subtree potentially has an include directory 32 | # corresponding to the common APIs applicable to modules 33 | # rooted at that subtree. Accordingly, the INCLUDE PATH 34 | # of a module can only contain the include directories up 35 | # its parent path, and not its siblings 36 | # 37 | # Required for each makefile to inherit from the parent 38 | # 39 | 40 | INCLUDES := $(INCLUDES) -I $(PDIR)include 41 | PDIR := ../$(PDIR) 42 | sinclude $(PDIR)Makefile 43 | 44 | -------------------------------------------------------------------------------- /libesphttpd/espfs/espfstest/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | Simple and stupid file decompressor for an espfs image. Mostly used as a testbed for espfs.c and 3 | the decompressors: code compiled natively is way easier to debug using gdb et all :) 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | 15 | #include "espfs.h" 16 | 17 | char *espFsData; 18 | 19 | int main(int argc, char **argv) { 20 | int f, out; 21 | int len; 22 | char buff[128]; 23 | EspFsFile *ef; 24 | off_t size; 25 | EspFsInitResult ir; 26 | 27 | if (argc!=3) { 28 | printf("Usage: %s espfs-image file\nExpands file from the espfs-image archive.\n", argv[0]); 29 | exit(0); 30 | } 31 | 32 | f=open(argv[1], O_RDONLY); 33 | if (f<=0) { 34 | perror(argv[1]); 35 | exit(1); 36 | } 37 | size=lseek(f, 0, SEEK_END); 38 | espFsData=mmap(NULL, size, PROT_READ, MAP_SHARED, f, 0); 39 | if (espFsData==MAP_FAILED) { 40 | perror("mmap"); 41 | exit(1); 42 | } 43 | 44 | ir=espFsInit(espFsData); 45 | if (ir != ESPFS_INIT_RESULT_OK) { 46 | printf("Couldn't init espfs filesystem (code %d)\n", ir); 47 | exit(1); 48 | } 49 | 50 | ef=espFsOpen(argv[2]); 51 | if (ef==NULL) { 52 | printf("Couldn't find %s in image.\n", argv[2]); 53 | exit(1); 54 | } 55 | 56 | out=open(argv[2], O_WRONLY|O_CREAT|O_TRUNC, 0644); 57 | if (out<=0) { 58 | perror(argv[2]); 59 | exit(1); 60 | } 61 | 62 | while ((len=espFsRead(ef, buff, 128))!=0) { 63 | write(out, buff, len); 64 | } 65 | espFsClose(ef); 66 | //munmap, close, ... I can't be bothered. 67 | } 68 | -------------------------------------------------------------------------------- /user/Makefile: -------------------------------------------------------------------------------- 1 | 2 | ############################################################# 3 | # Required variables for each makefile 4 | # Discard this section from all parent makefiles 5 | # Expected variables (with automatic defaults): 6 | # CSRCS (all "C" files in the dir) 7 | # SUBDIRS (all subdirs with a Makefile) 8 | # GEN_LIBS - list of libs to be generated () 9 | # GEN_IMAGES - list of images to be generated () 10 | # COMPONENTS_xxx - a list of libs/objs in the form 11 | # subdir/lib to be extracted and rolled up into 12 | # a generated lib/image xxx.a () 13 | # 14 | ifndef PDIR 15 | GEN_LIBS = libuser.a 16 | endif 17 | 18 | 19 | ############################################################# 20 | # Configuration i.e. compile options etc. 21 | # Target specific stuff (defines etc.) goes in here! 22 | # Generally values applying to a tree are captured in the 23 | # makefile at its root level - these are then overridden 24 | # for a subtree within the makefile rooted therein 25 | # 26 | #DEFINES += 27 | 28 | ############################################################# 29 | # Recursion Magic - Don't touch this!! 30 | # 31 | # Each subtree potentially has an include directory 32 | # corresponding to the common APIs applicable to modules 33 | # rooted at that subtree. Accordingly, the INCLUDE PATH 34 | # of a module can only contain the include directories up 35 | # its parent path, and not its siblings 36 | # 37 | # Required for each makefile to inherit from the parent 38 | # 39 | 40 | INCLUDES := $(INCLUDES) -I $(PDIR)include 41 | INCLUDES += -I ./ 42 | PDIR := ../$(PDIR) 43 | sinclude $(PDIR)Makefile 44 | 45 | -------------------------------------------------------------------------------- /sample_lib/folder1/Makefile: -------------------------------------------------------------------------------- 1 | 2 | ############################################################# 3 | # Required variables for each makefile 4 | # Discard this section from all parent makefiles 5 | # Expected variables (with automatic defaults): 6 | # CSRCS (all "C" files in the dir) 7 | # SUBDIRS (all subdirs with a Makefile) 8 | # GEN_LIBS - list of libs to be generated () 9 | # GEN_IMAGES - list of images to be generated () 10 | # COMPONENTS_xxx - a list of libs/objs in the form 11 | # subdir/lib to be extracted and rolled up into 12 | # a generated lib/image xxx.a () 13 | # 14 | ifndef PDIR 15 | GEN_LIBS = libfolder1.a 16 | endif 17 | 18 | 19 | ############################################################# 20 | # Configuration i.e. compile options etc. 21 | # Target specific stuff (defines etc.) goes in here! 22 | # Generally values applying to a tree are captured in the 23 | # makefile at its root level - these are then overridden 24 | # for a subtree within the makefile rooted therein 25 | # 26 | #DEFINES += 27 | 28 | ############################################################# 29 | # Recursion Magic - Don't touch this!! 30 | # 31 | # Each subtree potentially has an include directory 32 | # corresponding to the common APIs applicable to modules 33 | # rooted at that subtree. Accordingly, the INCLUDE PATH 34 | # of a module can only contain the include directories up 35 | # its parent path, and not its siblings 36 | # 37 | # Required for each makefile to inherit from the parent 38 | # 39 | 40 | INCLUDES := $(INCLUDES) -I $(PDIR)include 41 | INCLUDES += -I ./ 42 | PDIR := ../$(PDIR) 43 | sinclude $(PDIR)Makefile 44 | 45 | -------------------------------------------------------------------------------- /sample_lib/folder2/Makefile: -------------------------------------------------------------------------------- 1 | 2 | ############################################################# 3 | # Required variables for each makefile 4 | # Discard this section from all parent makefiles 5 | # Expected variables (with automatic defaults): 6 | # CSRCS (all "C" files in the dir) 7 | # SUBDIRS (all subdirs with a Makefile) 8 | # GEN_LIBS - list of libs to be generated () 9 | # GEN_IMAGES - list of images to be generated () 10 | # COMPONENTS_xxx - a list of libs/objs in the form 11 | # subdir/lib to be extracted and rolled up into 12 | # a generated lib/image xxx.a () 13 | # 14 | ifndef PDIR 15 | GEN_LIBS = libfolder2.a 16 | endif 17 | 18 | 19 | ############################################################# 20 | # Configuration i.e. compile options etc. 21 | # Target specific stuff (defines etc.) goes in here! 22 | # Generally values applying to a tree are captured in the 23 | # makefile at its root level - these are then overridden 24 | # for a subtree within the makefile rooted therein 25 | # 26 | #DEFINES += 27 | 28 | ############################################################# 29 | # Recursion Magic - Don't touch this!! 30 | # 31 | # Each subtree potentially has an include directory 32 | # corresponding to the common APIs applicable to modules 33 | # rooted at that subtree. Accordingly, the INCLUDE PATH 34 | # of a module can only contain the include directories up 35 | # its parent path, and not its siblings 36 | # 37 | # Required for each makefile to inherit from the parent 38 | # 39 | 40 | INCLUDES := $(INCLUDES) -I $(PDIR)include 41 | INCLUDES += -I ./ 42 | PDIR := ../$(PDIR) 43 | sinclude $(PDIR)Makefile 44 | 45 | -------------------------------------------------------------------------------- /sample_lib/Makefile: -------------------------------------------------------------------------------- 1 | 2 | ############################################################# 3 | # Required variables for each makefile 4 | # Discard this section from all parent makefiles 5 | # Expected variables (with automatic defaults): 6 | # CSRCS (all "C" files in the dir) 7 | # SUBDIRS (all subdirs with a Makefile) 8 | # GEN_LIBS - list of libs to be generated () 9 | # GEN_IMAGES - list of images to be generated () 10 | # COMPONENTS_xxx - a list of libs/objs in the form 11 | # subdir/lib to be extracted and rolled up into 12 | # a generated lib/image xxx.a () 13 | # 14 | ifndef PDIR 15 | UP_EXTRACT_DIR = .. 16 | GEN_LIBS = libsample.a 17 | COMPONENTS_libsample = folder1/libfolder1.a \ 18 | folder2/libfolder2.a 19 | endif 20 | 21 | 22 | ############################################################# 23 | # Configuration i.e. compile options etc. 24 | # Target specific stuff (defines etc.) goes in here! 25 | # Generally values applying to a tree are captured in the 26 | # makefile at its root level - these are then overridden 27 | # for a subtree within the makefile rooted therein 28 | # 29 | #DEFINES += 30 | 31 | ############################################################# 32 | # Recursion Magic - Don't touch this!! 33 | # 34 | # Each subtree potentially has an include directory 35 | # corresponding to the common APIs applicable to modules 36 | # rooted at that subtree. Accordingly, the INCLUDE PATH 37 | # of a module can only contain the include directories up 38 | # its parent path, and not its siblings 39 | # 40 | # Required for each makefile to inherit from the parent 41 | # 42 | 43 | INCLUDES := $(INCLUDES) -I $(PDIR)include 44 | INCLUDES += -I ./ 45 | PDIR := ../$(PDIR) 46 | sinclude $(PDIR)Makefile 47 | 48 | -------------------------------------------------------------------------------- /user/stepper.h: -------------------------------------------------------------------------------- 1 | #ifndef STEPPER_H 2 | #define STEPPER_H 3 | 4 | #include 5 | 6 | /// Stepper motor position interpolator. 7 | /** Handles bresenham algorithms for a single stepper motor. 8 | * Time samples are considered the dominant axis. 9 | * Decides wether to take a step or nor. 10 | * Assumes always fullspeed, does not handle acceleration. 11 | * Does not handle direction. 12 | */ 13 | class Stepper { 14 | uint32_t current, end; 15 | uint32_t rate_up, rate_dn; 16 | int32_t acc; 17 | public: 18 | Stepper() { 19 | prepare(0,0); 20 | } 21 | 22 | /// Prepare for a movement. 23 | /** \param D specifies the total steps count to generate. 24 | * \param T specifies how many time samples should this 25 | * movement take at full speed. 26 | */ 27 | void prepare( 28 | uint32_t D, 29 | uint32_t T 30 | ) { 31 | current = 0; 32 | end = D; 33 | rate_up = D; 34 | rate_dn = T; 35 | acc = -int32_t(T)/2; 36 | } 37 | 38 | /// Decides wether to take a step. 39 | /** This function should be called every sample 40 | * to update the stepper position. 41 | * \return true if a step should be taken. 42 | */ 43 | bool step() { 44 | acc += rate_up; 45 | if (acc>0) { 46 | acc -= rate_dn; 47 | if (++current == end) { 48 | prepare (0,0); 49 | } 50 | return true; 51 | } 52 | return false; 53 | } 54 | 55 | /// Detects if the last movement has completed. 56 | /** \returns true if the movement is completed, or 57 | * false if it is still in progress. 58 | */ 59 | bool done() const { 60 | return current == end; 61 | } 62 | }; 63 | 64 | #endif // STEPPER_H 65 | -------------------------------------------------------------------------------- /libesphttpd/mkupgimg/mkupgimg.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | //Cygwin e.a. needs O_BINARY. Don't miscompile if it's not set. 11 | #ifndef O_BINARY 12 | #define O_BINARY 0 13 | #endif 14 | 15 | typedef struct __attribute__((packed)) { 16 | char magic[4]; 17 | char tag[28]; 18 | int32_t len1; 19 | int32_t len2; 20 | } Header; 21 | 22 | 23 | int openFile(char *file) { 24 | int r=open(file, O_RDONLY|O_BINARY); 25 | if (r<=0) { 26 | perror(file); 27 | exit(1); 28 | } 29 | return r; 30 | } 31 | 32 | int32_t intToEsp(int32_t v) { 33 | int32_t ret; 34 | char *p=(char*)&ret; 35 | *p++=(v>>0)&0xff; 36 | *p++=(v>>8)&0xff; 37 | *p++=(v>>16)&0xff; 38 | *p++=(v>>24)&0xff; 39 | return ret; 40 | } 41 | 42 | size_t fileLen(int f) { 43 | size_t r; 44 | r=lseek(f, 0, SEEK_END); 45 | lseek(f, 0, SEEK_SET); 46 | return r; 47 | } 48 | 49 | 50 | int main(int argc, char **argv) { 51 | int u1, u2; 52 | size_t l1, l2; 53 | int of; 54 | char *fc1, *fc2; 55 | Header hdr; 56 | if (argc!=5) { 57 | printf("Usage: %s user1.bin user2.bin tagname outfile.bin\n", argv[0]); 58 | exit(1); 59 | } 60 | if (strlen(argv[3])>27) { 61 | printf("Error: Tag can't be longer than 27 characters.\n"); 62 | exit(1); 63 | } 64 | memset(&hdr, 0, sizeof(hdr)); 65 | memcpy(hdr.magic, "EHUG", 4); 66 | strcpy(hdr.tag, argv[3]); 67 | u1=openFile(argv[1]); 68 | u2=openFile(argv[2]); 69 | l1=fileLen(u1); 70 | l2=fileLen(u2); 71 | hdr.len1=intToEsp(l1); 72 | hdr.len2=intToEsp(l2); 73 | fc1=malloc(l1); 74 | fc2=malloc(l2); 75 | if (read(u1, fc1, l1)!=l1) { 76 | perror(argv[1]); 77 | exit(1); 78 | } 79 | if (read(u2, fc2, l2)!=l2) { 80 | perror(argv[2]); 81 | exit(1); 82 | } 83 | close(u1); 84 | close(u2); 85 | of=open(argv[4], O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666); 86 | if (of<=0) { 87 | perror(argv[4]); 88 | exit(1); 89 | } 90 | write(of, &hdr, sizeof(hdr)); 91 | write(of, fc1, l1); 92 | write(of, fc2, l2); 93 | printf("Header: %d bytes, user1: %d bytes, user2: %d bytes.\n", sizeof(hdr), (int)l1, (int)l2); 94 | close(of); 95 | exit(0); 96 | } 97 | 98 | -------------------------------------------------------------------------------- /libesphttpd/lib/heatshrink/enc_sm.dot: -------------------------------------------------------------------------------- 1 | digraph { 2 | graph [label="Encoder state machine", labelloc="t"] 3 | start [style="invis", shape="point"] 4 | not_full 5 | filled 6 | search 7 | yield_tag_bit 8 | yield_literal 9 | yield_br_length 10 | yield_br_index 11 | save_backlog 12 | flush_bits 13 | done [peripheries=2] 14 | 15 | start->not_full [label="start"] 16 | 17 | not_full->not_full [label="sink(), not full", color="blue"] 18 | not_full->filled [label="sink(), buffer is full", color="blue"] 19 | not_full->filled [label="finish(), set is_finished", color="blue"] 20 | 21 | filled->search [label="indexing (if any)"] 22 | 23 | search->search [label="step"] 24 | search->yield_tag_bit [label="literal"] 25 | search->yield_tag_bit [label="match found"] 26 | search->save_backlog [label="input exhausted"] 27 | 28 | yield_tag_bit->yield_tag_bit [label="poll(), full buf", color="red"] 29 | yield_tag_bit->yield_literal [label="poll(), literal", color="red"] 30 | yield_tag_bit->yield_br_index [label="poll(), no literal", color="red"] 31 | yield_tag_bit->flush_bits [label="finishing, no literal"] 32 | 33 | yield_literal->yield_literal [label="poll(), full buf", color="red"] 34 | yield_literal->search [label="poll(), no match", color="red"] 35 | yield_literal->yield_tag_bit [label="poll(), match", color="red"] 36 | yield_literal->flush_bits [label="poll(), final literal", color="red"] 37 | 38 | yield_br_index->yield_br_index [label="poll(), full buf", color="red"] 39 | yield_br_index->yield_br_length [label="poll()", color="red"] 40 | 41 | yield_br_length->yield_br_length [label="poll(), full buf", color="red"] 42 | yield_br_length->search [label="done"] 43 | 44 | save_backlog->flush_bits [label="finishing, no literal"] 45 | save_backlog->yield_tag_bit [label="finishing, literal"] 46 | save_backlog->not_full [label="expect more input"] 47 | 48 | flush_bits->flush_bits [label="poll(), full buf", color="red"] 49 | flush_bits->done [label="poll(), flushed", color="red"] 50 | flush_bits->done [label="no more output"] 51 | } 52 | -------------------------------------------------------------------------------- /libesphttpd/lib/heatshrink/README.md: -------------------------------------------------------------------------------- 1 | # heatshrink 2 | 3 | A data compression/decompression library for embedded/real-time systems. 4 | 5 | ## Key Features: 6 | 7 | - **Low memory usage (as low as 50 bytes)** 8 | It is useful for some cases with less than 50 bytes, and useful 9 | for many general cases with < 300 bytes. 10 | - **Incremental, bounded CPU use** 11 | You can chew on input data in arbitrarily tiny bites. 12 | This is a useful property in hard real-time environments. 13 | - **Can use either static or dynamic memory allocation** 14 | The library doesn't impose any constraints on memory management. 15 | - **ISC license** 16 | You can use it freely, even for commercial purposes. 17 | 18 | ## Getting Started: 19 | 20 | There is a standalone command-line program, `heatshrink`, but the 21 | encoder and decoder can also be used as libraries, independent of each 22 | other. To do so, copy `heatshrink_common.h`, `heatshrink_config.h`, and 23 | either `heatshrink_encoder.c` or `heatshrink_decoder.c` (and their 24 | respective header) into your project. 25 | 26 | Dynamic allocation is used by default, but in an embedded context, you 27 | probably want to statically allocate the encoder/decoder. Set 28 | `HEATSHRINK_DYNAMIC_ALLOC` to 0 in `heatshrink_config.h`. 29 | 30 | ## More Information and Benchmarks: 31 | 32 | heatshrink is based on [LZSS], since it's particularly suitable for 33 | compression in small amounts of memory. It can use an optional, small 34 | [index] to make compression significantly faster, but otherwise can run 35 | in under 100 bytes of memory. The index currently adds 2^(window size+1) 36 | bytes to memory usage for compression, and temporarily allocates 512 37 | bytes on the stack during index construction. 38 | 39 | For more information, see the [blog post] for an overview, and the 40 | `heatshrink_encoder.h` / `heatshrink_decoder.h` header files for API 41 | documentation. 42 | 43 | [blog post]: http://spin.atomicobject.com/2013/03/14/heatshrink-embedded-data-compression/ 44 | [index]: http://spin.atomicobject.com/2014/01/13/lightweight-indexing-for-embedded-systems/ 45 | [LZSS]: http://en.wikipedia.org/wiki/Lempel-Ziv-Storer-Szymanski 46 | 47 | ## Build Status 48 | 49 | [![Build Status](https://travis-ci.org/atomicobject/heatshrink.png)](http://travis-ci.org/atomicobject/heatshrink) 50 | -------------------------------------------------------------------------------- /libesphttpd/core/auth.c: -------------------------------------------------------------------------------- 1 | /* 2 | HTTP auth implementation. Only does basic authentication for now. 3 | */ 4 | 5 | /* 6 | * ---------------------------------------------------------------------------- 7 | * "THE BEER-WARE LICENSE" (Revision 42): 8 | * Jeroen Domburg wrote this file. As long as you retain 9 | * this notice you can do whatever you want with this stuff. If we meet some day, 10 | * and you think this stuff is worth it, you can buy me a beer in return. 11 | * ---------------------------------------------------------------------------- 12 | */ 13 | 14 | 15 | #include 16 | #include "auth.h" 17 | #include "base64.h" 18 | 19 | int ICACHE_FLASH_ATTR authBasic(HttpdConnData *connData) { 20 | const char *forbidden="401 Forbidden."; 21 | int no=0; 22 | int r; 23 | char hdr[(AUTH_MAX_USER_LEN+AUTH_MAX_PASS_LEN+2)*10]; 24 | char userpass[AUTH_MAX_USER_LEN+AUTH_MAX_PASS_LEN+2]; 25 | char user[AUTH_MAX_USER_LEN]; 26 | char pass[AUTH_MAX_PASS_LEN]; 27 | if (connData->conn==NULL) { 28 | //Connection aborted. Clean up. 29 | return HTTPD_CGI_DONE; 30 | } 31 | 32 | r=httpdGetHeader(connData, "Authorization", hdr, sizeof(hdr)); 33 | if (r && strncmp(hdr, "Basic", 5)==0) { 34 | r=base64_decode(strlen(hdr)-6, hdr+6, sizeof(userpass), (unsigned char *)userpass); 35 | if (r<0) r=0; //just clean out string on decode error 36 | userpass[r]=0; //zero-terminate user:pass string 37 | // printf("Auth: %s\n", userpass); 38 | while (((AuthGetUserPw)(connData->cgiArg))(connData, no, 39 | user, AUTH_MAX_USER_LEN, pass, AUTH_MAX_PASS_LEN)) { 40 | //Check user/pass against auth header 41 | if (strlen(userpass)==strlen(user)+strlen(pass)+1 && 42 | strncmp(userpass, user, strlen(user))==0 && 43 | userpass[strlen(user)]==':' && 44 | strcmp(userpass+strlen(user)+1, pass)==0) { 45 | //Authenticated. Yay! 46 | return HTTPD_CGI_AUTHENTICATED; 47 | } 48 | no++; //Not authenticated with this user/pass. Check next user/pass combo. 49 | } 50 | } 51 | 52 | //Not authenticated. Go bug user with login screen. 53 | httpdStartResponse(connData, 401); 54 | httpdHeader(connData, "Content-Type", "text/plain"); 55 | httpdHeader(connData, "WWW-Authenticate", "Basic realm=\""HTTP_AUTH_REALM"\""); 56 | httpdEndHeaders(connData); 57 | httpdSend(connData, forbidden, -1); 58 | //Okay, all done. 59 | return HTTPD_CGI_DONE; 60 | } 61 | 62 | -------------------------------------------------------------------------------- /libesphttpd/lib/heatshrink/dec_sm.dot: -------------------------------------------------------------------------------- 1 | digraph { 2 | graph [label="Decoder state machine", labelloc="t"] 3 | Start [style="invis", shape="point"] 4 | empty 5 | input_available 6 | yield_literal 7 | backref_index_msb 8 | backref_index_lsb 9 | backref_count_msb 10 | backref_count_lsb 11 | yield_backref 12 | check_for_more_input 13 | done [peripheries=2] 14 | 15 | empty->input_available [label="sink()", color="blue", weight=10] 16 | Start->empty 17 | 18 | input_available->yield_literal [label="pop 1-bit"] 19 | input_available->backref_index_msb [label="pop 0-bit", weight=10] 20 | input_available->backref_index_lsb [label="pop 0-bit, index <8 bits", weight=10] 21 | 22 | yield_literal->yield_literal [label="sink()", color="blue"] 23 | yield_literal->yield_literal [label="poll()", color="red"] 24 | yield_literal->check_for_more_input [label="poll(), done", color="red"] 25 | 26 | backref_index_msb->backref_index_msb [label="sink()", color="blue"] 27 | backref_index_msb->backref_index_lsb [label="pop index, upper bits", weight=10] 28 | backref_index_msb->done [label="finish()", color="blue"] 29 | 30 | backref_index_lsb->backref_index_lsb [label="sink()", color="blue"] 31 | backref_index_lsb->backref_count_msb [label="pop index, lower bits", weight=10] 32 | backref_index_lsb->backref_count_lsb [label="pop index, count <=8 bits", weight=10] 33 | backref_index_lsb->done [label="finish()", color="blue"] 34 | 35 | backref_count_msb->backref_count_msb [label="sink()", color="blue"] 36 | backref_count_msb->backref_count_lsb [label="pop count, upper bits", weight=10] 37 | backref_count_msb->done [label="finish()", color="blue"] 38 | 39 | backref_count_lsb->backref_count_lsb [label="sink()", color="blue"] 40 | backref_count_lsb->yield_backref [label="pop count, lower bits", weight=10] 41 | backref_count_lsb->done [label="finish()", color="blue"] 42 | 43 | yield_backref->yield_backref [label="sink()", color="blue"] 44 | yield_backref->yield_backref [label="poll()", color="red"] 45 | yield_backref->check_for_more_input [label="poll(), done", 46 | color="red", weight=10] 47 | 48 | check_for_more_input->empty [label="no"] 49 | check_for_more_input->input_available [label="yes"] 50 | 51 | empty->done [label="finish()", color="blue"] 52 | } 53 | -------------------------------------------------------------------------------- /user/cgi-test.c: -------------------------------------------------------------------------------- 1 | /* 2 | Cgi routines as used by the tests in the html/test subdirectory. 3 | */ 4 | 5 | /* 6 | * ---------------------------------------------------------------------------- 7 | * "THE BEER-WARE LICENSE" (Revision 42): 8 | * Jeroen Domburg wrote this file. As long as you retain 9 | * this notice you can do whatever you want with this stuff. If we meet some day, 10 | * and you think this stuff is worth it, you can buy me a beer in return. 11 | * ---------------------------------------------------------------------------- 12 | */ 13 | 14 | 15 | #include 16 | #include "cgi-test.h" 17 | 18 | 19 | typedef struct { 20 | int len; 21 | int sendPos; 22 | } TestbedState; 23 | 24 | 25 | int ICACHE_FLASH_ATTR cgiTestbed(HttpdConnData *connData) { 26 | char buff[1024]; 27 | int first=0; 28 | int l, x; 29 | TestbedState *state=(TestbedState*)connData->cgiData; 30 | 31 | if (connData->conn==NULL) { 32 | //Connection aborted. Clean up. 33 | if (state) free(state); 34 | return HTTPD_CGI_DONE; 35 | } 36 | 37 | if (state==NULL) { 38 | //First call 39 | state=malloc(sizeof(TestbedState)); 40 | memset(state, 0, sizeof(state)); 41 | connData->cgiData=state; 42 | first=1; 43 | } 44 | 45 | if (connData->requestType==HTTPD_METHOD_GET) { 46 | if (first) { 47 | httpdStartResponse(connData, 200); 48 | httpdHeader(connData, "content-type", "text/plain"); 49 | httpdEndHeaders(connData); 50 | l=httpdFindArg(connData->getArgs, "len", buff, sizeof(buff)); 51 | state->len=1024; 52 | if (l!=-1) state->len=atoi(buff); 53 | state->sendPos=0; 54 | return HTTPD_CGI_MORE; 55 | } else { 56 | l=sizeof(buff); 57 | if (l>(state->len-state->sendPos)) l=(state->len-state->sendPos); 58 | //Fill with semi-random data 59 | for (x=0; xsendPos>>10))&0x1F)+'0'; 60 | httpdSend(connData, buff, l); 61 | state->sendPos+=l; 62 | printf("Test: Uploaded %d/%d bytes\n", state->sendPos, state->len); 63 | if (state->len<=state->sendPos) { 64 | if (state) free(state); 65 | return HTTPD_CGI_DONE; 66 | } else { 67 | return HTTPD_CGI_MORE; 68 | } 69 | } 70 | } 71 | if (connData->requestType==HTTPD_METHOD_POST) { 72 | if (connData->post->len!=connData->post->received) { 73 | //Still receiving data. Ignore this. 74 | printf("Test: got %d/%d bytes\n", connData->post->received, connData->post->len); 75 | return HTTPD_CGI_MORE; 76 | } else { 77 | httpdStartResponse(connData, 200); 78 | httpdHeader(connData, "content-type", "text/plain"); 79 | httpdEndHeaders(connData); 80 | l=sprintf(buff, "%d", connData->post->received); 81 | httpdSend(connData, buff, l); 82 | return HTTPD_CGI_DONE; 83 | } 84 | } 85 | return HTTPD_CGI_DONE; 86 | } 87 | -------------------------------------------------------------------------------- /driver_lib/include/hw_timer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ESPRSSIF MIT License 3 | * 4 | * Copyright (c) 2015 5 | * 6 | * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, 7 | * it is free of charge, to any person obtaining a copy of this software and associated 8 | * documentation files (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished 11 | * to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all copies or 14 | * substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | * 23 | */ 24 | 25 | #ifndef __HW_TIMER_H__ 26 | #define __HW_TIMER_H__ 27 | 28 | #ifdef __cplusplus 29 | extern "C" { 30 | #endif 31 | 32 | /** \defgroup HW_Timer_APIs Hardware timer APIs 33 | * @brief Hardware timer APIs 34 | * 35 | * @attention Hardware timer can not interrupt other ISRs. 36 | * 37 | */ 38 | 39 | /** @addtogroup HW_Timer_APIs 40 | * @{ 41 | */ 42 | 43 | 44 | /** 45 | * @brief Initialize the hardware ISR timer. 46 | * 47 | * @param uint8 req : 0, not autoload; 1, autoload mode. 48 | * 49 | * @return null 50 | */ 51 | void hw_timer_init(uint8 req); 52 | 53 | /** 54 | * @brief Set a trigger timer delay to enable this timer. 55 | * 56 | * @param uint32 val : Timing 57 | * - In autoload mode, range : 50 ~ 0x7fffff 58 | * - In non-autoload mode, range : 10 ~ 0x7fffff 59 | * 60 | * @return null 61 | */ 62 | void hw_timer_arm(uint32 val); 63 | 64 | /** 65 | * @brief Set timer callback function. 66 | * 67 | * For enabled timer, timer callback has to be set. 68 | * 69 | * @param uint32 val : Timing 70 | * - In autoload mode, range : 50 ~ 0x7fffff 71 | * - In non-autoload mode, range : 10 ~ 0x7fffff 72 | * 73 | * @return null 74 | */ 75 | void hw_timer_set_func(void (* user_hw_timer_cb_set)(void)); 76 | 77 | /** 78 | * @} 79 | */ 80 | 81 | #ifdef __cplusplus 82 | } 83 | #endif 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /libesphttpd/core/httpd-nonos.c: -------------------------------------------------------------------------------- 1 | /* 2 | ESP8266 web server - platform-dependent routines, nonos version 3 | */ 4 | 5 | #include 6 | #include "httpd.h" 7 | #include "platform.h" 8 | #include "httpd-platform.h" 9 | 10 | #ifndef FREERTOS 11 | 12 | //Listening connection data 13 | static struct espconn httpdConn; 14 | static esp_tcp httpdTcp; 15 | 16 | //Set/clear global httpd lock. 17 | //Not needed on nonoos. 18 | void ICACHE_FLASH_ATTR httpdPlatLock() { 19 | } 20 | void ICACHE_FLASH_ATTR httpdPlatUnlock() { 21 | } 22 | 23 | 24 | static void ICACHE_FLASH_ATTR platReconCb(void *arg, sint8 err) { 25 | //From ESP8266 SDK 26 | //If still no response, considers it as TCP connection broke, goes into espconn_reconnect_callback. 27 | 28 | ConnTypePtr conn=arg; 29 | //Just call disconnect to clean up pool and close connection. 30 | httpdDisconCb(conn, (char*)conn->proto.tcp->remote_ip, conn->proto.tcp->remote_port); 31 | } 32 | 33 | static void ICACHE_FLASH_ATTR platDisconCb(void *arg) { 34 | ConnTypePtr conn=arg; 35 | httpdDisconCb(conn, (char*)conn->proto.tcp->remote_ip, conn->proto.tcp->remote_port); 36 | } 37 | 38 | static void ICACHE_FLASH_ATTR platRecvCb(void *arg, char *data, unsigned short len) { 39 | ConnTypePtr conn=arg; 40 | httpdRecvCb(conn, (char*)conn->proto.tcp->remote_ip, conn->proto.tcp->remote_port, data, len); 41 | } 42 | 43 | static void ICACHE_FLASH_ATTR platSentCb(void *arg) { 44 | ConnTypePtr conn=arg; 45 | httpdSentCb(conn, (char*)conn->proto.tcp->remote_ip, conn->proto.tcp->remote_port); 46 | } 47 | 48 | static void ICACHE_FLASH_ATTR platConnCb(void *arg) { 49 | ConnTypePtr conn=arg; 50 | if (httpdConnectCb(conn, (char*)conn->proto.tcp->remote_ip, conn->proto.tcp->remote_port)) { 51 | espconn_regist_recvcb(conn, platRecvCb); 52 | espconn_regist_reconcb(conn, platReconCb); 53 | espconn_regist_disconcb(conn, platDisconCb); 54 | espconn_regist_sentcb(conn, platSentCb); 55 | } else { 56 | espconn_disconnect(conn); 57 | } 58 | } 59 | 60 | 61 | int ICACHE_FLASH_ATTR httpdPlatSendData(ConnTypePtr conn, char *buff, int len) { 62 | int r; 63 | r=espconn_sent(conn, (uint8_t*)buff, len); 64 | return (r>=0); 65 | } 66 | 67 | void ICACHE_FLASH_ATTR httpdPlatDisconnect(ConnTypePtr conn) { 68 | espconn_disconnect(conn); 69 | } 70 | 71 | void ICACHE_FLASH_ATTR httpdPlatDisableTimeout(ConnTypePtr conn) { 72 | //Can't disable timeout; set to 2 hours instead. 73 | espconn_regist_time(conn, 7199, 1); 74 | } 75 | 76 | //Initialize listening socket, do general initialization 77 | void ICACHE_FLASH_ATTR httpdPlatInit(int port, int maxConnCt) { 78 | httpdConn.type=ESPCONN_TCP; 79 | httpdConn.state=ESPCONN_NONE; 80 | httpdTcp.local_port=port; 81 | httpdConn.proto.tcp=&httpdTcp; 82 | espconn_regist_connectcb(&httpdConn, platConnCb); 83 | espconn_accept(&httpdConn); 84 | espconn_tcp_set_max_con_allow(&httpdConn, maxConnCt); 85 | } 86 | 87 | 88 | #endif -------------------------------------------------------------------------------- /user/reprap_core.cpp: -------------------------------------------------------------------------------- 1 | #include "reprap_core.h" 2 | 3 | #include "stepper.h" 4 | #include "throttle.h" 5 | #include "maskedtransportdelay.h" 6 | #include "buffered_sw_pwm.h" 7 | #include "sigmadelta.h" 8 | 9 | #include "c_types.h" 10 | #include "driver/i2s_freertos.h" 11 | 12 | #define RATE 192000 // Sample rate 13 | #define MAXSPD (32*1000) // Max Speed, steps/s 14 | #define MOVE (5*MAXSPD) // Move distance, steps 15 | #define ACCEL (2*RATE) // Ramp up/down duration, samples 16 | 17 | #define STEP_MASK 0x00000001U 18 | #define DIR_MASK 0x00010000U 19 | #define NUM_STEPPERS 4 20 | 21 | #define PWM_MASK 0x00000010U 22 | #define PWM_COUNT 4 23 | #define SGD_MASK 0x00000100U 24 | #define SGD_COUNT 4 25 | 26 | static uint32_t forward = 0; 27 | static Throttle throttle; 28 | static Stepper stepper[NUM_STEPPERS]; 29 | static MaskedTransportDelay td; 30 | 31 | static BufferedSoftwarePwm pwm[PWM_COUNT]; 32 | static SigmaDeltaModulator sigmadelta[SGD_COUNT]; 33 | 34 | static uint32_t step() { 35 | uint32_t out = 0; 36 | 37 | // If motion has completed, prepare new move 38 | bool done = throttle.done(); 39 | for (int s=0; s>31); 87 | 88 | return out; 89 | } 90 | 91 | void reprap_core_task(void *arg) { 92 | i2sInit(); 93 | i2sSetRate(RATE,1); 94 | 95 | // Start the PWM for servos, as a demonstration. 96 | const uint32_t ms = 192; // Samples per milisecond 97 | for (int i=0; i 8 | #include 9 | 10 | 11 | int strcasecmp(const char *a, const char *b); 12 | #ifndef FREERTOS 13 | #include 14 | #include 15 | //Missing function prototypes in include folders. Gcc will warn on these if we don't define 'em anywhere. 16 | //MOST OF THESE ARE GUESSED! but they seem to swork and shut up the compiler. 17 | typedef struct espconn espconn; 18 | 19 | int atoi(const char *nptr); 20 | void ets_install_putc1(void *routine); 21 | void ets_isr_attach(int intr, void *handler, void *arg); 22 | void ets_isr_mask(unsigned intr); 23 | void ets_isr_unmask(unsigned intr); 24 | int ets_memcmp(const void *s1, const void *s2, size_t n); 25 | void *ets_memcpy(void *dest, const void *src, size_t n); 26 | void *ets_memset(void *s, int c, size_t n); 27 | int ets_sprintf(char *str, const char *format, ...) __attribute__ ((format (printf, 2, 3))); 28 | int ets_str2macaddr(void *, void *); 29 | int ets_strcmp(const char *s1, const char *s2); 30 | char *ets_strcpy(char *dest, const char *src); 31 | size_t ets_strlen(const char *s); 32 | int ets_strncmp(const char *s1, const char *s2, int len); 33 | char *ets_strncpy(char *dest, const char *src, size_t n); 34 | char *ets_strstr(const char *haystack, const char *needle); 35 | void ets_timer_arm_new(os_timer_t *a, int b, int c, int isMstimer); 36 | void ets_timer_disarm(os_timer_t *a); 37 | void ets_timer_setfn(os_timer_t *t, ETSTimerFunc *fn, void *parg); 38 | void ets_update_cpu_frequency(int freqmhz); 39 | void *os_memmove(void *dest, const void *src, size_t n); 40 | int os_printf(const char *format, ...) __attribute__ ((format (printf, 1, 2))); 41 | int os_snprintf(char *str, size_t size, const char *format, ...) __attribute__ ((format (printf, 3, 4))); 42 | int os_printf_plus(const char *format, ...) __attribute__ ((format (printf, 1, 2))); 43 | void uart_div_modify(int no, unsigned int freq); 44 | uint8 wifi_get_opmode(void); 45 | uint32 system_get_time(); 46 | int rand(void); 47 | void ets_bzero(void *s, size_t n); 48 | void ets_delay_us(int ms); 49 | 50 | //Hack: this is defined in SDK 1.4.0 and undefined in 1.3.0. It's only used for this, the symbol itself 51 | //has no meaning here. 52 | #ifndef RC_LIMIT_P2P_11N 53 | //Defs for SDK <1.4.0 54 | void *pvPortMalloc(size_t xWantedSize); 55 | void *pvPortZalloc(size_t); 56 | void vPortFree(void *ptr); 57 | void *vPortMalloc(size_t xWantedSize); 58 | void pvPortFree(void *ptr); 59 | #else 60 | void *pvPortMalloc(size_t xWantedSize, const char *file, int line); 61 | void *pvPortZalloc(size_t, const char *file, int line); 62 | void vPortFree(void *ptr, const char *file, int line); 63 | void *vPortMalloc(size_t xWantedSize, const char *file, int line); 64 | void pvPortFree(void *ptr, const char *file, int line); 65 | #endif 66 | 67 | //Standard PIN_FUNC_SELECT gives a warning. Replace by a non-warning one. 68 | #ifdef PIN_FUNC_SELECT 69 | #undef PIN_FUNC_SELECT 70 | #define PIN_FUNC_SELECT(PIN_NAME, FUNC) do { \ 71 | WRITE_PERI_REG(PIN_NAME, \ 72 | (READ_PERI_REG(PIN_NAME) \ 73 | & (~(PERIPHS_IO_MUX_FUNC< 4 | #include "base64.h" 5 | 6 | static const int base64dec_tab[256] ICACHE_RODATA_ATTR={ 7 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 8 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 9 | 255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63, 10 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255, 11 | 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 12 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255, 13 | 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 14 | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255, 15 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 16 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 17 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 18 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 19 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 20 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 21 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 22 | 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 23 | }; 24 | 25 | #if 0 26 | static int ICACHE_FLASH_ATTR base64decode(const char in[4], char out[3]) { 27 | uint8_t v[4]; 28 | 29 | v[0]=base64dec_tab[(unsigned)in[0]]; 30 | v[1]=base64dec_tab[(unsigned)in[1]]; 31 | v[2]=base64dec_tab[(unsigned)in[2]]; 32 | v[3]=base64dec_tab[(unsigned)in[3]]; 33 | 34 | out[0]=(v[0]<<2)|(v[1]>>4); 35 | out[1]=(v[1]<<4)|(v[2]>>2); 36 | out[2]=(v[2]<<6)|(v[3]); 37 | return (v[0]|v[1]|v[2]|v[3])!=255 ? in[3]=='=' ? in[2]=='=' ? 1 : 2 : 3 : 0; 38 | } 39 | #endif 40 | 41 | /* decode a base64 string in one shot */ 42 | int ICACHE_FLASH_ATTR __attribute__((weak)) base64_decode(size_t in_len, const char *in, size_t out_len, unsigned char *out) { 43 | unsigned int ii, io; 44 | uint32_t v; 45 | unsigned int rem; 46 | 47 | for(io=0,ii=0,v=0,rem=0;ii=8) { 56 | rem-=8; 57 | if(io>=out_len) return -1; /* truncation is failure */ 58 | out[io++]=(v>>rem)&255; 59 | } 60 | } 61 | if(rem>=8) { 62 | rem-=8; 63 | if(io>=out_len) return -1; /* truncation is failure */ 64 | out[io++]=(v>>rem)&255; 65 | } 66 | return io; 67 | } 68 | 69 | static const uint8_t base64enc_tab[64]= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 70 | 71 | #if 0 72 | void base64encode(const unsigned char in[3], unsigned char out[4], int count) { 73 | out[0]=base64enc_tab[(in[0]>>2)]; 74 | out[1]=base64enc_tab[((in[0]&3)<<4)|(in[1]>>4)]; 75 | out[2]=count<2 ? '=' : base64enc_tab[((in[1]&15)<<2)|(in[2]>>6)]; 76 | out[3]=count<3 ? '=' : base64enc_tab[(in[2]&63)]; 77 | } 78 | #endif 79 | 80 | int ICACHE_FLASH_ATTR __attribute__((weak)) base64_encode(size_t in_len, const unsigned char *in, size_t out_len, char *out) { 81 | unsigned ii, io; 82 | uint32_t v; 83 | unsigned rem; 84 | 85 | for(io=0,ii=0,v=0,rem=0;ii=6) { 91 | rem-=6; 92 | if(io>=out_len) return -1; /* truncation is failure */ 93 | out[io++]=base64enc_tab[(v>>rem)&63]; 94 | } 95 | } 96 | if(rem) { 97 | v<<=(6-rem); 98 | if(io>=out_len) return -1; /* truncation is failure */ 99 | out[io++]=base64enc_tab[v&63]; 100 | } 101 | while(io&3) { 102 | if(io>=out_len) return -1; /* truncation is failure */ 103 | out[io++]='='; 104 | } 105 | if(io>=out_len) return -1; /* no room for null terminator */ 106 | out[io]=0; 107 | return io; 108 | } 109 | 110 | -------------------------------------------------------------------------------- /driver_lib/hw_timer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ESPRSSIF MIT License 3 | * 4 | * Copyright (c) 2015 5 | * 6 | * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, 7 | * it is free of charge, to any person obtaining a copy of this software and associated 8 | * documentation files (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished 11 | * to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all copies or 14 | * substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | * 23 | */ 24 | 25 | #include "esp_common.h" 26 | 27 | #define US_TO_RTC_TIMER_TICKS(t) \ 28 | ((t) ? \ 29 | (((t) > 0x35A) ? \ 30 | (((t) >> 2) * ((APB_CLK_FREQ >> 4) / 250000) + ((t)&0x3) * ((APB_CLK_FREQ >> 4) / 1000000)) : \ 31 | (((t) *(APB_CLK_FREQ>>4)) / 1000000)) : \ 32 | 0) 33 | 34 | #define FRC1_ENABLE_TIMER BIT7 35 | #define FRC1_AUTO_LOAD BIT6 36 | 37 | typedef enum { // timer provided mode 38 | DIVDED_BY_1 = 0, // timer clock 39 | DIVDED_BY_16 = 4, // divided by 16 40 | DIVDED_BY_256 = 8, // divided by 256 41 | } TIMER_PREDIVED_MODE; 42 | 43 | typedef enum { // timer interrupt mode 44 | TM_LEVEL_INT = 1, // level interrupt 45 | TM_EDGE_INT = 0, // edge interrupt 46 | } TIMER_INT_MODE; 47 | 48 | #define RTC_REG_WRITE(addr, val) WRITE_PERI_REG(addr, val) 49 | 50 | static void (* user_hw_timer_cb)(void) = NULL; 51 | 52 | static void hw_timer_isr_cb(void *arg) 53 | { 54 | if (user_hw_timer_cb != NULL) { 55 | (*(user_hw_timer_cb))(); 56 | } 57 | } 58 | 59 | void hw_timer_arm(uint32 val) 60 | { 61 | RTC_REG_WRITE(FRC1_LOAD_ADDRESS, US_TO_RTC_TIMER_TICKS(val)); 62 | } 63 | 64 | void hw_timer_set_func(void (* user_hw_timer_cb_set)(void)) 65 | { 66 | user_hw_timer_cb = user_hw_timer_cb_set; 67 | } 68 | 69 | void hw_timer_init(uint8 req) 70 | { 71 | if (req == 1) { 72 | RTC_REG_WRITE(FRC1_CTRL_ADDRESS, 73 | FRC1_AUTO_LOAD | DIVDED_BY_16 | FRC1_ENABLE_TIMER | TM_EDGE_INT); 74 | } else { 75 | RTC_REG_WRITE(FRC1_CTRL_ADDRESS, 76 | DIVDED_BY_16 | FRC1_ENABLE_TIMER | TM_EDGE_INT); 77 | } 78 | 79 | _xt_isr_attach(ETS_FRC_TIMER1_INUM, hw_timer_isr_cb, NULL); 80 | 81 | TM1_EDGE_INT_ENABLE(); 82 | _xt_isr_unmask(1 << ETS_FRC_TIMER1_INUM); 83 | } 84 | 85 | //-------------------------------Test Code Below-------------------------------------- 86 | #if 0 87 | #include "hw_timer.h" 88 | 89 | #define REG_WRITE(_r,_v) (*(volatile uint32 *)(_r)) = (_v) 90 | #define REG_READ(_r) (*(volatile uint32 *)(_r)) 91 | #define WDEV_NOW() REG_READ(0x3ff20c00) 92 | 93 | uint32 tick_now2 = 0; 94 | void hw_test_timer_cb(void) 95 | { 96 | static uint16 j = 0; 97 | j++; 98 | 99 | if ((WDEV_NOW() - tick_now2) >= 1000000) { 100 | static uint32 idx = 1; 101 | tick_now2 = WDEV_NOW(); 102 | os_printf("b%u:%d\n", idx++, j); 103 | j = 0; 104 | } 105 | 106 | //hw_timer_arm(50); 107 | } 108 | 109 | void user_init(void) 110 | { 111 | hw_timer_init(1); 112 | hw_timer_set_func(hw_test_timer_cb); 113 | hw_timer_arm(100); 114 | } 115 | #endif 116 | 117 | -------------------------------------------------------------------------------- /libesphttpd/lib/heatshrink/heatshrink_encoder.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | #ifndef HEATSHRINK_ENCODER_H 5 | #define HEATSHRINK_ENCODER_H 6 | 7 | #include 8 | #include 9 | #include "heatshrink_common.h" 10 | #include "heatshrink_config.h" 11 | 12 | typedef enum { 13 | HSER_SINK_OK, /* data sunk into input buffer */ 14 | HSER_SINK_ERROR_NULL=-1, /* NULL argument */ 15 | HSER_SINK_ERROR_MISUSE=-2, /* API misuse */ 16 | } HSE_sink_res; 17 | 18 | typedef enum { 19 | HSER_POLL_EMPTY, /* input exhausted */ 20 | HSER_POLL_MORE, /* poll again for more output */ 21 | HSER_POLL_ERROR_NULL=-1, /* NULL argument */ 22 | HSER_POLL_ERROR_MISUSE=-2, /* API misuse */ 23 | } HSE_poll_res; 24 | 25 | typedef enum { 26 | HSER_FINISH_DONE, /* encoding is complete */ 27 | HSER_FINISH_MORE, /* more output remaining; use poll */ 28 | HSER_FINISH_ERROR_NULL=-1, /* NULL argument */ 29 | } HSE_finish_res; 30 | 31 | #if HEATSHRINK_DYNAMIC_ALLOC 32 | #define HEATSHRINK_ENCODER_WINDOW_BITS(HSE) \ 33 | ((HSE)->window_sz2) 34 | #define HEATSHRINK_ENCODER_LOOKAHEAD_BITS(HSE) \ 35 | ((HSE)->lookahead_sz2) 36 | #define HEATSHRINK_ENCODER_INDEX(HSE) \ 37 | ((HSE)->search_index) 38 | struct hs_index { 39 | uint16_t size; 40 | int16_t index[]; 41 | }; 42 | #else 43 | #define HEATSHRINK_ENCODER_WINDOW_BITS(_) \ 44 | (HEATSHRINK_STATIC_WINDOW_BITS) 45 | #define HEATSHRINK_ENCODER_LOOKAHEAD_BITS(_) \ 46 | (HEATSHRINK_STATIC_LOOKAHEAD_BITS) 47 | #define HEATSHRINK_ENCODER_INDEX(HSE) \ 48 | (&(HSE)->search_index) 49 | struct hs_index { 50 | uint16_t size; 51 | int16_t index[2 << HEATSHRINK_STATIC_WINDOW_BITS]; 52 | }; 53 | #endif 54 | 55 | typedef struct { 56 | uint16_t input_size; /* bytes in input buffer */ 57 | uint16_t match_scan_index; 58 | uint16_t match_length; 59 | uint16_t match_pos; 60 | uint16_t outgoing_bits; /* enqueued outgoing bits */ 61 | uint8_t outgoing_bits_count; 62 | uint8_t flags; 63 | uint8_t state; /* current state machine node */ 64 | uint8_t current_byte; /* current byte of output */ 65 | uint8_t bit_index; /* current bit index */ 66 | #if HEATSHRINK_DYNAMIC_ALLOC 67 | uint8_t window_sz2; /* 2^n size of window */ 68 | uint8_t lookahead_sz2; /* 2^n size of lookahead */ 69 | #if HEATSHRINK_USE_INDEX 70 | struct hs_index *search_index; 71 | #endif 72 | /* input buffer and / sliding window for expansion */ 73 | uint8_t buffer[]; 74 | #else 75 | #if HEATSHRINK_USE_INDEX 76 | struct hs_index search_index; 77 | #endif 78 | /* input buffer and / sliding window for expansion */ 79 | uint8_t buffer[2 << HEATSHRINK_ENCODER_WINDOW_BITS(_)]; 80 | #endif 81 | } heatshrink_encoder; 82 | 83 | #if HEATSHRINK_DYNAMIC_ALLOC 84 | /* Allocate a new encoder struct and its buffers. 85 | * Returns NULL on error. */ 86 | heatshrink_encoder *heatshrink_encoder_alloc(uint8_t window_sz2, 87 | uint8_t lookahead_sz2); 88 | 89 | /* Free an encoder. */ 90 | void heatshrink_encoder_free(heatshrink_encoder *hse); 91 | #endif 92 | 93 | /* Reset an encoder. */ 94 | void heatshrink_encoder_reset(heatshrink_encoder *hse); 95 | 96 | /* Sink up to SIZE bytes from IN_BUF into the encoder. 97 | * INPUT_SIZE is set to the number of bytes actually sunk (in case a 98 | * buffer was filled.). */ 99 | HSE_sink_res heatshrink_encoder_sink(heatshrink_encoder *hse, 100 | uint8_t *in_buf, size_t size, size_t *input_size); 101 | 102 | /* Poll for output from the encoder, copying at most OUT_BUF_SIZE bytes into 103 | * OUT_BUF (setting *OUTPUT_SIZE to the actual amount copied). */ 104 | HSE_poll_res heatshrink_encoder_poll(heatshrink_encoder *hse, 105 | uint8_t *out_buf, size_t out_buf_size, size_t *output_size); 106 | 107 | /* Notify the encoder that the input stream is finished. 108 | * If the return value is HSER_FINISH_MORE, there is still more output, so 109 | * call heatshrink_encoder_poll and repeat. */ 110 | HSE_finish_res heatshrink_encoder_finish(heatshrink_encoder *hse); 111 | 112 | #endif 113 | 114 | #ifdef __cplusplus 115 | } 116 | #endif 117 | -------------------------------------------------------------------------------- /include/i2s_reg.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | #define DR_REG_I2S_BASE (0x60000e00) 5 | 6 | #define I2STXFIFO (DR_REG_I2S_BASE + 0x0000) 7 | #define I2SRXFIFO (DR_REG_I2S_BASE + 0x0004) 8 | #define I2SCONF (DR_REG_I2S_BASE + 0x0008) 9 | #define I2S_BCK_DIV_NUM 0x0000003F 10 | #define I2S_BCK_DIV_NUM_S 22 11 | #define I2S_CLKM_DIV_NUM 0x0000003F 12 | #define I2S_CLKM_DIV_NUM_S 16 13 | #define I2S_BITS_MOD 0x0000000F 14 | #define I2S_BITS_MOD_S 12 15 | #define I2S_RECE_MSB_SHIFT (BIT(11)) 16 | #define I2S_TRANS_MSB_SHIFT (BIT(10)) 17 | #define I2S_I2S_RX_START (BIT(9)) 18 | #define I2S_I2S_TX_START (BIT(8)) 19 | #define I2S_MSB_RIGHT (BIT(7)) 20 | #define I2S_RIGHT_FIRST (BIT(6)) 21 | #define I2S_RECE_SLAVE_MOD (BIT(5)) 22 | #define I2S_TRANS_SLAVE_MOD (BIT(4)) 23 | #define I2S_I2S_RX_FIFO_RESET (BIT(3)) 24 | #define I2S_I2S_TX_FIFO_RESET (BIT(2)) 25 | #define I2S_I2S_RX_RESET (BIT(1)) 26 | #define I2S_I2S_TX_RESET (BIT(0)) 27 | #define I2S_I2S_RESET_MASK 0xf 28 | 29 | #define I2SINT_RAW (DR_REG_I2S_BASE + 0x000c) 30 | #define I2S_I2S_TX_REMPTY_INT_RAW (BIT(5)) 31 | #define I2S_I2S_TX_WFULL_INT_RAW (BIT(4)) 32 | #define I2S_I2S_RX_REMPTY_INT_RAW (BIT(3)) 33 | #define I2S_I2S_RX_WFULL_INT_RAW (BIT(2)) 34 | #define I2S_I2S_TX_PUT_DATA_INT_RAW (BIT(1)) 35 | #define I2S_I2S_RX_TAKE_DATA_INT_RAW (BIT(0)) 36 | 37 | 38 | #define I2SINT_ST (DR_REG_I2S_BASE + 0x0010) 39 | #define I2S_I2S_TX_REMPTY_INT_ST (BIT(5)) 40 | #define I2S_I2S_TX_WFULL_INT_ST (BIT(4)) 41 | #define I2S_I2S_RX_REMPTY_INT_ST (BIT(3)) 42 | #define I2S_I2S_RX_WFULL_INT_ST (BIT(2)) 43 | #define I2S_I2S_TX_PUT_DATA_INT_ST (BIT(1)) 44 | #define I2S_I2S_RX_TAKE_DATA_INT_ST (BIT(0)) 45 | 46 | #define I2SINT_ENA (DR_REG_I2S_BASE + 0x0014) 47 | #define I2S_I2S_TX_REMPTY_INT_ENA (BIT(5)) 48 | #define I2S_I2S_TX_WFULL_INT_ENA (BIT(4)) 49 | #define I2S_I2S_RX_REMPTY_INT_ENA (BIT(3)) 50 | #define I2S_I2S_RX_WFULL_INT_ENA (BIT(2)) 51 | #define I2S_I2S_TX_PUT_DATA_INT_ENA (BIT(1)) 52 | #define I2S_I2S_RX_TAKE_DATA_INT_ENA (BIT(0)) 53 | 54 | #define I2SINT_CLR (DR_REG_I2S_BASE + 0x0018) 55 | #define I2S_I2S_TX_REMPTY_INT_CLR (BIT(5)) 56 | #define I2S_I2S_TX_WFULL_INT_CLR (BIT(4)) 57 | #define I2S_I2S_RX_REMPTY_INT_CLR (BIT(3)) 58 | #define I2S_I2S_RX_WFULL_INT_CLR (BIT(2)) 59 | #define I2S_I2S_PUT_DATA_INT_CLR (BIT(1)) 60 | #define I2S_I2S_TAKE_DATA_INT_CLR (BIT(0)) 61 | 62 | #define I2STIMING (DR_REG_I2S_BASE + 0x001c) 63 | #define I2S_TRANS_BCK_IN_INV (BIT(22)) 64 | #define I2S_RECE_DSYNC_SW (BIT(21)) 65 | #define I2S_TRANS_DSYNC_SW (BIT(20)) 66 | #define I2S_RECE_BCK_OUT_DELAY 0x00000003 67 | #define I2S_RECE_BCK_OUT_DELAY_S 18 68 | #define I2S_RECE_WS_OUT_DELAY 0x00000003 69 | #define I2S_RECE_WS_OUT_DELAY_S 16 70 | #define I2S_TRANS_SD_OUT_DELAY 0x00000003 71 | #define I2S_TRANS_SD_OUT_DELAY_S 14 72 | #define I2S_TRANS_WS_OUT_DELAY 0x00000003 73 | #define I2S_TRANS_WS_OUT_DELAY_S 12 74 | #define I2S_TRANS_BCK_OUT_DELAY 0x00000003 75 | #define I2S_TRANS_BCK_OUT_DELAY_S 10 76 | #define I2S_RECE_SD_IN_DELAY 0x00000003 77 | #define I2S_RECE_SD_IN_DELAY_S 8 78 | #define I2S_RECE_WS_IN_DELAY 0x00000003 79 | #define I2S_RECE_WS_IN_DELAY_S 6 80 | #define I2S_RECE_BCK_IN_DELAY 0x00000003 81 | #define I2S_RECE_BCK_IN_DELAY_S 4 82 | #define I2S_TRANS_WS_IN_DELAY 0x00000003 83 | #define I2S_TRANS_WS_IN_DELAY_S 2 84 | #define I2S_TRANS_BCK_IN_DELAY 0x00000003 85 | #define I2S_TRANS_BCK_IN_DELAY_S 0 86 | 87 | #define I2S_FIFO_CONF (DR_REG_I2S_BASE + 0x0020) 88 | #define I2S_I2S_RX_FIFO_MOD 0x00000007 89 | #define I2S_I2S_RX_FIFO_MOD_S 16 90 | #define I2S_I2S_TX_FIFO_MOD 0x00000007 91 | #define I2S_I2S_TX_FIFO_MOD_S 13 92 | #define I2S_I2S_DSCR_EN (BIT(12)) 93 | #define I2S_I2S_TX_DATA_NUM 0x0000003F 94 | #define I2S_I2S_TX_DATA_NUM_S 6 95 | #define I2S_I2S_RX_DATA_NUM 0x0000003F 96 | #define I2S_I2S_RX_DATA_NUM_S 0 97 | 98 | 99 | #define I2SRXEOF_NUM (DR_REG_I2S_BASE + 0x0024) 100 | #define I2S_I2S_RX_EOF_NUM 0xFFFFFFFF 101 | #define I2S_I2S_RX_EOF_NUM_S 0 102 | 103 | #define I2SCONF_SIGLE_DATA (DR_REG_I2S_BASE + 0x0028) 104 | #define I2S_I2S_SIGLE_DATA 0xFFFFFFFF 105 | #define I2S_I2S_SIGLE_DATA_S 0 106 | 107 | #define I2SCONF_CHAN (DR_REG_I2S_BASE + 0x002c) 108 | #define I2S_RX_CHAN_MOD 0x00000003 109 | #define I2S_RX_CHAN_MOD_S 3 110 | #define I2S_TX_CHAN_MOD 0x00000007 111 | #define I2S_TX_CHAN_MOD_S 0 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | #ifdef __cplusplus 123 | } 124 | #endif 125 | -------------------------------------------------------------------------------- /libesphttpd/lib/heatshrink/heatshrink_decoder.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | #ifndef HEATSHRINK_DECODER_H 5 | #define HEATSHRINK_DECODER_H 6 | 7 | #include 8 | #include 9 | #include "heatshrink_common.h" 10 | #include "heatshrink_config.h" 11 | 12 | typedef enum { 13 | HSDR_SINK_OK, /* data sunk, ready to poll */ 14 | HSDR_SINK_FULL, /* out of space in internal buffer */ 15 | HSDR_SINK_ERROR_NULL=-1, /* NULL argument */ 16 | } HSD_sink_res; 17 | 18 | typedef enum { 19 | HSDR_POLL_EMPTY, /* input exhausted */ 20 | HSDR_POLL_MORE, /* more data remaining, call again w/ fresh output buffer */ 21 | HSDR_POLL_ERROR_NULL=-1, /* NULL arguments */ 22 | HSDR_POLL_ERROR_UNKNOWN=-2, 23 | } HSD_poll_res; 24 | 25 | typedef enum { 26 | HSDR_FINISH_DONE, /* output is done */ 27 | HSDR_FINISH_MORE, /* more output remains */ 28 | HSDR_FINISH_ERROR_NULL=-1, /* NULL arguments */ 29 | } HSD_finish_res; 30 | 31 | #if HEATSHRINK_DYNAMIC_ALLOC 32 | #define HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(BUF) \ 33 | ((BUF)->input_buffer_size) 34 | #define HEATSHRINK_DECODER_WINDOW_BITS(BUF) \ 35 | ((BUF)->window_sz2) 36 | #define HEATSHRINK_DECODER_LOOKAHEAD_BITS(BUF) \ 37 | ((BUF)->lookahead_sz2) 38 | #else 39 | #define HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(_) \ 40 | HEATSHRINK_STATIC_INPUT_BUFFER_SIZE 41 | #define HEATSHRINK_DECODER_WINDOW_BITS(_) \ 42 | (HEATSHRINK_STATIC_WINDOW_BITS) 43 | #define HEATSHRINK_DECODER_LOOKAHEAD_BITS(BUF) \ 44 | (HEATSHRINK_STATIC_LOOKAHEAD_BITS) 45 | #endif 46 | 47 | typedef struct { 48 | uint16_t input_size; /* bytes in input buffer */ 49 | uint16_t input_index; /* offset to next unprocessed input byte */ 50 | uint16_t output_count; /* how many bytes to output */ 51 | uint16_t output_index; /* index for bytes to output */ 52 | uint16_t head_index; /* head of window buffer */ 53 | uint16_t bit_accumulator; 54 | uint8_t state; /* current state machine node */ 55 | uint8_t current_byte; /* current byte of input */ 56 | uint8_t bit_index; /* current bit index */ 57 | 58 | #if HEATSHRINK_DYNAMIC_ALLOC 59 | /* Fields that are only used if dynamically allocated. */ 60 | uint8_t window_sz2; /* window buffer bits */ 61 | uint8_t lookahead_sz2; /* lookahead bits */ 62 | uint16_t input_buffer_size; /* input buffer size */ 63 | 64 | /* Input buffer, then expansion window buffer */ 65 | uint8_t buffers[]; 66 | #else 67 | /* Input buffer, then expansion window buffer */ 68 | uint8_t buffers[(1 << HEATSHRINK_DECODER_WINDOW_BITS(_)) 69 | + HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(_)]; 70 | #endif 71 | } heatshrink_decoder; 72 | 73 | #if HEATSHRINK_DYNAMIC_ALLOC 74 | /* Allocate a decoder with an input buffer of INPUT_BUFFER_SIZE bytes, 75 | * an expansion buffer size of 2^WINDOW_SZ2, and a lookahead 76 | * size of 2^lookahead_sz2. (The window buffer and lookahead sizes 77 | * must match the settings used when the data was compressed.) 78 | * Returns NULL on error. */ 79 | heatshrink_decoder *heatshrink_decoder_alloc(uint16_t input_buffer_size, 80 | uint8_t expansion_buffer_sz2, uint8_t lookahead_sz2); 81 | 82 | /* Free a decoder. */ 83 | void heatshrink_decoder_free(heatshrink_decoder *hsd); 84 | #endif 85 | 86 | /* Reset a decoder. */ 87 | void heatshrink_decoder_reset(heatshrink_decoder *hsd); 88 | 89 | /* Sink at most SIZE bytes from IN_BUF into the decoder. *INPUT_SIZE is set to 90 | * indicate how many bytes were actually sunk (in case a buffer was filled). */ 91 | HSD_sink_res heatshrink_decoder_sink(heatshrink_decoder *hsd, 92 | uint8_t *in_buf, size_t size, size_t *input_size); 93 | 94 | /* Poll for output from the decoder, copying at most OUT_BUF_SIZE bytes into 95 | * OUT_BUF (setting *OUTPUT_SIZE to the actual amount copied). */ 96 | HSD_poll_res heatshrink_decoder_poll(heatshrink_decoder *hsd, 97 | uint8_t *out_buf, size_t out_buf_size, size_t *output_size); 98 | 99 | /* Notify the dencoder that the input stream is finished. 100 | * If the return value is HSDR_FINISH_MORE, there is still more output, so 101 | * call heatshrink_decoder_poll and repeat. */ 102 | HSD_finish_res heatshrink_decoder_finish(heatshrink_decoder *hsd); 103 | 104 | #endif 105 | 106 | #ifdef __cplusplus 107 | } 108 | #endif 109 | -------------------------------------------------------------------------------- /gen_misc.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | Rem ******NOTICE****** 4 | Rem MUST set SDK_PATH & BIN_PATH firstly!!! 5 | Rem example: 6 | Rem set SDK_PATH=/c/esp_iot_sdk_freertos 7 | Rem set BIN_PATH=/c/esp8266_bin 8 | 9 | set SDK_PATH="" 10 | set BIN_PATH="" 11 | 12 | echo gen_misc.bat version 20150911 13 | echo . 14 | 15 | if not %SDK_PATH% == "" ( 16 | echo SDK_PATH: %SDK_PATH% 17 | ) else ( 18 | echo ERROR: Please set SDK_PATH in gen_misc.bat firstly, exit!!! 19 | goto end 20 | ) 21 | 22 | if not %BIN_PATH% == "" ( 23 | echo BIN_PATH: %BIN_PATH% 24 | ) else ( 25 | echo ERROR: Please set BIN_PATH in gen_misc.bat firstly, exit!!! 26 | goto end 27 | ) 28 | 29 | echo . 30 | echo Please check SDK_PATH/BIN_PATH, enter (Y/y) to continue: 31 | set input=default 32 | set /p input= 33 | 34 | if not %input% == Y ( 35 | if not %input% == y ( 36 | goto end 37 | ) 38 | ) 39 | 40 | echo . 41 | echo Please follow below steps(1-5) to generate specific bin(s): 42 | echo STEP 1: use boot_v1.2+ by default 43 | set boot=new 44 | 45 | echo boot mode: %boot% 46 | echo. 47 | 48 | echo STEP 2: choose bin generate(0=eagle.flash.bin+eagle.irom0text.bin, 1=user1.bin, 2=user2.bin) 49 | set input=default 50 | set /p input=enter (0/1/2, default 0): 51 | 52 | if %input% equ 1 ( 53 | if %boot% equ none ( 54 | set app=0 55 | echo choose no boot before 56 | echo generate bin: eagle.flash.bin+eagle.irom0text.bin 57 | ) else ( 58 | set app=1 59 | echo generate bin: user1.bin 60 | ) 61 | ) else ( 62 | if %input% equ 2 ( 63 | if %boot% equ none ( 64 | set app=0 65 | echo choose no boot before 66 | echo generate bin: eagle.flash.bin+eagle.irom0text.bin 67 | ) else ( 68 | set app=2 69 | echo generate bin: user2.bin 70 | ) 71 | ) else ( 72 | if %boot% neq none ( 73 | set boot=none 74 | echo ignore boot 75 | ) 76 | set app=0 77 | echo generate bin: eagle.flash.bin+eagle.irom0text.bin 78 | )) 79 | 80 | echo. 81 | 82 | echo STEP 3: choose spi speed(0=20MHz, 1=26.7MHz, 2=40MHz, 3=80MHz) 83 | set input=default 84 | set /p input=enter (0/1/2/3, default 2): 85 | 86 | if %input% equ 0 ( 87 | set spi_speed=20 88 | ) else ( 89 | if %input% equ 1 ( 90 | set spi_speed=26.7 91 | ) else ( 92 | if %input% equ 3 ( 93 | set spi_speed=80 94 | ) else ( 95 | set spi_speed=40 96 | ))) 97 | 98 | echo spi speed: %spi_speed% MHz 99 | echo. 100 | 101 | echo STEP 4: choose spi mode(0=QIO, 1=QOUT, 2=DIO, 3=DOUT) 102 | set input=default 103 | set /p input=enter (0/1/2/3, default 0): 104 | 105 | if %input% equ 1 ( 106 | set spi_mode=QOUT 107 | ) else ( 108 | if %input% equ 2 ( 109 | set spi_mode=DIO 110 | ) else ( 111 | if %input% equ 3 ( 112 | set spi_mode=DOUT 113 | ) else ( 114 | set spi_mode=QIO 115 | ))) 116 | 117 | echo spi mode: %spi_mode% 118 | echo. 119 | 120 | echo STEP 5: choose flash size and map 121 | echo 0= 512KB( 256KB+ 256KB) 122 | echo 2=1024KB( 512KB+ 512KB) 123 | echo 3=2048KB( 512KB+ 512KB) 124 | echo 4=4096KB( 512KB+ 512KB) 125 | echo 5=2048KB(1024KB+1024KB) 126 | echo 6=4096KB(1024KB+1024KB) 127 | set input=default 128 | set /p input=enter (0/1/2/3/4/5/6, default 0): 129 | 130 | if %input% equ 2 ( 131 | set spi_size_map=2 132 | echo spi size: 1024KB 133 | echo spi ota map: 512KB + 512KB 134 | ) else ( 135 | if %input% equ 3 ( 136 | set spi_size_map=3 137 | echo spi size: 2048KB 138 | echo spi ota map: 512KB + 512KB 139 | ) else ( 140 | if %input% equ 4 ( 141 | set spi_size_map=4 142 | echo spi size: 4096KB 143 | echo spi ota map: 512KB + 512KB 144 | ) else ( 145 | if %input% equ 5 ( 146 | set spi_size_map=5 147 | echo spi size: 2048KB 148 | echo spi ota map: 1024KB + 1024KB 149 | ) else ( 150 | if %input% equ 6 ( 151 | set spi_size_map=6 152 | echo spi size: 4096KB 153 | echo spi ota map: 1024KB + 1024KB 154 | ) else ( 155 | set spi_size_map=0 156 | echo spi size: 512KB 157 | echo spi ota map: 256KB + 256KB 158 | ) 159 | ) 160 | ) 161 | ) 162 | ) 163 | 164 | echo. 165 | echo start... 166 | echo. 167 | 168 | make clean 169 | 170 | make COMPILE=xcc BOOT=%boot% APP=%app% SPI_SPEED=%spi_speed% SPI_MODE=%spi_mode% SPI_SIZE_MAP=%spi_size_map% 171 | 172 | :end -------------------------------------------------------------------------------- /gen_misc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | :< 5 | 6 | /// Handles acceleration via time dilatation. 7 | /** This class handles acceleration separately from the stepper 8 | * motor controllers. Instead of changing the stepper speed 9 | * directly this class helps to create a virtual, distorted 10 | * time frame in which the stepper motors are always at full 11 | * speed. Time itself moves slower at the start and end of 12 | * every movement, as controlled by variable rates. 13 | * 14 | * The variable rate comes from a variable numerator and a 15 | * constant denominator. The user can set the denominator 16 | * and the initial and final values of the numerator for each 17 | * movement. The numerator is incremented, kept, or decremented 18 | * once every step in oder to create the appropriate time 19 | * distortion for acceleration. 20 | */ 21 | struct Throttle { 22 | public: 23 | uint32_t n; //!< current output samples counter 24 | uint32_t n1; //!< output sample at which to start deceleration 25 | uint32_t N; //!< total output samples required 26 | 27 | uint32_t rd; //!< Rate denominator 28 | uint32_t r0; //!< Start rate numerator 29 | uint32_t r1; //!< End rate numerator 30 | uint32_t r; //!< Current rate 31 | int32_t acc; //!< accumulator 32 | 33 | bool paused; 34 | 35 | uint32_t min(uint32_t a, uint32_t b) { 36 | return (a> 31)); 38 | } 39 | 40 | public: 41 | /// Prepare time distortion for one movement. 42 | /** \param nN is the number of samples required for 43 | * the steppers to complete the movement. 44 | * \param nrd is the time rate denominator and is 45 | * inversely proportional to the acceleration. 46 | * Full speed will be reached after nrd-nr0 47 | * samples. 48 | * \param nr0 is the initial rate numerator. The initial 49 | * speed will be nr0/nrd times the speed 50 | * programmed for the stepper class. 51 | * \param nr1 is the final rate numerator. The final 52 | * speed will be nr1/nrd times the speed 53 | * programmed for the stepper class. 54 | */ 55 | void prepare( 56 | uint32_t nN, 57 | uint32_t nrd, 58 | uint32_t nr0, 59 | uint32_t nr1 60 | ) { 61 | n = 0; 62 | N = nN; 63 | rd = nrd; 64 | r0 = nr0; 65 | r1 = nr1 ? nr1 : 1; // Zero could cause a deadlock 66 | paused = false; 67 | 68 | acc = -int32_t(r0); // 1 sample delay, for DIR bits. 69 | r = r0; 70 | uint32_t dk = rd-r1; 71 | if (rd) n1 = N - dk + dk*1.*dk/(2.*rd); 72 | else n1 = 0; 73 | } 74 | 75 | Throttle() { 76 | prepare(0,0,0,0); 77 | } 78 | 79 | /// Evaluates one time step. 80 | /** Should be called once every real time sample, and 81 | * used to decide wether or not to evaluate the stepper 82 | * motion interpolators. 83 | * \return true if the steppers should be evaluated, or 84 | * false otherwise. 85 | */ 86 | bool step() { 87 | if (paused) { 88 | // On pause, decelerate gracefully to zero. 89 | if (r) r--; 90 | } else { 91 | // If before brake point 92 | if (n r1) r--; 98 | 99 | // On resume, accelerate to end-speed 100 | if (r < r1) r++; 101 | } 102 | } 103 | acc += r; 104 | if (acc > 0) { 105 | acc -= rd; 106 | if (n < N) n++; 107 | return true; 108 | } 109 | return false; 110 | } 111 | 112 | /// Detects wether the current movement is completed. 113 | /** \return true if movement is completed, or 114 | * false if movement is in progress. 115 | */ 116 | bool done() const { 117 | return n == N; 118 | } 119 | 120 | /// Pauses the movement halfway with deceleration. 121 | void pause() { 122 | paused = true; 123 | } 124 | 125 | /// Resumes the movement with acceleration. 126 | void resume() { 127 | paused = false; 128 | } 129 | }; 130 | 131 | #endif // THROTTLE_H 132 | 133 | /* N = total output steps 134 | * n = current step 135 | * n1 = steps until full-speed 136 | * 137 | * */ 138 | -------------------------------------------------------------------------------- /libesphttpd/core/sha1.c: -------------------------------------------------------------------------------- 1 | /* This code is public-domain - it is based on libcrypt 2 | * placed in the public domain by Wei Dai and other contributors. 3 | */ 4 | // gcc -Wall -DSHA1TEST -o sha1test sha1.c && ./sha1test 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "sha1.h" 11 | 12 | //according to http://ip.cadence.com/uploads/pdf/xtensalx_overview_handbook.pdf 13 | // the cpu is normally defined as little ending, but can be big endian too. 14 | // for the esp this seems to work 15 | //#define SHA_BIG_ENDIAN 16 | 17 | 18 | 19 | /* code */ 20 | #define SHA1_K0 0x5a827999 21 | #define SHA1_K20 0x6ed9eba1 22 | #define SHA1_K40 0x8f1bbcdc 23 | #define SHA1_K60 0xca62c1d6 24 | 25 | void ICACHE_FLASH_ATTR sha1_init(sha1nfo *s) { 26 | s->state[0] = 0x67452301; 27 | s->state[1] = 0xefcdab89; 28 | s->state[2] = 0x98badcfe; 29 | s->state[3] = 0x10325476; 30 | s->state[4] = 0xc3d2e1f0; 31 | s->byteCount = 0; 32 | s->bufferOffset = 0; 33 | } 34 | 35 | uint32_t ICACHE_FLASH_ATTR sha1_rol32(uint32_t number, uint8_t bits) { 36 | return ((number << bits) | (number >> (32-bits))); 37 | } 38 | 39 | void ICACHE_FLASH_ATTR sha1_hashBlock(sha1nfo *s) { 40 | uint8_t i; 41 | uint32_t a,b,c,d,e,t; 42 | 43 | a=s->state[0]; 44 | b=s->state[1]; 45 | c=s->state[2]; 46 | d=s->state[3]; 47 | e=s->state[4]; 48 | for (i=0; i<80; i++) { 49 | if (i>=16) { 50 | t = s->buffer[(i+13)&15] ^ s->buffer[(i+8)&15] ^ s->buffer[(i+2)&15] ^ s->buffer[i&15]; 51 | s->buffer[i&15] = sha1_rol32(t,1); 52 | } 53 | if (i<20) { 54 | t = (d ^ (b & (c ^ d))) + SHA1_K0; 55 | } else if (i<40) { 56 | t = (b ^ c ^ d) + SHA1_K20; 57 | } else if (i<60) { 58 | t = ((b & c) | (d & (b | c))) + SHA1_K40; 59 | } else { 60 | t = (b ^ c ^ d) + SHA1_K60; 61 | } 62 | t+=sha1_rol32(a,5) + e + s->buffer[i&15]; 63 | e=d; 64 | d=c; 65 | c=sha1_rol32(b,30); 66 | b=a; 67 | a=t; 68 | } 69 | s->state[0] += a; 70 | s->state[1] += b; 71 | s->state[2] += c; 72 | s->state[3] += d; 73 | s->state[4] += e; 74 | } 75 | 76 | void ICACHE_FLASH_ATTR sha1_addUncounted(sha1nfo *s, uint8_t data) { 77 | uint8_t * const b = (uint8_t*) s->buffer; 78 | #ifdef SHA_BIG_ENDIAN 79 | b[s->bufferOffset] = data; 80 | #else 81 | b[s->bufferOffset ^ 3] = data; 82 | #endif 83 | s->bufferOffset++; 84 | if (s->bufferOffset == BLOCK_LENGTH) { 85 | sha1_hashBlock(s); 86 | s->bufferOffset = 0; 87 | } 88 | } 89 | 90 | void ICACHE_FLASH_ATTR sha1_writebyte(sha1nfo *s, uint8_t data) { 91 | ++s->byteCount; 92 | sha1_addUncounted(s, data); 93 | } 94 | 95 | void ICACHE_FLASH_ATTR sha1_write(sha1nfo *s, const char *data, size_t len) { 96 | for (;len--;) sha1_writebyte(s, (uint8_t) *data++); 97 | } 98 | 99 | void ICACHE_FLASH_ATTR sha1_pad(sha1nfo *s) { 100 | // Implement SHA-1 padding (fips180-2 §5.1.1) 101 | 102 | // Pad with 0x80 followed by 0x00 until the end of the block 103 | sha1_addUncounted(s, 0x80); 104 | while (s->bufferOffset != 56) sha1_addUncounted(s, 0x00); 105 | 106 | // Append length in the last 8 bytes 107 | sha1_addUncounted(s, 0); // We're only using 32 bit lengths 108 | sha1_addUncounted(s, 0); // But SHA-1 supports 64 bit lengths 109 | sha1_addUncounted(s, 0); // So zero pad the top bits 110 | sha1_addUncounted(s, s->byteCount >> 29); // Shifting to multiply by 8 111 | sha1_addUncounted(s, s->byteCount >> 21); // as SHA-1 supports bitstreams as well as 112 | sha1_addUncounted(s, s->byteCount >> 13); // byte. 113 | sha1_addUncounted(s, s->byteCount >> 5); 114 | sha1_addUncounted(s, s->byteCount << 3); 115 | } 116 | 117 | uint8_t* ICACHE_FLASH_ATTR sha1_result(sha1nfo *s) { 118 | // Pad to complete the last block 119 | sha1_pad(s); 120 | 121 | #ifndef SHA_BIG_ENDIAN 122 | // Swap byte order back 123 | int i; 124 | for (i=0; i<5; i++) { 125 | s->state[i]= 126 | (((s->state[i])<<24)& 0xff000000) 127 | | (((s->state[i])<<8) & 0x00ff0000) 128 | | (((s->state[i])>>8) & 0x0000ff00) 129 | | (((s->state[i])>>24)& 0x000000ff); 130 | } 131 | #endif 132 | 133 | // Return pointer to hash (20 characters) 134 | return (uint8_t*) s->state; 135 | } 136 | 137 | #define HMAC_IPAD 0x36 138 | #define HMAC_OPAD 0x5c 139 | 140 | void ICACHE_FLASH_ATTR sha1_initHmac(sha1nfo *s, const uint8_t* key, int keyLength) { 141 | uint8_t i; 142 | memset(s->keyBuffer, 0, BLOCK_LENGTH); 143 | if (keyLength > BLOCK_LENGTH) { 144 | // Hash long keys 145 | sha1_init(s); 146 | for (;keyLength--;) sha1_writebyte(s, *key++); 147 | memcpy(s->keyBuffer, sha1_result(s), HASH_LENGTH); 148 | } else { 149 | // Block length keys are used as is 150 | memcpy(s->keyBuffer, key, keyLength); 151 | } 152 | // Start inner hash 153 | sha1_init(s); 154 | for (i=0; ikeyBuffer[i] ^ HMAC_IPAD); 156 | } 157 | } 158 | 159 | uint8_t* ICACHE_FLASH_ATTR sha1_resultHmac(sha1nfo *s) { 160 | uint8_t i; 161 | // Complete inner hash 162 | memcpy(s->innerHash,sha1_result(s),HASH_LENGTH); 163 | // Calculate outer hash 164 | sha1_init(s); 165 | for (i=0; ikeyBuffer[i] ^ HMAC_OPAD); 166 | for (i=0; iinnerHash[i]); 167 | return sha1_result(s); 168 | } 169 | -------------------------------------------------------------------------------- /libesphttpd/lib/heatshrink/test_heatshrink_static.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "heatshrink_encoder.h" 5 | #include "heatshrink_decoder.h" 6 | #include "greatest.h" 7 | 8 | #if HEATSHRINK_DYNAMIC_ALLOC 9 | #error HEATSHRINK_DYNAMIC_ALLOC must be false for static allocation test suite. 10 | #endif 11 | 12 | SUITE(integration); 13 | 14 | /* The majority of the tests are in test_heatshrink_dynamic, because that allows 15 | * instantiating encoders/decoders with different settings at run-time. */ 16 | 17 | static heatshrink_encoder hse; 18 | static heatshrink_decoder hsd; 19 | 20 | static void fill_with_pseudorandom_letters(uint8_t *buf, uint16_t size, uint32_t seed) { 21 | uint64_t rn = 9223372036854775783; /* prime under 2^64 */ 22 | for (int i=0; i 1) { 50 | printf("\n^^ COMPRESSING\n"); 51 | dump_buf("input", input, input_size); 52 | } 53 | 54 | uint32_t sunk = 0; 55 | uint32_t polled = 0; 56 | while (sunk < input_size) { 57 | ASSERT(heatshrink_encoder_sink(&hse, &input[sunk], input_size - sunk, &count) >= 0); 58 | sunk += count; 59 | if (log_lvl > 1) printf("^^ sunk %zd\n", count); 60 | if (sunk == input_size) { 61 | ASSERT_EQ(HSER_FINISH_MORE, heatshrink_encoder_finish(&hse)); 62 | } 63 | 64 | HSE_poll_res pres; 65 | do { /* "turn the crank" */ 66 | pres = heatshrink_encoder_poll(&hse, &comp[polled], comp_sz - polled, &count); 67 | ASSERT(pres >= 0); 68 | polled += count; 69 | if (log_lvl > 1) printf("^^ polled %zd\n", count); 70 | } while (pres == HSER_POLL_MORE); 71 | ASSERT_EQ(HSER_POLL_EMPTY, pres); 72 | if (polled >= comp_sz) FAILm("compression should never expand that much"); 73 | if (sunk == input_size) { 74 | ASSERT_EQ(HSER_FINISH_DONE, heatshrink_encoder_finish(&hse)); 75 | } 76 | } 77 | if (log_lvl > 0) printf("in: %u compressed: %u ", input_size, polled); 78 | uint32_t compressed_size = polled; 79 | sunk = 0; 80 | polled = 0; 81 | 82 | if (log_lvl > 1) { 83 | printf("\n^^ DECOMPRESSING\n"); 84 | dump_buf("comp", comp, compressed_size); 85 | } 86 | while (sunk < compressed_size) { 87 | ASSERT(heatshrink_decoder_sink(&hsd, &comp[sunk], compressed_size - sunk, &count) >= 0); 88 | sunk += count; 89 | if (log_lvl > 1) printf("^^ sunk %zd\n", count); 90 | if (sunk == compressed_size) { 91 | ASSERT_EQ(HSDR_FINISH_MORE, heatshrink_decoder_finish(&hsd)); 92 | } 93 | 94 | HSD_poll_res pres; 95 | do { 96 | pres = heatshrink_decoder_poll(&hsd, &decomp[polled], 97 | decomp_sz - polled, &count); 98 | ASSERT(pres >= 0); 99 | polled += count; 100 | if (log_lvl > 1) printf("^^ polled %zd\n", count); 101 | } while (pres == HSDR_POLL_MORE); 102 | ASSERT_EQ(HSDR_POLL_EMPTY, pres); 103 | if (sunk == compressed_size) { 104 | HSD_finish_res fres = heatshrink_decoder_finish(&hsd); 105 | ASSERT_EQ(HSDR_FINISH_DONE, fres); 106 | } 107 | 108 | if (polled > input_size) { 109 | FAILm("Decompressed data is larger than original input"); 110 | } 111 | } 112 | if (log_lvl > 0) printf("decompressed: %u\n", polled); 113 | if (polled != input_size) { 114 | FAILm("Decompressed length does not match original input length"); 115 | } 116 | 117 | if (log_lvl > 1) dump_buf("decomp", decomp, polled); 118 | for (size_t i=0; i out[%zd] == 0x%02x ('%c')\n", 124 | j, input[j], isprint(input[j]) ? input[j] : '.', 125 | j, decomp[j], isprint(decomp[j]) ? decomp[j] : '.'); 126 | } 127 | } 128 | } 129 | ASSERT_EQ(input[i], decomp[i]); 130 | } 131 | free(comp); 132 | free(decomp); 133 | PASS(); 134 | } 135 | 136 | TEST pseudorandom_data_should_match(uint32_t size, uint32_t seed) { 137 | uint8_t input[size]; 138 | fill_with_pseudorandom_letters(input, size, seed); 139 | return compress_and_expand_and_check(input, size, 0); 140 | } 141 | 142 | SUITE(integration) { 143 | #if __STDC_VERSION__ >= 19901L 144 | for (uint32_t size=1; size < 64*1024; size <<= 1) { 145 | if (GREATEST_IS_VERBOSE()) printf(" -- size %u\n", size); 146 | for (uint32_t seed=1; seed<=100; seed++) { 147 | if (GREATEST_IS_VERBOSE()) printf(" -- seed %u\n", seed); 148 | RUN_TESTp(pseudorandom_data_should_match, size, seed); 149 | } 150 | } 151 | #endif 152 | } 153 | 154 | /* Add all the definitions that need to be in the test runner's main file. */ 155 | GREATEST_MAIN_DEFS(); 156 | 157 | int main(int argc, char **argv) { 158 | GREATEST_MAIN_BEGIN(); /* command-line arguments, initialization. */ 159 | printf("INPUT_BUFFER_SIZE: %u\n", HEATSHRINK_STATIC_INPUT_BUFFER_SIZE); 160 | printf("WINDOW_BITS: %u\n", HEATSHRINK_STATIC_WINDOW_BITS); 161 | printf("LOOKAHEAD_BITS: %u\n", HEATSHRINK_STATIC_LOOKAHEAD_BITS); 162 | 163 | printf("sizeof(heatshrink_encoder): %zd\n", sizeof(heatshrink_encoder)); 164 | printf("sizeof(heatshrink_decoder): %zd\n", sizeof(heatshrink_decoder)); 165 | RUN_SUITE(integration); 166 | GREATEST_MAIN_END(); /* display results */ 167 | } 168 | -------------------------------------------------------------------------------- /libesphttpd/core/httpdespfs.c: -------------------------------------------------------------------------------- 1 | /* 2 | Connector to let httpd use the espfs filesystem to serve the files in it. 3 | */ 4 | 5 | /* 6 | * ---------------------------------------------------------------------------- 7 | * "THE BEER-WARE LICENSE" (Revision 42): 8 | * Jeroen Domburg wrote this file. As long as you retain 9 | * this notice you can do whatever you want with this stuff. If we meet some day, 10 | * and you think this stuff is worth it, you can buy me a beer in return. 11 | * ---------------------------------------------------------------------------- 12 | */ 13 | 14 | #include 15 | #include "httpdespfs.h" 16 | #include "espfs.h" 17 | #include "espfsformat.h" 18 | 19 | // The static files marked with FLAG_GZIP are compressed and will be served with GZIP compression. 20 | // If the client does not advertise that he accepts GZIP send following warning message (telnet users for e.g.) 21 | static const char *gzipNonSupportedMessage = "HTTP/1.0 501 Not implemented\r\nServer: esp8266-httpd/"HTTPDVER"\r\nConnection: close\r\nContent-Type: text/plain\r\nContent-Length: 52\r\n\r\nYour browser does not accept gzip-compressed data.\r\n"; 22 | 23 | 24 | //This is a catch-all cgi function. It takes the url passed to it, looks up the corresponding 25 | //path in the filesystem and if it exists, passes the file through. This simulates what a normal 26 | //webserver would do with static files. 27 | int ICACHE_FLASH_ATTR cgiEspFsHook(HttpdConnData *connData) { 28 | EspFsFile *file=connData->cgiData; 29 | int len; 30 | char buff[1024]; 31 | char acceptEncodingBuffer[64]; 32 | int isGzip; 33 | 34 | if (connData->conn==NULL) { 35 | //Connection aborted. Clean up. 36 | espFsClose(file); 37 | return HTTPD_CGI_DONE; 38 | } 39 | 40 | //First call to this cgi. 41 | if (file==NULL) { 42 | if (connData->cgiArg != NULL) { 43 | //Open a different file than provided in http request. 44 | //Common usage: {"/", cgiEspFsHook, "/index.html"} will show content of index.html without actual redirect to that file if host root was requested 45 | file = espFsOpen((char*)connData->cgiArg); 46 | } else { 47 | //Open the file so we can read it. 48 | file = espFsOpen(connData->url); 49 | } 50 | 51 | if (file==NULL) { 52 | return HTTPD_CGI_NOTFOUND; 53 | } 54 | 55 | // The gzip checking code is intentionally without #ifdefs because checking 56 | // for FLAG_GZIP (which indicates gzip compressed file) is very easy, doesn't 57 | // mean additional overhead and is actually safer to be on at all times. 58 | // If there are no gzipped files in the image, the code bellow will not cause any harm. 59 | 60 | // Check if requested file was GZIP compressed 61 | isGzip = espFsFlags(file) & FLAG_GZIP; 62 | if (isGzip) { 63 | // Check the browser's "Accept-Encoding" header. If the client does not 64 | // advertise that he accepts GZIP send a warning message (telnet users for e.g.) 65 | httpdGetHeader(connData, "Accept-Encoding", acceptEncodingBuffer, 64); 66 | if (strstr(acceptEncodingBuffer, "gzip") == NULL) { 67 | //No Accept-Encoding: gzip header present 68 | httpdSend(connData, gzipNonSupportedMessage, -1); 69 | espFsClose(file); 70 | return HTTPD_CGI_DONE; 71 | } 72 | } 73 | 74 | connData->cgiData=file; 75 | httpdStartResponse(connData, 200); 76 | httpdHeader(connData, "Content-Type", httpdGetMimetype(connData->url)); 77 | if (isGzip) { 78 | httpdHeader(connData, "Content-Encoding", "gzip"); 79 | } 80 | httpdHeader(connData, "Cache-Control", "max-age=3600, must-revalidate"); 81 | httpdEndHeaders(connData); 82 | return HTTPD_CGI_MORE; 83 | } 84 | 85 | len=espFsRead(file, buff, 1024); 86 | if (len>0) httpdSend(connData, buff, len); 87 | if (len!=1024) { 88 | //We're done. 89 | espFsClose(file); 90 | return HTTPD_CGI_DONE; 91 | } else { 92 | //Ok, till next time. 93 | return HTTPD_CGI_MORE; 94 | } 95 | } 96 | 97 | 98 | //cgiEspFsTemplate can be used as a template. 99 | 100 | typedef struct { 101 | EspFsFile *file; 102 | void *tplArg; 103 | char token[64]; 104 | int tokenPos; 105 | } TplData; 106 | 107 | typedef void (* TplCallback)(HttpdConnData *connData, char *token, void **arg); 108 | 109 | int ICACHE_FLASH_ATTR cgiEspFsTemplate(HttpdConnData *connData) { 110 | TplData *tpd=connData->cgiData; 111 | int len; 112 | int x, sp=0; 113 | char *e=NULL; 114 | char buff[1025]; 115 | 116 | if (connData->conn==NULL) { 117 | //Connection aborted. Clean up. 118 | ((TplCallback)(connData->cgiArg))(connData, NULL, &tpd->tplArg); 119 | espFsClose(tpd->file); 120 | free(tpd); 121 | return HTTPD_CGI_DONE; 122 | } 123 | 124 | if (tpd==NULL) { 125 | //First call to this cgi. Open the file so we can read it. 126 | tpd=(TplData *)malloc(sizeof(TplData)); 127 | if (tpd==NULL) return HTTPD_CGI_NOTFOUND; 128 | tpd->file=espFsOpen(connData->url); 129 | tpd->tplArg=NULL; 130 | tpd->tokenPos=-1; 131 | if (tpd->file==NULL) { 132 | espFsClose(tpd->file); 133 | free(tpd); 134 | return HTTPD_CGI_NOTFOUND; 135 | } 136 | if (espFsFlags(tpd->file) & FLAG_GZIP) { 137 | httpd_printf("cgiEspFsTemplate: Trying to use gzip-compressed file %s as template!\n", connData->url); 138 | espFsClose(tpd->file); 139 | free(tpd); 140 | return HTTPD_CGI_NOTFOUND; 141 | } 142 | connData->cgiData=tpd; 143 | httpdStartResponse(connData, 200); 144 | httpdHeader(connData, "Content-Type", httpdGetMimetype(connData->url)); 145 | httpdEndHeaders(connData); 146 | return HTTPD_CGI_MORE; 147 | } 148 | 149 | len=espFsRead(tpd->file, buff, 1024); 150 | if (len>0) { 151 | sp=0; 152 | e=buff; 153 | for (x=0; xtokenPos==-1) { 155 | //Inside ordinary text. 156 | if (buff[x]=='%') { 157 | //Send raw data up to now 158 | if (sp!=0) httpdSend(connData, e, sp); 159 | sp=0; 160 | //Go collect token chars. 161 | tpd->tokenPos=0; 162 | } else { 163 | sp++; 164 | } 165 | } else { 166 | if (buff[x]=='%') { 167 | if (tpd->tokenPos==0) { 168 | //This is the second % of a %% escape string. 169 | //Send a single % and resume with the normal program flow. 170 | httpdSend(connData, "%", 1); 171 | } else { 172 | //This is an actual token. 173 | tpd->token[tpd->tokenPos++]=0; //zero-terminate token 174 | ((TplCallback)(connData->cgiArg))(connData, tpd->token, &tpd->tplArg); 175 | } 176 | //Go collect normal chars again. 177 | e=&buff[x+1]; 178 | tpd->tokenPos=-1; 179 | } else { 180 | if (tpd->tokenPos<(sizeof(tpd->token)-1)) tpd->token[tpd->tokenPos++]=buff[x]; 181 | } 182 | } 183 | } 184 | } 185 | //Send remaining bit. 186 | if (sp!=0) httpdSend(connData, e, sp); 187 | if (len!=1024) { 188 | //We're done. 189 | ((TplCallback)(connData->cgiArg))(connData, NULL, &tpd->tplArg); 190 | espFsClose(tpd->file); 191 | free(tpd); 192 | return HTTPD_CGI_DONE; 193 | } else { 194 | //Ok, till next time. 195 | return HTTPD_CGI_MORE; 196 | } 197 | } 198 | 199 | -------------------------------------------------------------------------------- /user/user_main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * ESPRSSIF MIT License 3 | * 4 | * Copyright (c) 2015 5 | * 6 | * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, 7 | * it is free of charge, to any person obtaining a copy of this software and associated 8 | * documentation files (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished 11 | * to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all copies or 14 | * substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | * 23 | */ 24 | 25 | #include "esp_common.h" 26 | #include "esp_system.h" 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include "cgi-test.h" 39 | #include 40 | #include 41 | #include "reprap_core.h" 42 | 43 | int __errno; 44 | 45 | //On reception of a message, echo it back verbatim 46 | void myEchoWebsocketRecv(Websock *ws, char *data, int len, int flags) { 47 | os_printf("EchoWs: echo, len=%d\n", len); 48 | cgiWebsocketSend(ws, data, len, flags); 49 | } 50 | 51 | //Echo websocket connected. Install reception handler. 52 | void myEchoWebsocketConnect(Websock *ws) { 53 | os_printf("EchoWs: connect\n"); 54 | ws->recvCb=myEchoWebsocketRecv; 55 | } 56 | 57 | //On reception of a message, echo it back verbatim 58 | double getAFuckingDouble(cJSON *object) { 59 | if (!object) return NAN; 60 | switch (object->type & 0xff) { 61 | case cJSON_False: return 0; 62 | case cJSON_True: return 1; 63 | case cJSON_NULL: return 0; 64 | case cJSON_Number: return object->valuedouble; 65 | case cJSON_String: return atoi(object->valuestring); 66 | case cJSON_Array: return NAN; 67 | case cJSON_Object: return NAN; 68 | } 69 | } 70 | void myBhaskaraSolver_onMessage(Websock *ws, char *data, int len, int flags) { 71 | double a,b,c,d, x1, x2; 72 | char *str; 73 | cJSON *root; 74 | 75 | os_printf("BHWS: Got data!\n"); 76 | for (str=data; str-data < len; ++str) os_putc(*str); 77 | 78 | root = cJSON_Parse(data); 79 | if (!root) { 80 | os_printf("BhaskaraWs: Bad JSON data:\n"); 81 | 82 | root = cJSON_CreateNull(); 83 | str = cJSON_Print(root); 84 | } else { 85 | a = getAFuckingDouble(cJSON_GetObjectItem(root,"a")); 86 | b = getAFuckingDouble(cJSON_GetObjectItem(root,"b")); 87 | c = getAFuckingDouble(cJSON_GetObjectItem(root,"c")); 88 | 89 | cJSON_Delete(root); 90 | 91 | root = cJSON_CreateObject(); 92 | 93 | d = b*b - 4*a*c; 94 | if (d>=0) { // Real responses 95 | x1 = (-b - sqrt(d)) / (2*a); 96 | x2 = (-b + sqrt(d)) / (2*a); 97 | 98 | cJSON_AddItemToObjectCS(root,"isComplex", cJSON_CreateFalse()); 99 | cJSON_AddItemToObjectCS(root,"x1", cJSON_CreateNumber(x1)); 100 | cJSON_AddItemToObjectCS(root,"x2", cJSON_CreateNumber(x2)); 101 | } else { // Complex 102 | x1 = (-b) / (2*a); // Real 103 | x2 = sqrt(-d) / (2*a); // imaginary 104 | 105 | cJSON_AddItemToObjectCS(root,"isComplex", cJSON_CreateTrue()); 106 | cJSON_AddItemToObjectCS(root,"real", cJSON_CreateNumber(x1)); 107 | cJSON_AddItemToObjectCS(root,"imag", cJSON_CreateNumber(1));//x2)); 108 | } 109 | 110 | os_printf("BhaskaraWs: a=%d, b=%d, c=%d ==> x1=%d, x2=%d.\n", 111 | (int)a, (int)b, (int)c, (int)x1, (int)x2 112 | ); 113 | 114 | str = cJSON_Print(root); 115 | } 116 | 117 | cgiWebsocketSend(ws, str, strlen(str), flags); 118 | 119 | free(str); 120 | cJSON_Delete(root); 121 | } 122 | 123 | // Echo websocket connected. Install reception handler. 124 | void myBhaskaraSolver_onOpen(Websock *ws) { 125 | os_printf("BhaskaraWs: connect\n"); 126 | ws->recvCb=myBhaskaraSolver_onMessage; 127 | } 128 | 129 | HttpdBuiltInUrl builtInUrls[]={ 130 | {"/cgiTestbed", cgiTestbed, NULL}, 131 | {"/websocket/echo.cgi", cgiWebsocket, (void*)myEchoWebsocketConnect}, 132 | {"/websocket/bhaskara.cgi", cgiWebsocket, (void*)myBhaskaraSolver_onOpen}, 133 | {"/", cgiRedirect, "/index.html"}, 134 | {"*", cgiEspFsHook, NULL}, 135 | {NULL, NULL, NULL} 136 | }; 137 | 138 | // RTOS Task 139 | void myTask(void *pdParameters) { 140 | while(1) { 141 | // Delay 1 second 142 | vTaskDelay(configTICK_RATE_HZ); 143 | 144 | os_printf("myTask: Still alive...\n"); 145 | } 146 | } 147 | 148 | /****************************************************************************** 149 | * FunctionName : user_init 150 | * Description : entry of user application, init user function here 151 | * Parameters : none 152 | * Returns : none 153 | *******************************************************************************/ 154 | extern "C" void user_init(void) { 155 | system_update_cpu_freq(SYS_CPU_160MHZ); 156 | 157 | UART_SetPrintPort(UART0); 158 | UART_SetBaudrate(UART0, 115200); 159 | os_printf("SDK version:%s\n", system_get_sdk_version()); 160 | 161 | #ifdef ESPFS_POS 162 | espFsInit((void*)(0x40200000 + ESPFS_POS)); 163 | #else 164 | espFsInit((void*)(webpages_espfs_start)); 165 | #endif 166 | httpdInit(builtInUrls, 80); 167 | 168 | if (pdPASS == xTaskCreate( 169 | &myTask, 170 | (signed char *)"myTask", 171 | 1024, // unsigned portSHORT usStackDepth, 172 | 0, // void *pvParameters, 173 | 6, // unsigned portBASE_TYPE uxPriority, 174 | 0 // xTaskHandle *pvCreatedTask 175 | )) { 176 | os_printf("Creating myTask succeeded.\n"); 177 | } else { 178 | os_printf("Creating myTask failed.\n"); 179 | } 180 | 181 | if (pdPASS == xTaskCreate( 182 | &reprap_core_task, 183 | (signed char *)"reprap_core", 184 | 1024, // unsigned portSHORT usStackDepth, 185 | 0, // void *pvParameters, 186 | 10, // unsigned portBASE_TYPE uxPriority, 187 | 0 // xTaskHandle *pvCreatedTask 188 | )) { 189 | os_printf("Creating myTask succeeded.\n"); 190 | } else { 191 | os_printf("Creating myTask failed.\n"); 192 | } 193 | } 194 | 195 | -------------------------------------------------------------------------------- /libesphttpd/Makefile: -------------------------------------------------------------------------------- 1 | 2 | # Directory the Makefile is in. Please don't include other Makefiles before this. 3 | THISDIR:=$(dir $(abspath $(lastword $(MAKEFILE_LIST)))) 4 | 5 | #Include httpd config from lower level, if it exists 6 | -include ../esphttpdconfig.mk 7 | 8 | #Default options. If you want to change them, please create ../esphttpdconfig.mk with the options you want in it. 9 | GZIP_COMPRESSION ?= no 10 | COMPRESS_W_YUI ?= no 11 | YUI-COMPRESSOR ?= /usr/bin/yui-compressor 12 | USE_HEATSHRINK ?= yes 13 | HTTPD_WEBSOCKETS ?= yes 14 | USE_OPENSDK ?= no 15 | HTTPD_MAX_CONNECTIONS ?= 4 16 | #For FreeRTOS 17 | HTTPD_STACKSIZE ?= 2048 18 | #Auto-detect ESP32 build if not given. 19 | ifneq (,$(wildcard $(SDK_PATH)/include/esp32)) 20 | ESP32 ?= yes 21 | FREERTOS ?= yes 22 | else 23 | ESP32 ?= no 24 | FREERTOS ?= no 25 | endif 26 | 27 | # Output directors to store intermediate compiled files 28 | # relative to the project directory 29 | BUILD_BASE = build 30 | 31 | # Base directory for the compiler. Needs a / at the end; if not set it'll use the tools that are in 32 | # the PATH. 33 | XTENSA_TOOLS_ROOT ?= 34 | 35 | # base directory of the ESP8266 SDK package, absolute 36 | # Only used for the non-FreeRTOS build 37 | SDK_BASE ?= /opt/Espressif/ESP8266_SDK 38 | 39 | # Base directory of the ESP8266 FreeRTOS SDK package, absolute 40 | # Only used for the FreeRTOS build 41 | SDK_PATH ?= /opt/Espressif/ESP8266_RTOS_SDK 42 | 43 | 44 | # name for the target project 45 | LIB = libesphttpd.a 46 | 47 | # which modules (subdirectories) of the project to include in compiling 48 | MODULES = espfs core util 49 | EXTRA_INCDIR = ./include \ 50 | . \ 51 | lib/heatshrink/ 52 | 53 | 54 | # compiler flags using during compilation of source files 55 | CFLAGS = -Os -ggdb -std=c99 -Werror -Wpointer-arith -Wundef -Wall -Wl,-EL -fno-inline-functions \ 56 | -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH \ 57 | -Wno-address -DHTTPD_MAX_CONNECTIONS=$(HTTPD_MAX_CONNECTIONS) -DHTTPD_STACKSIZE=$(HTTPD_STACKSIZE) \ 58 | 59 | 60 | # various paths from the SDK used in this project 61 | SDK_LIBDIR = lib 62 | SDK_LDDIR = ld 63 | 64 | 65 | ifeq ("$(FREERTOS)","yes") 66 | CFLAGS += -DFREERTOS -DLWIP_OPEN_SRC -ffunction-sections -fdata-sections 67 | ifeq ("$(ESP32)","yes") 68 | SDK_INCDIR = include \ 69 | include/esp32 \ 70 | driver_lib/include \ 71 | extra_include \ 72 | third_party/include \ 73 | third_party/include/cjson \ 74 | third_party/include/freertos \ 75 | third_party/include/lwip \ 76 | third_party/include/lwip/ipv4 \ 77 | third_party/include/lwip/ipv6 \ 78 | third_party/include/ssl 79 | CFLAGS += -DESP32 -DFREERTOS -DLWIP_OPEN_SRC -ffunction-sections -fdata-sections 80 | else 81 | SDK_INCDIR = include \ 82 | include/freertos \ 83 | include/espressif/esp8266 \ 84 | include/espressif \ 85 | extra_include \ 86 | include/lwip \ 87 | include/lwip/lwip \ 88 | include/lwip/ipv4 \ 89 | include/lwip/ipv6 90 | CFLAGS += -DFREERTOS -DLWIP_OPEN_SRC -ffunction-sections -fdata-sections 91 | endif 92 | SDK_INCDIR := $(addprefix -I$(SDK_PATH)/,$(SDK_INCDIR)) 93 | else 94 | SDK_INCDIR = include 95 | SDK_INCDIR := $(addprefix -I$(SDK_BASE)/,$(SDK_INCDIR)) 96 | endif 97 | 98 | 99 | ifeq ("$(ESP32)","yes") 100 | TOOLPREFIX=xtensa-esp108-elf- 101 | CFLAGS+=-DESP32 102 | else 103 | TOOLPREFIX=xtensa-lx106-elf- 104 | endif 105 | 106 | # select which tools to use as compiler, librarian and linker 107 | CC := $(XTENSA_TOOLS_ROOT)$(TOOLPREFIX)gcc 108 | AR := $(XTENSA_TOOLS_ROOT)$(TOOLPREFIX)ar 109 | LD := $(XTENSA_TOOLS_ROOT)$(TOOLPREFIX)gcc 110 | OBJCOPY := $(XTENSA_TOOLS_ROOT)$(TOOLPREFIX)objcopy 111 | 112 | #### 113 | #### no user configurable options below here 114 | #### 115 | SRC_DIR := $(MODULES) 116 | BUILD_DIR := $(addprefix $(BUILD_BASE)/,$(MODULES)) 117 | 118 | SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c)) 119 | OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC)) 120 | 121 | INCDIR := $(addprefix -I,$(SRC_DIR)) 122 | EXTRA_INCDIR := $(addprefix -I,$(EXTRA_INCDIR)) 123 | MODULE_INCDIR := $(addsuffix /include,$(INCDIR)) 124 | 125 | V ?= $(VERBOSE) 126 | ifeq ("$(V)","1") 127 | Q := 128 | vecho := @true 129 | else 130 | Q := @ 131 | vecho := @echo 132 | endif 133 | 134 | 135 | ifneq ("$(FREERTOS)","yes") 136 | ifeq ("$(USE_OPENSDK)","yes") 137 | CFLAGS += -DUSE_OPENSDK 138 | else 139 | CFLAGS += -D_STDINT_H 140 | endif 141 | endif 142 | 143 | ifeq ("$(GZIP_COMPRESSION)","yes") 144 | CFLAGS += -DGZIP_COMPRESSION 145 | endif 146 | 147 | ifeq ("$(USE_HEATSHRINK)","yes") 148 | CFLAGS += -DESPFS_HEATSHRINK 149 | endif 150 | 151 | ifeq ("$(HTTPD_WEBSOCKETS)","yes") 152 | CFLAGS += -DHTTPD_WEBSOCKETS 153 | endif 154 | 155 | vpath %.c $(SRC_DIR) 156 | 157 | define compile-objects 158 | $1/%.o: %.c 159 | $(vecho) "CC $$<" 160 | $(Q) $(CC) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@ 161 | endef 162 | 163 | .PHONY: all checkdirs clean webpages.espfs submodules 164 | 165 | all: checkdirs $(LIB) webpages.espfs libwebpages-espfs.a 166 | 167 | submodules: lib/heatshrink/Makefile 168 | lib/heatshrink/Makefile: 169 | $(Q) echo "Heatshrink isn't found. Checking out submodules to fetch it." 170 | $(Q) git submodule init 171 | $(Q) git submodule update 172 | 173 | 174 | $(LIB): $(BUILD_DIR) submodules $(OBJ) 175 | $(vecho) "AR $@" 176 | $(Q) $(AR) cru $@ $(OBJ) 177 | 178 | checkdirs: $(BUILD_DIR) 179 | 180 | $(BUILD_DIR): 181 | $(Q) mkdir -p $@ 182 | 183 | 184 | webpages.espfs: $(HTMLDIR) espfs/mkespfsimage/mkespfsimage 185 | ifeq ("$(COMPRESS_W_YUI)","yes") 186 | $(Q) rm -rf html_compressed; 187 | $(Q) cp -r ../html html_compressed; 188 | $(Q) echo "Compression assets with yui-compressor. This may take a while..." 189 | $(Q) for file in `find html_compressed -type f -name "*.js"`; do $(YUI-COMPRESSOR) --type js $$file -o $$file; done 190 | $(Q) for file in `find html_compressed -type f -name "*.css"`; do $(YUI-COMPRESSOR) --type css $$file -o $$file; done 191 | $(Q) awk "BEGIN {printf \"YUI compression ratio was: %.2f%%\\n\", (`du -b -s html_compressed/ | sed 's/\([0-9]*\).*/\1/'`/`du -b -s ../html/ | sed 's/\([0-9]*\).*/\1/'`)*100}" 192 | # mkespfsimage will compress html, css, svg and js files with gzip by default if enabled 193 | # override with -g cmdline parameter 194 | $(Q) cd html_compressed; find . | $(THISDIR)/espfs/mkespfsimage/mkespfsimage > $(THISDIR)/webpages.espfs; cd ..; 195 | else 196 | $(Q) cd ../html; find . | $(THISDIR)/espfs/mkespfsimage/mkespfsimage > $(THISDIR)/webpages.espfs; cd .. 197 | endif 198 | 199 | libwebpages-espfs.a: webpages.espfs 200 | $(Q) $(OBJCOPY) -I binary -O elf32-xtensa-le -B xtensa --rename-section .data=.irom0.literal \ 201 | webpages.espfs build/webpages.espfs.o.tmp 202 | $(Q) $(LD) -nostdlib -Wl,-r build/webpages.espfs.o.tmp -o build/webpages.espfs.o -Wl,-T webpages.espfs.ld 203 | $(Q) $(AR) cru $@ build/webpages.espfs.o 204 | 205 | espfs/mkespfsimage/mkespfsimage: espfs/mkespfsimage/ 206 | $(Q) $(MAKE) -C espfs/mkespfsimage USE_HEATSHRINK="$(USE_HEATSHRINK)" GZIP_COMPRESSION="$(GZIP_COMPRESSION)" 207 | 208 | clean: 209 | $(Q) rm -f $(LIB) 210 | $(Q) find $(BUILD_BASE) -type f | xargs rm -f 211 | $(Q) make -C espfs/mkespfsimage/ clean 212 | $(Q) rm -rf $(FW_BASE) 213 | $(Q) rm -f webpages.espfs libwebpages-espfs.a 214 | ifeq ("$(COMPRESS_W_YUI)","yes") 215 | $(Q) rm -rf html_compressed 216 | endif 217 | 218 | $(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir)))) 219 | -------------------------------------------------------------------------------- /driver_lib/gpio.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ESPRSSIF MIT License 3 | * 4 | * Copyright (c) 2015 5 | * 6 | * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, 7 | * it is free of charge, to any person obtaining a copy of this software and associated 8 | * documentation files (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished 11 | * to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all copies or 14 | * substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | * 23 | */ 24 | 25 | #include "espressif/esp_common.h" 26 | #include "freertos/portmacro.h" 27 | 28 | #include "gpio.h" 29 | 30 | void gpio_config(GPIO_ConfigTypeDef *pGPIOConfig) 31 | { 32 | uint16 gpio_pin_mask = pGPIOConfig->GPIO_Pin; 33 | uint32 io_reg; 34 | uint8 io_num = 0; 35 | uint32 pin_reg; 36 | 37 | if (pGPIOConfig->GPIO_Mode == GPIO_Mode_Input) { 38 | GPIO_AS_INPUT(gpio_pin_mask); 39 | } else if (pGPIOConfig->GPIO_Mode == GPIO_Mode_Output) { 40 | GPIO_AS_OUTPUT(gpio_pin_mask); 41 | } 42 | 43 | do { 44 | if ((gpio_pin_mask >> io_num) & 0x1) { 45 | io_reg = GPIO_PIN_REG(io_num); 46 | 47 | if ((0x1 << io_num) & (GPIO_Pin_0 | GPIO_Pin_2 | GPIO_Pin_4 | GPIO_Pin_5)) { 48 | PIN_FUNC_SELECT(io_reg, 0); 49 | } else { 50 | PIN_FUNC_SELECT(io_reg, 3); 51 | } 52 | 53 | if (pGPIOConfig->GPIO_Pullup) { 54 | PIN_PULLUP_EN(io_reg); 55 | } else { 56 | PIN_PULLUP_DIS(io_reg); 57 | } 58 | 59 | if (pGPIOConfig->GPIO_Mode == GPIO_Mode_Out_OD) { 60 | portENTER_CRITICAL(); 61 | 62 | pin_reg = GPIO_REG_READ(GPIO_PIN_ADDR(io_num)); 63 | pin_reg &= (~GPIO_PIN_DRIVER_MASK); 64 | pin_reg |= (GPIO_PAD_DRIVER_ENABLE << GPIO_PIN_DRIVER_LSB); 65 | GPIO_REG_WRITE(GPIO_PIN_ADDR(io_num), pin_reg); 66 | 67 | portEXIT_CRITICAL(); 68 | } else if (pGPIOConfig->GPIO_Mode == GPIO_Mode_Sigma_Delta) { 69 | portENTER_CRITICAL(); 70 | 71 | pin_reg = GPIO_REG_READ(GPIO_PIN_ADDR(io_num)); 72 | pin_reg &= (~GPIO_PIN_SOURCE_MASK); 73 | pin_reg |= (0x1 << GPIO_PIN_SOURCE_LSB); 74 | GPIO_REG_WRITE(GPIO_PIN_ADDR(io_num), pin_reg); 75 | GPIO_REG_WRITE(GPIO_SIGMA_DELTA_ADDRESS, SIGMA_DELTA_ENABLE); 76 | 77 | portEXIT_CRITICAL(); 78 | } 79 | 80 | gpio_pin_intr_state_set(io_num, pGPIOConfig->GPIO_IntrType); 81 | } 82 | 83 | io_num++; 84 | } while (io_num < 16); 85 | } 86 | 87 | /* 88 | * Change GPIO pin output by setting, clearing, or disabling pins. 89 | * In general, it is expected that a bit will be set in at most one 90 | * of these masks. If a bit is clear in all masks, the output state 91 | * remains unchanged. 92 | * 93 | * There is no particular ordering guaranteed; so if the order of 94 | * writes is significant, calling code should divide a single call 95 | * into multiple calls. 96 | */ 97 | void gpio_output_conf(uint32 set_mask, uint32 clear_mask, uint32 enable_mask, uint32 disable_mask) 98 | { 99 | GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, set_mask); 100 | GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, clear_mask); 101 | GPIO_REG_WRITE(GPIO_ENABLE_W1TS_ADDRESS, enable_mask); 102 | GPIO_REG_WRITE(GPIO_ENABLE_W1TC_ADDRESS, disable_mask); 103 | } 104 | 105 | /* 106 | * Sample the value of GPIO input pins and returns a bitmask. 107 | */ 108 | uint32 gpio_input_get(void) 109 | { 110 | return GPIO_REG_READ(GPIO_IN_ADDRESS); 111 | } 112 | 113 | /* 114 | * Register an application-specific interrupt handler for GPIO pin 115 | * interrupts. Once the interrupt handler is called, it will not 116 | * be called again until after a call to gpio_intr_ack. Any GPIO 117 | * interrupts that occur during the interim are masked. 118 | * 119 | * The application-specific handler is called with a mask of 120 | * pending GPIO interrupts. After processing pin interrupts, the 121 | * application-specific handler may wish to use gpio_intr_pending 122 | * to check for any additional pending interrupts before it returns. 123 | */ 124 | void gpio_intr_handler_register(void *fn, void *arg) 125 | { 126 | _xt_isr_attach(ETS_GPIO_INUM, fn, arg); 127 | } 128 | 129 | /* 130 | only highlevel and lowlevel intr can use for wakeup 131 | */ 132 | void gpio_pin_wakeup_enable(uint32 i, GPIO_INT_TYPE intr_state) 133 | { 134 | uint32 pin_reg; 135 | 136 | if ((intr_state == GPIO_PIN_INTR_LOLEVEL) || (intr_state == GPIO_PIN_INTR_HILEVEL)) { 137 | portENTER_CRITICAL(); 138 | 139 | pin_reg = GPIO_REG_READ(GPIO_PIN_ADDR(i)); 140 | pin_reg &= (~GPIO_PIN_INT_TYPE_MASK); 141 | pin_reg |= (intr_state << GPIO_PIN_INT_TYPE_LSB); 142 | pin_reg |= GPIO_PIN_WAKEUP_ENABLE_SET(GPIO_WAKEUP_ENABLE); 143 | GPIO_REG_WRITE(GPIO_PIN_ADDR(i), pin_reg); 144 | 145 | portEXIT_CRITICAL(); 146 | } 147 | } 148 | 149 | void gpio_pin_wakeup_disable(void) 150 | { 151 | uint8 i; 152 | uint32 pin_reg; 153 | 154 | for (i = 0; i < GPIO_PIN_COUNT; i++) { 155 | pin_reg = GPIO_REG_READ(GPIO_PIN_ADDR(i)); 156 | 157 | if (pin_reg & GPIO_PIN_WAKEUP_ENABLE_MASK) { 158 | pin_reg &= (~GPIO_PIN_INT_TYPE_MASK); 159 | pin_reg |= (GPIO_PIN_INTR_DISABLE << GPIO_PIN_INT_TYPE_LSB); 160 | pin_reg &= ~(GPIO_PIN_WAKEUP_ENABLE_SET(GPIO_WAKEUP_ENABLE)); 161 | GPIO_REG_WRITE(GPIO_PIN_ADDR(i), pin_reg); 162 | } 163 | } 164 | } 165 | 166 | void gpio_pin_intr_state_set(uint32 i, GPIO_INT_TYPE intr_state) 167 | { 168 | uint32 pin_reg; 169 | 170 | portENTER_CRITICAL(); 171 | 172 | pin_reg = GPIO_REG_READ(GPIO_PIN_ADDR(i)); 173 | pin_reg &= (~GPIO_PIN_INT_TYPE_MASK); 174 | pin_reg |= (intr_state << GPIO_PIN_INT_TYPE_LSB); 175 | GPIO_REG_WRITE(GPIO_PIN_ADDR(i), pin_reg); 176 | 177 | portEXIT_CRITICAL(); 178 | } 179 | 180 | void gpio16_output_conf(void) 181 | { 182 | WRITE_PERI_REG(PAD_XPD_DCDC_CONF, 183 | (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | (uint32)0x1); // mux configuration for XPD_DCDC to output rtc_gpio0 184 | 185 | WRITE_PERI_REG(RTC_GPIO_CONF, 186 | (READ_PERI_REG(RTC_GPIO_CONF) & (uint32)0xfffffffe) | (uint32)0x0); //mux configuration for out enable 187 | 188 | WRITE_PERI_REG(RTC_GPIO_ENABLE, 189 | (READ_PERI_REG(RTC_GPIO_ENABLE) & (uint32)0xfffffffe) | (uint32)0x1); //out enable 190 | } 191 | 192 | void gpio16_output_set(uint8 value) 193 | { 194 | WRITE_PERI_REG(RTC_GPIO_OUT, 195 | (READ_PERI_REG(RTC_GPIO_OUT) & (uint32)0xfffffffe) | (uint32)(value & 1)); 196 | } 197 | 198 | void gpio16_input_conf(void) 199 | { 200 | WRITE_PERI_REG(PAD_XPD_DCDC_CONF, 201 | (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | (uint32)0x1); // mux configuration for XPD_DCDC and rtc_gpio0 connection 202 | 203 | WRITE_PERI_REG(RTC_GPIO_CONF, 204 | (READ_PERI_REG(RTC_GPIO_CONF) & (uint32)0xfffffffe) | (uint32)0x0); //mux configuration for out enable 205 | 206 | WRITE_PERI_REG(RTC_GPIO_ENABLE, 207 | READ_PERI_REG(RTC_GPIO_ENABLE) & (uint32)0xfffffffe); //out disable 208 | } 209 | 210 | uint8 gpio16_input_get(void) 211 | { 212 | return (uint8)(READ_PERI_REG(RTC_GPIO_IN_DATA) & 1); 213 | } 214 | -------------------------------------------------------------------------------- /libesphttpd/core/httpd-freertos.c: -------------------------------------------------------------------------------- 1 | /* 2 | ESP8266 web server - platform-dependent routines, FreeRTOS version 3 | 4 | 5 | Thanks to my collague at Espressif for writing the foundations of this code. 6 | */ 7 | #ifdef FREERTOS 8 | 9 | 10 | #include 11 | #include "httpd.h" 12 | #include "platform.h" 13 | #include "httpd-platform.h" 14 | 15 | #include "freertos/FreeRTOS.h" 16 | #include "freertos/task.h" 17 | #include "freertos/queue.h" 18 | #include "freertos/semphr.h" 19 | 20 | #include "lwip/lwip/sockets.h" 21 | 22 | 23 | static int httpPort; 24 | static int httpMaxConnCt; 25 | static xQueueHandle httpdMux; 26 | 27 | 28 | struct RtosConnType{ 29 | int fd; 30 | int needWriteDoneNotif; 31 | int needsClose; 32 | int port; 33 | char ip[4]; 34 | }; 35 | 36 | static RtosConnType rconn[HTTPD_MAX_CONNECTIONS]; 37 | 38 | int ICACHE_FLASH_ATTR httpdPlatSendData(ConnTypePtr conn, char *buff, int len) { 39 | conn->needWriteDoneNotif=1; 40 | return (write(conn->fd, buff, len)>=0); 41 | } 42 | 43 | void ICACHE_FLASH_ATTR httpdPlatDisconnect(ConnTypePtr conn) { 44 | conn->needsClose=1; 45 | conn->needWriteDoneNotif=1; //because the real close is done in the writable select code 46 | } 47 | 48 | void httpdPlatDisableTimeout(ConnTypePtr conn) { 49 | //Unimplemented for FreeRTOS 50 | } 51 | 52 | //Set/clear global httpd lock. 53 | void ICACHE_FLASH_ATTR httpdPlatLock() { 54 | xSemaphoreTakeRecursive(httpdMux, portMAX_DELAY); 55 | } 56 | 57 | void ICACHE_FLASH_ATTR httpdPlatUnlock() { 58 | xSemaphoreGiveRecursive(httpdMux); 59 | } 60 | 61 | 62 | #define RECV_BUF_SIZE 2048 63 | static void platHttpServerTask(void *pvParameters) { 64 | int32 listenfd; 65 | int32 remotefd; 66 | int32 len; 67 | int32 ret; 68 | int x; 69 | int maxfdp = 0; 70 | char *precvbuf; 71 | fd_set readset,writeset; 72 | struct sockaddr name; 73 | //struct timeval timeout; 74 | struct sockaddr_in server_addr; 75 | struct sockaddr_in remote_addr; 76 | 77 | httpdMux=xSemaphoreCreateRecursiveMutex(); 78 | 79 | for (x=0; xmaxfdp) maxfdp=rconn[x].fd; 133 | } else { 134 | socketsFull=0; 135 | } 136 | } 137 | 138 | if (!socketsFull) { 139 | FD_SET(listenfd, &readset); 140 | if (listenfd>maxfdp) maxfdp=listenfd; 141 | } 142 | 143 | //polling all exist client handle,wait until readable/writable 144 | ret = select(maxfdp+1, &readset, &writeset, NULL, NULL);//&timeout 145 | if(ret > 0){ 146 | //See if we need to accept a new connection 147 | if (FD_ISSET(listenfd, &readset)) { 148 | len=sizeof(struct sockaddr_in); 149 | remotefd = accept(listenfd, (struct sockaddr *)&remote_addr, (socklen_t *)&len); 150 | if (remotefd<0) { 151 | httpd_printf("platHttpServerTask: Huh? Accept failed.\n"); 152 | continue; 153 | } 154 | for(x=0; xsin_port; 178 | memcpy(&rconn[x].ip, &piname->sin_addr.s_addr, sizeof(rconn[x].ip)); 179 | 180 | httpdConnectCb(&rconn[x], rconn[x].ip, rconn[x].port); 181 | //os_timer_disarm(&connData[x].conn->stop_watch); 182 | //os_timer_setfn(&connData[x].conn->stop_watch, (os_timer_func_t *)httpserver_conn_watcher, connData[x].conn); 183 | //os_timer_arm(&connData[x].conn->stop_watch, STOP_TIMER, 0); 184 | // httpd_printf("httpserver acpt index %d sockfd %d!\n", x, remotefd); 185 | } 186 | 187 | //See if anything happened on the existing connections. 188 | for(x=0; x < HTTPD_MAX_CONNECTIONS; x++){ 189 | //Skip empty slots 190 | if (rconn[x].fd==-1) continue; 191 | 192 | //Check for write availability first: the read routines may write needWriteDoneNotif while 193 | //the select didn't check for that. 194 | if (rconn[x].needWriteDoneNotif && FD_ISSET(rconn[x].fd, &writeset)) { 195 | rconn[x].needWriteDoneNotif=0; //Do this first, httpdSentCb may write something making this 1 again. 196 | if (rconn[x].needsClose) { 197 | //Do callback and close fd. 198 | httpdDisconCb(&rconn[x], rconn[x].ip, rconn[x].port); 199 | close(rconn[x].fd); 200 | rconn[x].fd=-1; 201 | } else { 202 | httpdSentCb(&rconn[x], rconn[x].ip, rconn[x].port); 203 | } 204 | } 205 | 206 | if (FD_ISSET(rconn[x].fd, &readset)) { 207 | precvbuf=(char*)malloc(RECV_BUF_SIZE); 208 | if (precvbuf==NULL) { 209 | httpd_printf("platHttpServerTask: memory exhausted!\n"); 210 | httpdDisconCb(&rconn[x], rconn[x].ip, rconn[x].port); 211 | close(rconn[x].fd); 212 | rconn[x].fd=-1; 213 | } 214 | ret=recv(rconn[x].fd, precvbuf, RECV_BUF_SIZE,0); 215 | if (ret > 0) { 216 | //Data received. Pass to httpd. 217 | httpdRecvCb(&rconn[x], rconn[x].ip, rconn[x].port, precvbuf, ret); 218 | } else { 219 | //recv error,connection close 220 | httpdDisconCb(&rconn[x], rconn[x].ip, rconn[x].port); 221 | close(rconn[x].fd); 222 | rconn[x].fd=-1; 223 | } 224 | if (precvbuf) free(precvbuf); 225 | } 226 | } 227 | } 228 | } 229 | 230 | #if 0 231 | //Deinit code, not used here. 232 | /*release data connection*/ 233 | for(x=0; x < HTTPD_MAX_CONNECTIONS; x++){ 234 | //find all valid handle 235 | if(connData[x].conn == NULL) continue; 236 | if(connData[x].conn->sockfd >= 0){ 237 | os_timer_disarm((os_timer_t *)&connData[x].conn->stop_watch); 238 | close(connData[x].conn->sockfd); 239 | connData[x].conn->sockfd = -1; 240 | connData[x].conn = NULL; 241 | if(connData[x].cgi!=NULL) connData[x].cgi(&connData[x]); //flush cgi data 242 | httpdRetireConn(&connData[x]); 243 | } 244 | } 245 | /*release listen socket*/ 246 | close(listenfd); 247 | 248 | vTaskDelete(NULL); 249 | #endif 250 | } 251 | 252 | 253 | 254 | //Initialize listening socket, do general initialization 255 | void ICACHE_FLASH_ATTR httpdPlatInit(int port, int maxConnCt) { 256 | httpPort=port; 257 | httpMaxConnCt=maxConnCt; 258 | #ifdef ESP32 259 | xTaskCreate(platHttpServerTask, (const char *)"esphttpd", HTTPD_STACKSIZE, NULL, 4, NULL); 260 | #else 261 | xTaskCreate(platHttpServerTask, (const signed char *)"esphttpd", HTTPD_STACKSIZE, NULL, 4, NULL); 262 | #endif 263 | } 264 | 265 | 266 | #endif -------------------------------------------------------------------------------- /driver_lib/include/uart.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ESPRSSIF MIT License 3 | * 4 | * Copyright (c) 2015 5 | * 6 | * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, 7 | * it is free of charge, to any person obtaining a copy of this software and associated 8 | * documentation files (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished 11 | * to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all copies or 14 | * substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | * 23 | */ 24 | 25 | #ifndef __UART_H__ 26 | #define __UART_H__ 27 | 28 | #ifdef __cplusplus 29 | extern "C" { 30 | #endif 31 | 32 | #define ETS_UART_INTR_ENABLE() _xt_isr_unmask(1 << ETS_UART_INUM) 33 | #define ETS_UART_INTR_DISABLE() _xt_isr_mask(1 << ETS_UART_INUM) 34 | #define UART_INTR_MASK 0x1ff 35 | #define UART_LINE_INV_MASK (0x3f<<19) 36 | 37 | typedef enum { 38 | UART_WordLength_5b = 0x0, 39 | UART_WordLength_6b = 0x1, 40 | UART_WordLength_7b = 0x2, 41 | UART_WordLength_8b = 0x3 42 | } UART_WordLength; 43 | 44 | typedef enum { 45 | USART_StopBits_1 = 0x1, 46 | USART_StopBits_1_5 = 0x2, 47 | USART_StopBits_2 = 0x3, 48 | } UART_StopBits; 49 | 50 | typedef enum { 51 | UART0 = 0x0, 52 | UART1 = 0x1, 53 | } UART_Port; 54 | 55 | typedef enum { 56 | USART_Parity_None = 0x2, 57 | USART_Parity_Even = 0x0, 58 | USART_Parity_Odd = 0x1 59 | } UART_ParityMode; 60 | 61 | typedef enum { 62 | PARITY_DIS = 0x0, 63 | PARITY_EN = 0x2 64 | } UartExistParity; 65 | 66 | typedef enum { 67 | BIT_RATE_300 = 300, 68 | BIT_RATE_600 = 600, 69 | BIT_RATE_1200 = 1200, 70 | BIT_RATE_2400 = 2400, 71 | BIT_RATE_4800 = 4800, 72 | BIT_RATE_9600 = 9600, 73 | BIT_RATE_19200 = 19200, 74 | BIT_RATE_38400 = 38400, 75 | BIT_RATE_57600 = 57600, 76 | BIT_RATE_74880 = 74880, 77 | BIT_RATE_115200 = 115200, 78 | BIT_RATE_230400 = 230400, 79 | BIT_RATE_460800 = 460800, 80 | BIT_RATE_921600 = 921600, 81 | BIT_RATE_1843200 = 1843200, 82 | BIT_RATE_3686400 = 3686400, 83 | } UART_BautRate; //you can add any rate you need in this range 84 | 85 | typedef enum { 86 | USART_HardwareFlowControl_None = 0x0, 87 | USART_HardwareFlowControl_RTS = 0x1, 88 | USART_HardwareFlowControl_CTS = 0x2, 89 | USART_HardwareFlowControl_CTS_RTS = 0x3 90 | } UART_HwFlowCtrl; 91 | 92 | typedef enum { 93 | UART_None_Inverse = 0x0, 94 | UART_Rxd_Inverse = UART_RXD_INV, 95 | UART_CTS_Inverse = UART_CTS_INV, 96 | UART_Txd_Inverse = UART_TXD_INV, 97 | UART_RTS_Inverse = UART_RTS_INV, 98 | } UART_LineLevelInverse; 99 | 100 | typedef struct { 101 | UART_BautRate baud_rate; 102 | UART_WordLength data_bits; 103 | UART_ParityMode parity; // chip size in byte 104 | UART_StopBits stop_bits; 105 | UART_HwFlowCtrl flow_ctrl; 106 | uint8 UART_RxFlowThresh ; 107 | uint32 UART_InverseMask; 108 | } UART_ConfigTypeDef; 109 | 110 | typedef struct { 111 | uint32 UART_IntrEnMask; 112 | uint8 UART_RX_TimeOutIntrThresh; 113 | uint8 UART_TX_FifoEmptyIntrThresh; 114 | uint8 UART_RX_FifoFullIntrThresh; 115 | } UART_IntrConfTypeDef; 116 | 117 | //======================================= 118 | 119 | /** \defgroup Driver_APIs Driver APIs 120 | * @brief Driver APIs 121 | */ 122 | 123 | /** @addtogroup Driver_APIs 124 | * @{ 125 | */ 126 | 127 | /** \defgroup UART_Driver_APIs UART Driver APIs 128 | * @brief UART driver APIs 129 | */ 130 | 131 | /** @addtogroup UART_Driver_APIs 132 | * @{ 133 | */ 134 | 135 | /** 136 | * @brief Wait uart tx fifo empty, do not use it if tx flow control enabled. 137 | * 138 | * @param UART_Port uart_no:UART0 or UART1 139 | * 140 | * @return null 141 | */ 142 | void UART_WaitTxFifoEmpty(UART_Port uart_no); //do not use if tx flow control enabled 143 | 144 | /** 145 | * @brief Clear uart tx fifo and rx fifo. 146 | * 147 | * @param UART_Port uart_no : UART0 or UART1 148 | * 149 | * @return null 150 | */ 151 | void UART_ResetFifo(UART_Port uart_no); 152 | 153 | /** 154 | * @brief Clear uart interrupt flags. 155 | * 156 | * @param UART_Port uart_no : UART0 or UART1 157 | * @param uint32 clr_mask : To clear the interrupt bits 158 | * 159 | * @return null 160 | */ 161 | void UART_ClearIntrStatus(UART_Port uart_no, uint32 clr_mask); 162 | 163 | /** 164 | * @brief Enable uart interrupts . 165 | * 166 | * @param UART_Port uart_no : UART0 or UART1 167 | * @param uint32 ena_mask : To enable the interrupt bits 168 | * 169 | * @return null 170 | */ 171 | void UART_SetIntrEna(UART_Port uart_no, uint32 ena_mask); 172 | 173 | /** 174 | * @brief Register an application-specific interrupt handler for Uarts interrupts. 175 | * 176 | * @param void *fn : interrupt handler for Uart interrupts. 177 | * @param void *arg : interrupt handler's arg. 178 | * 179 | * @return null 180 | */ 181 | void UART_intr_handler_register(void *fn, void *arg); 182 | 183 | /** 184 | * @brief Config from which serial output printf function. 185 | * 186 | * @param UART_Port uart_no : UART0 or UART1 187 | * 188 | * @return null 189 | */ 190 | void UART_SetPrintPort(UART_Port uart_no); 191 | 192 | /** 193 | * @brief Config Common parameters of serial ports. 194 | * 195 | * @param UART_Port uart_no : UART0 or UART1 196 | * @param UART_ConfigTypeDef *pUARTConfig : parameters structure 197 | * 198 | * @return null 199 | */ 200 | void UART_ParamConfig(UART_Port uart_no, UART_ConfigTypeDef *pUARTConfig); 201 | 202 | /** 203 | * @brief Config types of uarts. 204 | * 205 | * @param UART_Port uart_no : UART0 or UART1 206 | * @param UART_IntrConfTypeDef *pUARTIntrConf : parameters structure 207 | * 208 | * @return null 209 | */ 210 | void UART_IntrConfig(UART_Port uart_no, UART_IntrConfTypeDef *pUARTIntrConf); 211 | 212 | /** 213 | * @brief Config the length of the uart communication data bits. 214 | * 215 | * @param UART_Port uart_no : UART0 or UART1 216 | * @param UART_WordLength len : the length of the uart communication data bits 217 | * 218 | * @return null 219 | */ 220 | void UART_SetWordLength(UART_Port uart_no, UART_WordLength len); 221 | 222 | /** 223 | * @brief Config the length of the uart communication stop bits. 224 | * 225 | * @param UART_Port uart_no : UART0 or UART1 226 | * @param UART_StopBits bit_num : the length uart communication stop bits 227 | * 228 | * @return null 229 | */ 230 | void UART_SetStopBits(UART_Port uart_no, UART_StopBits bit_num); 231 | 232 | /** 233 | * @brief Configure whether to open the parity. 234 | * 235 | * @param UART_Port uart_no : UART0 or UART1 236 | * @param UART_ParityMode Parity_mode : the enum of uart parity configuration 237 | * 238 | * @return null 239 | */ 240 | void UART_SetParity(UART_Port uart_no, UART_ParityMode Parity_mode) ; 241 | 242 | /** 243 | * @brief Configure the Baud rate. 244 | * 245 | * @param UART_Port uart_no : UART0 or UART1 246 | * @param uint32 baud_rate : the Baud rate 247 | * 248 | * @return null 249 | */ 250 | void UART_SetBaudrate(UART_Port uart_no, uint32 baud_rate); 251 | 252 | /** 253 | * @brief Configure Hardware flow control. 254 | * 255 | * @param UART_Port uart_no : UART0 or UART1 256 | * @param UART_HwFlowCtrl flow_ctrl : Hardware flow control mode 257 | * @param uint8 rx_thresh : threshold of Hardware flow control 258 | * 259 | * @return null 260 | */ 261 | void UART_SetFlowCtrl(UART_Port uart_no, UART_HwFlowCtrl flow_ctrl, uint8 rx_thresh); 262 | 263 | /** 264 | * @brief Configure trigging signal of uarts. 265 | * 266 | * @param UART_Port uart_no : UART0 or UART1 267 | * @param UART_LineLevelInverse inverse_mask : Choose need to flip the IO 268 | * 269 | * @return null 270 | */ 271 | void UART_SetLineInverse(UART_Port uart_no, UART_LineLevelInverse inverse_mask) ; 272 | 273 | /** 274 | * @brief An example illustrates how to configure the serial port. 275 | * 276 | * @param null 277 | * 278 | * @return null 279 | */ 280 | void uart_init_new(void); 281 | 282 | /** 283 | * @} 284 | */ 285 | 286 | /** 287 | * @} 288 | */ 289 | 290 | #ifdef __cplusplus 291 | } 292 | #endif 293 | 294 | #endif 295 | -------------------------------------------------------------------------------- /libesphttpd/espfs/espfs.c: -------------------------------------------------------------------------------- 1 | /* 2 | This is a simple read-only implementation of a file system. It uses a block of data coming from the 3 | mkespfsimg tool, and can use that block to do abstracted operations on the files that are in there. 4 | It's written for use with httpd, but doesn't need to be used as such. 5 | */ 6 | 7 | /* 8 | * ---------------------------------------------------------------------------- 9 | * "THE BEER-WARE LICENSE" (Revision 42): 10 | * Jeroen Domburg wrote this file. As long as you retain 11 | * this notice you can do whatever you want with this stuff. If we meet some day, 12 | * and you think this stuff is worth it, you can buy me a beer in return. 13 | * ---------------------------------------------------------------------------- 14 | */ 15 | 16 | 17 | //These routines can also be tested by comping them in with the espfstest tool. This 18 | //simplifies debugging, but needs some slightly different headers. The #ifdef takes 19 | //care of that. 20 | 21 | #ifdef __ets__ 22 | //esp build 23 | #include 24 | #else 25 | //Test build 26 | #include 27 | #include 28 | #include 29 | #include 30 | #define ICACHE_FLASH_ATTR 31 | #endif 32 | 33 | #include "espfsformat.h" 34 | #include "espfs.h" 35 | 36 | #ifdef ESPFS_HEATSHRINK 37 | #include "heatshrink_config_custom.h" 38 | #include "heatshrink_decoder.h" 39 | #endif 40 | 41 | static char* espFsData = NULL; 42 | 43 | 44 | struct EspFsFile { 45 | EspFsHeader *header; 46 | char decompressor; 47 | int32_t posDecomp; 48 | char *posStart; 49 | char *posComp; 50 | void *decompData; 51 | }; 52 | 53 | /* 54 | Available locations, at least in my flash, with boundaries partially guessed. This 55 | is using 0.9.1/0.9.2 SDK on a not-too-new module. 56 | 0x00000 (0x10000): Code/data (RAM data?) 57 | 0x10000 (0x02000): Gets erased by something? 58 | 0x12000 (0x2E000): Free (filled with zeroes) (parts used by ESPCloud and maybe SSL) 59 | 0x40000 (0x20000): Code/data (ROM data?) 60 | 0x60000 (0x1C000): Free 61 | 0x7c000 (0x04000): Param store 62 | 0x80000 - end of flash 63 | 64 | Accessing the flash through the mem emulation at 0x40200000 is a bit hairy: All accesses 65 | *must* be aligned 32-bit accesses. Reading a short, byte or unaligned word will result in 66 | a memory exception, crashing the program. 67 | */ 68 | 69 | #ifndef ESP32 70 | #define FLASH_BASE_ADDR 0x40200000 71 | #else 72 | //ESP32 IRAM addresses start at 0x40000000, but the IRAM segment actually is mapped 73 | //starting from SPI address 0x40000. 74 | #define FLASH_BASE_ADDR 0x40040000 75 | #endif 76 | 77 | EspFsInitResult ICACHE_FLASH_ATTR espFsInit(void *flashAddress) { 78 | if((uint32_t)flashAddress > 0x40000000) { 79 | flashAddress = (void*)((uint32_t)flashAddress-FLASH_BASE_ADDR); 80 | } 81 | 82 | // base address must be aligned to 4 bytes 83 | if (((int)flashAddress & 3) != 0) { 84 | return ESPFS_INIT_RESULT_BAD_ALIGN; 85 | } 86 | 87 | // check if there is valid header at address 88 | EspFsHeader testHeader; 89 | spi_flash_read((uint32)flashAddress, (uint32*)&testHeader, sizeof(EspFsHeader)); 90 | if (testHeader.magic != ESPFS_MAGIC) { 91 | return ESPFS_INIT_RESULT_NO_IMAGE; 92 | } 93 | 94 | espFsData = (char *)flashAddress; 95 | return ESPFS_INIT_RESULT_OK; 96 | } 97 | 98 | //Copies len bytes over from dst to src, but does it using *only* 99 | //aligned 32-bit reads. Yes, it's no too optimized but it's short and sweet and it works. 100 | 101 | //ToDo: perhaps memcpy also does unaligned accesses? 102 | #ifdef __ets__ 103 | void ICACHE_FLASH_ATTR readFlashUnaligned(char *dst, char *src, int len) { 104 | uint8_t src_offset = ((uint32_t)src) & 3; 105 | uint32_t src_address = ((uint32_t)src) - src_offset; 106 | 107 | uint32_t tmp_buf[len/4 + 2]; 108 | spi_flash_read((uint32)src_address, (uint32*)tmp_buf, len+src_offset); 109 | memcpy(dst, ((uint8_t*)tmp_buf)+src_offset, len); 110 | } 111 | #else 112 | #define readFlashUnaligned memcpy 113 | #endif 114 | 115 | // Returns flags of opened file. 116 | int ICACHE_FLASH_ATTR espFsFlags(EspFsFile *fh) { 117 | if (fh == NULL) { 118 | httpd_printf("File handle not ready\n"); 119 | return -1; 120 | } 121 | 122 | int8_t flags; 123 | readFlashUnaligned((char*)&flags, (char*)&fh->header->flags, 1); 124 | return (int)flags; 125 | } 126 | 127 | //Open a file and return a pointer to the file desc struct. 128 | EspFsFile ICACHE_FLASH_ATTR *espFsOpen(char *fileName) { 129 | if (espFsData == NULL) { 130 | httpd_printf("Call espFsInit first!\n"); 131 | return NULL; 132 | } 133 | char *p=espFsData; 134 | char *hpos; 135 | char namebuf[256]; 136 | EspFsHeader h; 137 | EspFsFile *r; 138 | //Strip initial slashes 139 | while(fileName[0]=='/') fileName++; 140 | //Go find that file! 141 | while(1) { 142 | hpos=p; 143 | //Grab the next file header. 144 | spi_flash_read((uint32)p, (uint32*)&h, sizeof(EspFsHeader)); 145 | 146 | if (h.magic!=ESPFS_MAGIC) { 147 | httpd_printf("Magic mismatch. EspFS image broken.\n"); 148 | return NULL; 149 | } 150 | if (h.flags&FLAG_LASTFILE) { 151 | httpd_printf("End of image.\n"); 152 | return NULL; 153 | } 154 | //Grab the name of the file. 155 | p+=sizeof(EspFsHeader); 156 | spi_flash_read((uint32)p, (uint32*)&namebuf, sizeof(namebuf)); 157 | // httpd_printf("Found file '%s'. Namelen=%x fileLenComp=%x, compr=%d flags=%d\n", 158 | // namebuf, (unsigned int)h.nameLen, (unsigned int)h.fileLenComp, h.compression, h.flags); 159 | if (strcmp(namebuf, fileName)==0) { 160 | //Yay, this is the file we need! 161 | p+=h.nameLen; //Skip to content. 162 | r=(EspFsFile *)malloc(sizeof(EspFsFile)); //Alloc file desc mem 163 | // httpd_printf("Alloc %p\n", r); 164 | if (r==NULL) return NULL; 165 | r->header=(EspFsHeader *)hpos; 166 | r->decompressor=h.compression; 167 | r->posComp=p; 168 | r->posStart=p; 169 | r->posDecomp=0; 170 | if (h.compression==COMPRESS_NONE) { 171 | r->decompData=NULL; 172 | #ifdef ESPFS_HEATSHRINK 173 | } else if (h.compression==COMPRESS_HEATSHRINK) { 174 | //File is compressed with Heatshrink. 175 | char parm; 176 | heatshrink_decoder *dec; 177 | //Decoder params are stored in 1st byte. 178 | readFlashUnaligned(&parm, r->posComp, 1); 179 | r->posComp++; 180 | httpd_printf("Heatshrink compressed file; decode parms = %x\n", parm); 181 | dec=heatshrink_decoder_alloc(16, (parm>>4)&0xf, parm&0xf); 182 | r->decompData=dec; 183 | #endif 184 | } else { 185 | httpd_printf("Invalid compression: %d\n", h.compression); 186 | return NULL; 187 | } 188 | return r; 189 | } 190 | //We don't need this file. Skip name and file 191 | p+=h.nameLen+h.fileLenComp; 192 | if ((int)p&3) p+=4-((int)p&3); //align to next 32bit val 193 | } 194 | } 195 | 196 | //Read len bytes from the given file into buff. Returns the actual amount of bytes read. 197 | int ICACHE_FLASH_ATTR espFsRead(EspFsFile *fh, char *buff, int len) { 198 | int flen; 199 | #ifdef ESPFS_HEATSHRINK 200 | int fdlen; 201 | #endif 202 | if (fh==NULL) return 0; 203 | 204 | readFlashUnaligned((char*)&flen, (char*)&fh->header->fileLenComp, 4); 205 | //Cache file length. 206 | //Do stuff depending on the way the file is compressed. 207 | if (fh->decompressor==COMPRESS_NONE) { 208 | int toRead; 209 | toRead=flen-(fh->posComp-fh->posStart); 210 | if (len>toRead) len=toRead; 211 | // httpd_printf("Reading %d bytes from %x\n", len, (unsigned int)fh->posComp); 212 | readFlashUnaligned(buff, fh->posComp, len); 213 | fh->posDecomp+=len; 214 | fh->posComp+=len; 215 | // httpd_printf("Done reading %d bytes, pos=%x\n", len, fh->posComp); 216 | return len; 217 | #ifdef ESPFS_HEATSHRINK 218 | } else if (fh->decompressor==COMPRESS_HEATSHRINK) { 219 | readFlashUnaligned((char*)&fdlen, (char*)&fh->header->fileLenDecomp, 4); 220 | int decoded=0; 221 | size_t elen, rlen; 222 | char ebuff[16]; 223 | heatshrink_decoder *dec=(heatshrink_decoder *)fh->decompData; 224 | // httpd_printf("Alloc %p\n", dec); 225 | if (fh->posDecomp == fdlen) { 226 | return 0; 227 | } 228 | 229 | // We must ensure that whole file is decompressed and written to output buffer. 230 | // This means even when there is no input data (elen==0) try to poll decoder until 231 | // posDecomp equals decompressed file length 232 | 233 | while(decodedposComp - fh->posStart); 237 | if (elen>0) { 238 | readFlashUnaligned(ebuff, fh->posComp, 16); 239 | heatshrink_decoder_sink(dec, (uint8_t *)ebuff, (elen>16)?16:elen, &rlen); 240 | fh->posComp+=rlen; 241 | } 242 | //Grab decompressed data and put into buff 243 | heatshrink_decoder_poll(dec, (uint8_t *)buff, len-decoded, &rlen); 244 | fh->posDecomp+=rlen; 245 | buff+=rlen; 246 | decoded+=rlen; 247 | 248 | // httpd_printf("Elen %d rlen %d d %d pd %ld fdl %d\n",elen,rlen,decoded, fh->posDecomp, fdlen); 249 | 250 | if (elen == 0) { 251 | if (fh->posDecomp == fdlen) { 252 | // httpd_printf("Decoder finish\n"); 253 | heatshrink_decoder_finish(dec); 254 | } 255 | return decoded; 256 | } 257 | } 258 | return len; 259 | #endif 260 | } 261 | return 0; 262 | } 263 | 264 | //Close the file. 265 | void ICACHE_FLASH_ATTR espFsClose(EspFsFile *fh) { 266 | if (fh==NULL) return; 267 | #ifdef ESPFS_HEATSHRINK 268 | if (fh->decompressor==COMPRESS_HEATSHRINK) { 269 | heatshrink_decoder *dec=(heatshrink_decoder *)fh->decompData; 270 | heatshrink_decoder_free(dec); 271 | // httpd_printf("Freed %p\n", dec); 272 | } 273 | #endif 274 | // httpd_printf("Freed %p\n", fh); 275 | free(fh); 276 | } 277 | 278 | 279 | 280 | -------------------------------------------------------------------------------- /libesphttpd/espfs/mkespfsimage/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #ifdef __MINGW32__ 10 | #include 11 | #endif 12 | #include "espfs.h" 13 | #include "espfsformat.h" 14 | 15 | //Heatshrink 16 | #ifdef ESPFS_HEATSHRINK 17 | #include "heatshrink_common.h" 18 | #include "heatshrink_config.h" 19 | #include "heatshrink_encoder.h" 20 | #endif 21 | 22 | //Gzip 23 | #ifdef ESPFS_GZIP 24 | // If compiler complains about missing header, try running "sudo apt-get install zlib1g-dev" 25 | // to install missing package. 26 | #include 27 | #endif 28 | 29 | //Cygwin e.a. needs O_BINARY. Don't miscompile if it's not set. 30 | #ifndef O_BINARY 31 | #define O_BINARY 0 32 | #endif 33 | 34 | //Routines to convert host format to the endianness used in the xtensa 35 | short htoxs(short in) { 36 | char r[2]; 37 | r[0]=in; 38 | r[1]=in>>8; 39 | return *((short *)r); 40 | } 41 | 42 | int htoxl(int in) { 43 | unsigned char r[4]; 44 | r[0]=in; 45 | r[1]=in>>8; 46 | r[2]=in>>16; 47 | r[3]=in>>24; 48 | return *((int *)r); 49 | } 50 | 51 | #ifdef ESPFS_HEATSHRINK 52 | size_t compressHeatshrink(char *in, int insize, char *out, int outsize, int level) { 53 | char *inp=in; 54 | char *outp=out; 55 | size_t len; 56 | int ws[]={5, 6, 8, 11, 13}; 57 | int ls[]={3, 3, 4, 4, 4}; 58 | HSE_poll_res pres; 59 | HSE_sink_res sres; 60 | size_t r; 61 | if (level==-1) level=8; 62 | level=(level-1)/2; //level is now 0, 1, 2, 3, 4 63 | heatshrink_encoder *enc=heatshrink_encoder_alloc(ws[level], ls[level]); 64 | if (enc==NULL) { 65 | perror("allocating mem for heatshrink"); 66 | exit(1); 67 | } 68 | //Save encoder parms as first byte 69 | *outp=(ws[level]<<4)|ls[level]; 70 | outp++; outsize--; 71 | 72 | r=1; 73 | do { 74 | if (insize>0) { 75 | sres=heatshrink_encoder_sink(enc, inp, insize, &len); 76 | if (sres!=HSER_SINK_OK) break; 77 | inp+=len; insize-=len; 78 | if (insize==0) heatshrink_encoder_finish(enc); 79 | } 80 | do { 81 | pres=heatshrink_encoder_poll(enc, outp, outsize, &len); 82 | if (pres!=HSER_POLL_MORE && pres!=HSER_POLL_EMPTY) break; 83 | outp+=len; outsize-=len; 84 | r+=len; 85 | } while (pres==HSER_POLL_MORE); 86 | } while (insize!=0); 87 | 88 | if (insize!=0) { 89 | fprintf(stderr, "Heatshrink: Bug? insize is still %d. sres=%d pres=%d\n", insize, sres, pres); 90 | exit(1); 91 | } 92 | 93 | heatshrink_encoder_free(enc); 94 | return r; 95 | } 96 | #endif 97 | 98 | #ifdef ESPFS_GZIP 99 | size_t compressGzip(char *in, int insize, char *out, int outsize, int level) { 100 | z_stream stream; 101 | int zresult; 102 | 103 | stream.zalloc = Z_NULL; 104 | stream.zfree = Z_NULL; 105 | stream.opaque = Z_NULL; 106 | stream.next_in = in; 107 | stream.avail_in = insize; 108 | stream.next_out = out; 109 | stream.avail_out = outsize; 110 | // 31 -> 15 window bits + 16 for gzip 111 | zresult = deflateInit2 (&stream, level, Z_DEFLATED, 31, 8, Z_DEFAULT_STRATEGY); 112 | if (zresult != Z_OK) { 113 | fprintf(stderr, "DeflateInit2 failed with code %d\n", zresult); 114 | exit(1); 115 | } 116 | 117 | zresult = deflate(&stream, Z_FINISH); 118 | if (zresult != Z_STREAM_END) { 119 | fprintf(stderr, "Deflate failed with code %d\n", zresult); 120 | exit(1); 121 | } 122 | 123 | zresult = deflateEnd(&stream); 124 | if (zresult != Z_OK) { 125 | fprintf(stderr, "DeflateEnd failed with code %d\n", zresult); 126 | exit(1); 127 | } 128 | 129 | return stream.total_out; 130 | } 131 | 132 | char **gzipExtensions = NULL; 133 | 134 | int shouldCompressGzip(char *name) { 135 | char *ext = name + strlen(name); 136 | while (*ext != '.') { 137 | ext--; 138 | if (ext < name) { 139 | // no dot in file name -> no extension -> nothing to match against 140 | return 0; 141 | } 142 | } 143 | ext++; 144 | 145 | int i = 0; 146 | while (gzipExtensions[i] != NULL) { 147 | if (strcmp(ext,gzipExtensions[i]) == 0) { 148 | return 1; 149 | } 150 | i++; 151 | } 152 | 153 | return 0; 154 | } 155 | 156 | int parseGzipExtensions(char *input) { 157 | char *token; 158 | char *extList = input; 159 | int count = 2; // one for first element, second for terminator 160 | 161 | // count elements 162 | while (*extList != 0) { 163 | if (*extList == ',') count++; 164 | extList++; 165 | } 166 | 167 | // split string 168 | extList = input; 169 | gzipExtensions = malloc(count * sizeof(char*)); 170 | count = 0; 171 | token = strtok(extList, ","); 172 | while (token) { 173 | gzipExtensions[count++] = token; 174 | token = strtok(NULL, ","); 175 | } 176 | // terminate list 177 | gzipExtensions[count] = NULL; 178 | 179 | return 1; 180 | } 181 | #endif 182 | 183 | int handleFile(int f, char *name, int compression, int level, char **compName) { 184 | char *fdat, *cdat; 185 | off_t size, csize; 186 | EspFsHeader h; 187 | int nameLen; 188 | int8_t flags = 0; 189 | size=lseek(f, 0, SEEK_END); 190 | fdat=malloc(size); 191 | lseek(f, 0, SEEK_SET); 192 | read(f, fdat, size); 193 | 194 | 195 | #ifdef ESPFS_GZIP 196 | if (shouldCompressGzip(name)) { 197 | csize = size*3; 198 | if (csize<100) // gzip has some headers that do not fit when trying to compress small files 199 | csize = 100; // enlarge buffer if this is the case 200 | cdat=malloc(csize); 201 | csize=compressGzip(fdat, size, cdat, csize, level); 202 | compression = COMPRESS_NONE; 203 | flags = FLAG_GZIP; 204 | } else 205 | #endif 206 | if (compression==COMPRESS_NONE) { 207 | csize=size; 208 | cdat=fdat; 209 | #ifdef ESPFS_HEATSHRINK 210 | } else if (compression==COMPRESS_HEATSHRINK) { 211 | cdat=malloc(size*2); 212 | csize=compressHeatshrink(fdat, size, cdat, size*2, level); 213 | #endif 214 | } else { 215 | fprintf(stderr, "Unknown compression - %d\n", compression); 216 | exit(1); 217 | } 218 | 219 | if (csize>size) { 220 | //Compressing enbiggened this file. Revert to uncompressed store. 221 | compression=COMPRESS_NONE; 222 | csize=size; 223 | cdat=fdat; 224 | flags=0; 225 | } 226 | 227 | //Fill header data 228 | h.magic=('E'<<0)+('S'<<8)+('f'<<16)+('s'<<24); 229 | h.flags=flags; 230 | h.compression=compression; 231 | h.nameLen=nameLen=strlen(name)+1; 232 | if (h.nameLen&3) h.nameLen+=4-(h.nameLen&3); //Round to next 32bit boundary 233 | h.nameLen=htoxs(h.nameLen); 234 | h.fileLenComp=htoxl(csize); 235 | h.fileLenDecomp=htoxl(size); 236 | 237 | write(1, &h, sizeof(EspFsHeader)); 238 | write(1, name, nameLen); 239 | while (nameLen&3) { 240 | write(1, "\000", 1); 241 | nameLen++; 242 | } 243 | write(1, cdat, csize); 244 | //Pad out to 32bit boundary 245 | while (csize&3) { 246 | write(1, "\000", 1); 247 | csize++; 248 | } 249 | free(fdat); 250 | 251 | if (compName != NULL) { 252 | if (h.compression==COMPRESS_HEATSHRINK) { 253 | *compName = "heatshrink"; 254 | } else if (h.compression==COMPRESS_NONE) { 255 | if (h.flags & FLAG_GZIP) { 256 | *compName = "gzip"; 257 | } else { 258 | *compName = "none"; 259 | } 260 | } else { 261 | *compName = "unknown"; 262 | } 263 | } 264 | return size ? (csize*100)/size : 100; 265 | } 266 | 267 | //Write final dummy header with FLAG_LASTFILE set. 268 | void finishArchive() { 269 | EspFsHeader h; 270 | h.magic=('E'<<0)+('S'<<8)+('f'<<16)+('s'<<24); 271 | h.flags=FLAG_LASTFILE; 272 | h.compression=COMPRESS_NONE; 273 | h.nameLen=htoxs(0); 274 | h.fileLenComp=htoxl(0); 275 | h.fileLenDecomp=htoxl(0); 276 | write(1, &h, sizeof(EspFsHeader)); 277 | } 278 | 279 | int main(int argc, char **argv) { 280 | int f, x; 281 | char fileName[1024]; 282 | char *realName; 283 | struct stat statBuf; 284 | int serr; 285 | int rate; 286 | int err=0; 287 | int compType; //default compression type - heatshrink 288 | int compLvl=-1; 289 | 290 | #ifdef __MINGW32__ 291 | setmode(fileno(stdout), O_BINARY); 292 | #endif 293 | #ifdef ESPFS_HEATSHRINK 294 | compType = COMPRESS_HEATSHRINK; 295 | #else 296 | compType = COMPRESS_NONE; 297 | #endif 298 | 299 | for (x=1; x=x-2) { 301 | compType=atoi(argv[x+1]); 302 | x++; 303 | } else if (strcmp(argv[x], "-l")==0 && argc>=x-2) { 304 | compLvl=atoi(argv[x+1]); 305 | if (compLvl<1 || compLvl>9) err=1; 306 | x++; 307 | #ifdef ESPFS_GZIP 308 | } else if (strcmp(argv[x], "-g")==0 && argc>=x-2) { 309 | if (!parseGzipExtensions(argv[x+1])) err=1; 310 | x++; 311 | #endif 312 | } else { 313 | err=1; 314 | } 315 | } 316 | 317 | #ifdef ESPFS_GZIP 318 | if (gzipExtensions == NULL) { 319 | parseGzipExtensions(strdup("html,css,js,svg")); 320 | } 321 | #endif 322 | 323 | if (err) { 324 | fprintf(stderr, "%s - Program to create espfs images\n", argv[0]); 325 | fprintf(stderr, "Usage: \nfind | %s [-c compressor] [-l compression_level] ", argv[0]); 326 | #ifdef ESPFS_GZIP 327 | fprintf(stderr, "[-g gzipped_extensions] "); 328 | #endif 329 | fprintf(stderr, "> out.espfs\n"); 330 | fprintf(stderr, "Compressors:\n"); 331 | #ifdef ESPFS_HEATSHRINK 332 | fprintf(stderr, "0 - None\n1 - Heatshrink(default)\n"); 333 | #else 334 | fprintf(stderr, "0 - None(default)\n"); 335 | #endif 336 | fprintf(stderr, "\nCompression level: 1 is worst but low RAM usage, higher is better compression \nbut uses more ram on decompression. -1 = compressors default.\n"); 337 | #ifdef ESPFS_GZIP 338 | fprintf(stderr, "\nGzipped extensions: list of comma separated, case sensitive file extensions \nthat will be gzipped. Defaults to 'html,css,js'\n"); 339 | #endif 340 | exit(0); 341 | } 342 | 343 | while(fgets(fileName, sizeof(fileName), stdin)) { 344 | //Kill off '\n' at the end 345 | fileName[strlen(fileName)-1]=0; 346 | //Only include files 347 | serr=stat(fileName, &statBuf); 348 | if ((serr==0) && S_ISREG(statBuf.st_mode)) { 349 | //Strip off './' or '/' madness. 350 | realName=fileName; 351 | if (fileName[0]=='.') realName++; 352 | if (realName[0]=='/') realName++; 353 | f=open(fileName, O_RDONLY|O_BINARY); 354 | if (f>0) { 355 | char *compName = "unknown"; 356 | rate=handleFile(f, realName, compType, compLvl, &compName); 357 | fprintf(stderr, "%s (%d%%, %s)\n", realName, rate, compName); 358 | close(f); 359 | } else { 360 | perror(fileName); 361 | } 362 | } else { 363 | if (serr!=0) { 364 | perror(fileName); 365 | } 366 | } 367 | } 368 | finishArchive(); 369 | return 0; 370 | } 371 | 372 | -------------------------------------------------------------------------------- /libesphttpd/util/cgiflash.c: -------------------------------------------------------------------------------- 1 | /* 2 | Some flash handling cgi routines. Used for updating the ESPFS/OTA image. 3 | */ 4 | 5 | /* 6 | * ---------------------------------------------------------------------------- 7 | * "THE BEER-WARE LICENSE" (Revision 42): 8 | * Jeroen Domburg wrote this file. As long as you retain 9 | * this notice you can do whatever you want with this stuff. If we meet some day, 10 | * and you think this stuff is worth it, you can buy me a beer in return. 11 | * ---------------------------------------------------------------------------- 12 | */ 13 | 14 | //This doesn't work yet on the ESP32. ToDo: figure out how to make it work. 15 | #ifndef ESP32 16 | 17 | #include 18 | #include "cgiflash.h" 19 | #include "espfs.h" 20 | #include "cgiflash.h" 21 | #include "espfs.h" 22 | 23 | //#include 24 | #include "cgiflash.h" 25 | #include "espfs.h" 26 | 27 | #ifndef UPGRADE_FLAG_FINISH 28 | #define UPGRADE_FLAG_FINISH 0x02 29 | #endif 30 | 31 | // Check that the header of the firmware blob looks like actual firmware... 32 | static int ICACHE_FLASH_ATTR checkBinHeader(void *buf) { 33 | uint8_t *cd = (uint8_t *)buf; 34 | if (cd[0] != 0xEA) return 0; 35 | if (cd[1] != 4 || cd[2] > 3 || cd[3] > 0x40) return 0; 36 | if (((uint16_t *)buf)[3] != 0x4010) return 0; 37 | if (((uint32_t *)buf)[2] != 0) return 0; 38 | return 1; 39 | } 40 | 41 | static int ICACHE_FLASH_ATTR checkEspfsHeader(void *buf) { 42 | if (memcmp(buf, "ESfs", 4)!=0) return 0; 43 | return 1; 44 | } 45 | 46 | 47 | // Cgi to query which firmware needs to be uploaded next 48 | int ICACHE_FLASH_ATTR cgiGetFirmwareNext(HttpdConnData *connData) { 49 | if (connData->conn==NULL) { 50 | //Connection aborted. Clean up. 51 | return HTTPD_CGI_DONE; 52 | } 53 | uint8 id = system_upgrade_userbin_check(); 54 | httpdStartResponse(connData, 200); 55 | httpdHeader(connData, "Content-Type", "text/plain"); 56 | httpdHeader(connData, "Content-Length", "9"); 57 | httpdEndHeaders(connData); 58 | char *next = id == 1 ? "user1.bin" : "user2.bin"; 59 | httpdSend(connData, next, -1); 60 | httpd_printf("Next firmware: %s (got %d)\n", next, id); 61 | return HTTPD_CGI_DONE; 62 | } 63 | 64 | 65 | //Cgi that allows the firmware to be replaced via http POST This takes 66 | //a direct POST from e.g. Curl or a Javascript AJAX call with either the 67 | //firmware given by cgiGetFirmwareNext or an OTA upgrade image. 68 | 69 | //Because we don't have the buffer to allocate an entire sector but will 70 | //have to buffer some data because the post buffer may be misaligned, we 71 | //write SPI data in pages. The page size is a software thing, not 72 | //a hardware one. 73 | #define PAGELEN 64 74 | 75 | #define FLST_START 0 76 | #define FLST_WRITE 1 77 | #define FLST_SKIP 2 78 | #define FLST_DONE 3 79 | #define FLST_ERROR 4 80 | 81 | #define FILETYPE_ESPFS 0 82 | #define FILETYPE_FLASH 1 83 | #define FILETYPE_OTA 2 84 | typedef struct { 85 | int state; 86 | int filetype; 87 | int flashPos; 88 | char pageData[PAGELEN]; 89 | int pagePos; 90 | int address; 91 | int len; 92 | int skip; 93 | char *err; 94 | } UploadState; 95 | 96 | typedef struct __attribute__((packed)) { 97 | char magic[4]; 98 | char tag[28]; 99 | int32_t len1; 100 | int32_t len2; 101 | } OtaHeader; 102 | 103 | 104 | int ICACHE_FLASH_ATTR cgiUploadFirmware(HttpdConnData *connData) { 105 | CgiUploadFlashDef *def=(CgiUploadFlashDef*)connData->cgiArg; 106 | UploadState *state=(UploadState *)connData->cgiData; 107 | int len; 108 | char buff[128]; 109 | 110 | if (connData->conn==NULL) { 111 | //Connection aborted. Clean up. 112 | if (state!=NULL) free(state); 113 | return HTTPD_CGI_DONE; 114 | } 115 | 116 | if (state==NULL) { 117 | //First call. Allocate and initialize state variable. 118 | httpd_printf("Firmware upload cgi start.\n"); 119 | state=malloc(sizeof(UploadState)); 120 | if (state==NULL) { 121 | httpd_printf("Can't allocate firmware upload struct!\n"); 122 | return HTTPD_CGI_DONE; 123 | } 124 | memset(state, 0, sizeof(UploadState)); 125 | state->state=FLST_START; 126 | connData->cgiData=state; 127 | state->err="Premature end"; 128 | } 129 | 130 | char *data=connData->post->buff; 131 | int dataLen=connData->post->buffLen; 132 | 133 | while (dataLen!=0) { 134 | if (state->state==FLST_START) { 135 | //First call. Assume the header of whatever we're uploading already is in the POST buffer. 136 | if (def->type==CGIFLASH_TYPE_FW && memcmp(data, "EHUG", 4)==0) { 137 | //Type is combined flash1/flash2 file 138 | OtaHeader *h=(OtaHeader*)data; 139 | strncpy(buff, h->tag, 27); 140 | buff[27]=0; 141 | if (strcmp(buff, def->tagName)!=0) { 142 | httpd_printf("OTA tag mismatch! Current=`%s` uploaded=`%s`.\n", 143 | def->tagName, buff); 144 | len=httpdFindArg(connData->getArgs, "force", buff, sizeof(buff)); 145 | if (len!=-1 && atoi(buff)) { 146 | httpd_printf("Forcing firmware flash.\n"); 147 | } else { 148 | state->err="Firmware not intended for this device!\n"; 149 | state->state=FLST_ERROR; 150 | } 151 | } 152 | if (state->state!=FLST_ERROR && connData->post->len > def->fwSize*2+sizeof(OtaHeader)) { 153 | state->err="Firmware image too large"; 154 | state->state=FLST_ERROR; 155 | } 156 | if (state->state!=FLST_ERROR) { 157 | //Flash header seems okay. 158 | dataLen-=sizeof(OtaHeader); //skip header when parsing data 159 | data+=sizeof(OtaHeader); 160 | if (system_upgrade_userbin_check()==1) { 161 | httpd_printf("Flashing user1.bin from ota image\n"); 162 | state->len=h->len1; 163 | state->skip=h->len2; 164 | state->state=FLST_WRITE; 165 | state->address=def->fw1Pos; 166 | } else { 167 | httpd_printf("Flashing user2.bin from ota image\n"); 168 | state->len=h->len2; 169 | state->skip=h->len1; 170 | state->state=FLST_SKIP; 171 | state->address=def->fw2Pos; 172 | } 173 | } 174 | } else if (def->type==CGIFLASH_TYPE_FW && checkBinHeader(connData->post->buff)) { 175 | if (connData->post->len > def->fwSize) { 176 | state->err="Firmware image too large"; 177 | state->state=FLST_ERROR; 178 | } else { 179 | state->len=connData->post->len; 180 | state->address=def->fw1Pos; 181 | state->state=FLST_WRITE; 182 | } 183 | } else if (def->type==CGIFLASH_TYPE_ESPFS && checkEspfsHeader(connData->post->buff)) { 184 | if (connData->post->len > def->fwSize) { 185 | state->err="Firmware image too large"; 186 | state->state=FLST_ERROR; 187 | } else { 188 | state->len=connData->post->len; 189 | state->address=def->fw1Pos; 190 | state->state=FLST_WRITE; 191 | } 192 | } else { 193 | state->err="Invalid flash image type!"; 194 | state->state=FLST_ERROR; 195 | httpd_printf("Did not recognize flash image type!\n"); 196 | } 197 | } else if (state->state==FLST_SKIP) { 198 | //Skip bytes without doing anything with them 199 | if (state->skip>dataLen) { 200 | //Skip entire buffer 201 | state->skip-=dataLen; 202 | dataLen=0; 203 | } else { 204 | //Only skip part of buffer 205 | dataLen-=state->skip; 206 | data+=state->skip; 207 | state->skip=0; 208 | if (state->len) state->state=FLST_WRITE; else state->state=FLST_DONE; 209 | } 210 | } else if (state->state==FLST_WRITE) { 211 | //Copy bytes to page buffer, and if page buffer is full, flash the data. 212 | //First, calculate the amount of bytes we need to finish the page buffer. 213 | int lenLeft=PAGELEN-state->pagePos; 214 | if (state->lenlen; //last buffer can be a cut-off one 215 | //See if we need to write the page. 216 | if (dataLenpageData[state->pagePos], data, dataLen); 219 | state->pagePos+=dataLen; 220 | state->len-=dataLen; 221 | dataLen=0; 222 | } else { 223 | //Finish page; take data we need from post buffer 224 | memcpy(&state->pageData[state->pagePos], data, lenLeft); 225 | data+=lenLeft; 226 | dataLen-=lenLeft; 227 | state->pagePos+=lenLeft; 228 | state->len-=lenLeft; 229 | //Erase sector, if needed 230 | if ((state->address&(SPI_FLASH_SEC_SIZE-1))==0) { 231 | spi_flash_erase_sector(state->address/SPI_FLASH_SEC_SIZE); 232 | } 233 | //Write page 234 | //httpd_printf("Writing %d bytes of data to SPI pos 0x%x...\n", state->pagePos, state->address); 235 | spi_flash_write(state->address, (uint32 *)state->pageData, state->pagePos); 236 | state->address+=PAGELEN; 237 | state->pagePos=0; 238 | if (state->len==0) { 239 | //Done. 240 | if (state->skip) state->state=FLST_SKIP; else state->state=FLST_DONE; 241 | } 242 | } 243 | } else if (state->state==FLST_DONE) { 244 | httpd_printf("Huh? %d bogus bytes received after data received.\n", dataLen); 245 | //Ignore those bytes. 246 | dataLen=0; 247 | } else if (state->state==FLST_ERROR) { 248 | //Just eat up any bytes we receive. 249 | dataLen=0; 250 | } 251 | } 252 | 253 | if (connData->post->len==connData->post->received) { 254 | //We're done! Format a response. 255 | httpd_printf("Upload done. Sending response.\n"); 256 | httpdStartResponse(connData, state->state==FLST_ERROR?400:200); 257 | httpdHeader(connData, "Content-Type", "text/plain"); 258 | httpdEndHeaders(connData); 259 | if (state->state!=FLST_DONE) { 260 | httpdSend(connData, "Firmware image error:", -1); 261 | httpdSend(connData, state->err, -1); 262 | httpdSend(connData, "\n", -1); 263 | } 264 | free(state); 265 | return HTTPD_CGI_DONE; 266 | } 267 | 268 | return HTTPD_CGI_MORE; 269 | } 270 | 271 | 272 | 273 | static os_timer_t resetTimer; 274 | 275 | static void ICACHE_FLASH_ATTR resetTimerCb(void *arg) { 276 | system_upgrade_flag_set(UPGRADE_FLAG_FINISH); 277 | system_upgrade_reboot(); 278 | } 279 | 280 | // Handle request to reboot into the new firmware 281 | int ICACHE_FLASH_ATTR cgiRebootFirmware(HttpdConnData *connData) { 282 | if (connData->conn==NULL) { 283 | //Connection aborted. Clean up. 284 | return HTTPD_CGI_DONE; 285 | } 286 | 287 | // TODO: sanity-check that the 'next' partition actually contains something that looks like 288 | // valid firmware 289 | 290 | //Do reboot in a timer callback so we still have time to send the response. 291 | os_timer_disarm(&resetTimer); 292 | os_timer_setfn(&resetTimer, resetTimerCb, NULL); 293 | os_timer_arm(&resetTimer, 200, 0); 294 | 295 | httpdStartResponse(connData, 200); 296 | httpdHeader(connData, "Content-Type", "text/plain"); 297 | httpdEndHeaders(connData); 298 | httpdSend(connData, "Rebooting...", -1); 299 | return HTTPD_CGI_DONE; 300 | } 301 | 302 | #endif -------------------------------------------------------------------------------- /driver_lib/include/gpio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ESPRSSIF MIT License 3 | * 4 | * Copyright (c) 2015 5 | * 6 | * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, 7 | * it is free of charge, to any person obtaining a copy of this software and associated 8 | * documentation files (the "Software"), to deal in the Software without restriction, including 9 | * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the Software is furnished 11 | * to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all copies or 14 | * substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | * 23 | */ 24 | 25 | #ifndef __GPIO_H__ 26 | #define __GPIO_H__ 27 | 28 | #ifdef __cplusplus 29 | extern "C" { 30 | #endif 31 | 32 | #define GPIO_Pin_0 (BIT(0)) /* Pin 0 selected */ 33 | #define GPIO_Pin_1 (BIT(1)) /* Pin 1 selected */ 34 | #define GPIO_Pin_2 (BIT(2)) /* Pin 2 selected */ 35 | #define GPIO_Pin_3 (BIT(3)) /* Pin 3 selected */ 36 | #define GPIO_Pin_4 (BIT(4)) /* Pin 4 selected */ 37 | #define GPIO_Pin_5 (BIT(5)) /* Pin 5 selected */ 38 | #define GPIO_Pin_6 (BIT(6)) /* Pin 6 selected */ 39 | #define GPIO_Pin_7 (BIT(7)) /* Pin 7 selected */ 40 | #define GPIO_Pin_8 (BIT(8)) /* Pin 8 selected */ 41 | #define GPIO_Pin_9 (BIT(9)) /* Pin 9 selected */ 42 | #define GPIO_Pin_10 (BIT(10)) /* Pin 10 selected */ 43 | #define GPIO_Pin_11 (BIT(11)) /* Pin 11 selected */ 44 | #define GPIO_Pin_12 (BIT(12)) /* Pin 12 selected */ 45 | #define GPIO_Pin_13 (BIT(13)) /* Pin 13 selected */ 46 | #define GPIO_Pin_14 (BIT(14)) /* Pin 14 selected */ 47 | #define GPIO_Pin_15 (BIT(15)) /* Pin 15 selected */ 48 | #define GPIO_Pin_All (0xFFFF) /* All pins selected */ 49 | 50 | #define GPIO_PIN_REG_0 PERIPHS_IO_MUX_GPIO0_U 51 | #define GPIO_PIN_REG_1 PERIPHS_IO_MUX_U0TXD_U 52 | #define GPIO_PIN_REG_2 PERIPHS_IO_MUX_GPIO2_U 53 | #define GPIO_PIN_REG_3 PERIPHS_IO_MUX_U0RXD_U 54 | #define GPIO_PIN_REG_4 PERIPHS_IO_MUX_GPIO4_U 55 | #define GPIO_PIN_REG_5 PERIPHS_IO_MUX_GPIO5_U 56 | #define GPIO_PIN_REG_6 PERIPHS_IO_MUX_SD_CLK_U 57 | #define GPIO_PIN_REG_7 PERIPHS_IO_MUX_SD_DATA0_U 58 | #define GPIO_PIN_REG_8 PERIPHS_IO_MUX_SD_DATA1_U 59 | #define GPIO_PIN_REG_9 PERIPHS_IO_MUX_SD_DATA2_U 60 | #define GPIO_PIN_REG_10 PERIPHS_IO_MUX_SD_DATA3_U 61 | #define GPIO_PIN_REG_11 PERIPHS_IO_MUX_SD_CMD_U 62 | #define GPIO_PIN_REG_12 PERIPHS_IO_MUX_MTDI_U 63 | #define GPIO_PIN_REG_13 PERIPHS_IO_MUX_MTCK_U 64 | #define GPIO_PIN_REG_14 PERIPHS_IO_MUX_MTMS_U 65 | #define GPIO_PIN_REG_15 PERIPHS_IO_MUX_MTDO_U 66 | 67 | #define GPIO_PIN_REG(i) \ 68 | (i==0) ? GPIO_PIN_REG_0: \ 69 | (i==1) ? GPIO_PIN_REG_1: \ 70 | (i==2) ? GPIO_PIN_REG_2: \ 71 | (i==3) ? GPIO_PIN_REG_3: \ 72 | (i==4) ? GPIO_PIN_REG_4: \ 73 | (i==5) ? GPIO_PIN_REG_5: \ 74 | (i==6) ? GPIO_PIN_REG_6: \ 75 | (i==7) ? GPIO_PIN_REG_7: \ 76 | (i==8) ? GPIO_PIN_REG_8: \ 77 | (i==9) ? GPIO_PIN_REG_9: \ 78 | (i==10)? GPIO_PIN_REG_10: \ 79 | (i==11)? GPIO_PIN_REG_11: \ 80 | (i==12)? GPIO_PIN_REG_12: \ 81 | (i==13)? GPIO_PIN_REG_13: \ 82 | (i==14)? GPIO_PIN_REG_14: \ 83 | GPIO_PIN_REG_15 84 | 85 | #define GPIO_PIN_ADDR(i) (GPIO_PIN0_ADDRESS + i*4) 86 | 87 | #define GPIO_ID_IS_PIN_REGISTER(reg_id) \ 88 | ((reg_id >= GPIO_ID_PIN0) && (reg_id <= GPIO_ID_PIN(GPIO_PIN_COUNT-1))) 89 | 90 | #define GPIO_REGID_TO_PINIDX(reg_id) ((reg_id) - GPIO_ID_PIN0) 91 | 92 | typedef enum { 93 | GPIO_PIN_INTR_DISABLE = 0, /**< disable GPIO interrupt */ 94 | GPIO_PIN_INTR_POSEDGE = 1, /**< GPIO interrupt type : rising edge */ 95 | GPIO_PIN_INTR_NEGEDGE = 2, /**< GPIO interrupt type : falling edge */ 96 | GPIO_PIN_INTR_ANYEDGE = 3, /**< GPIO interrupt type : bothe rising and falling edge */ 97 | GPIO_PIN_INTR_LOLEVEL = 4, /**< GPIO interrupt type : low level */ 98 | GPIO_PIN_INTR_HILEVEL = 5 /**< GPIO interrupt type : high level */ 99 | } GPIO_INT_TYPE; 100 | 101 | typedef enum { 102 | GPIO_Mode_Input = 0x0, /**< GPIO mode : Input */ 103 | GPIO_Mode_Out_OD, /**< GPIO mode : Output_OD */ 104 | GPIO_Mode_Output , /**< GPIO mode : Output */ 105 | GPIO_Mode_Sigma_Delta , /**< GPIO mode : Sigma_Delta */ 106 | } GPIOMode_TypeDef; 107 | 108 | typedef enum { 109 | GPIO_PullUp_DIS = 0x0, /**< disable GPIO pullup */ 110 | GPIO_PullUp_EN = 0x1, /**< enable GPIO pullup */ 111 | } GPIO_Pullup_IF; 112 | 113 | typedef struct { 114 | uint16 GPIO_Pin; /**< GPIO pin */ 115 | GPIOMode_TypeDef GPIO_Mode; /**< GPIO mode */ 116 | GPIO_Pullup_IF GPIO_Pullup; /**< GPIO pullup */ 117 | GPIO_INT_TYPE GPIO_IntrType; /**< GPIO interrupt type */ 118 | } GPIO_ConfigTypeDef; 119 | 120 | /** \defgroup Driver_APIs Driver APIs 121 | * @brief Driver APIs 122 | */ 123 | 124 | /** @addtogroup Driver_APIs 125 | * @{ 126 | */ 127 | 128 | /** \defgroup GPIO_Driver_APIs GPIO Driver APIs 129 | * @brief GPIO APIs 130 | */ 131 | 132 | /** @addtogroup GPIO_Driver_APIs 133 | * @{ 134 | */ 135 | 136 | /** 137 | * @brief Set GPIO pin output level. 138 | * 139 | * @param gpio_no : The GPIO sequence number. 140 | * @param bit_value : GPIO pin output level. 141 | * 142 | * @return null 143 | */ 144 | #define GPIO_OUTPUT_SET(gpio_no, bit_value) \ 145 | gpio_output_conf(bit_value<>gpio_no)&BIT0) 194 | 195 | /** 196 | * @brief Enable GPIO16 output. 197 | * 198 | * @param null 199 | * 200 | * @return null 201 | */ 202 | void gpio16_output_conf(void); 203 | 204 | /** 205 | * @brief Set GPIO16 output level. 206 | * 207 | * @param uint8 value : GPIO16 output level. 208 | * 209 | * @return null 210 | */ 211 | void gpio16_output_set(uint8 value); 212 | 213 | /** 214 | * @brief Enable GPIO pin intput. 215 | * 216 | * @param null 217 | * 218 | * @return null 219 | */ 220 | void gpio16_input_conf(void); 221 | 222 | /** 223 | * @brief Sample the value of GPIO16 input. 224 | * 225 | * @param null 226 | * 227 | * @return the level of GPIO16 input. 228 | */ 229 | uint8 gpio16_input_get(void); 230 | 231 | /** 232 | * @brief Configure Gpio pins out or input. 233 | * 234 | * @param uint32 set_mask : Set the output for the high bit, the 235 | * corresponding bit is 1, the output of high, 236 | * the corresponding bit is 0, do not change the state. 237 | * @param uint32 set_mask : Set the output for the high bit, the 238 | * corresponding bit is 1, the output of low, 239 | * the corresponding bit is 0, do not change the state. 240 | * @param uint32 enable_mask : Enable Output 241 | * @param uint32 disable_mask : Enable Input 242 | * 243 | * @return null 244 | */ 245 | void gpio_output_conf(uint32 set_mask, uint32 clear_mask, uint32 enable_mask, uint32 disable_mask); 246 | 247 | /** 248 | * @brief Register an application-specific interrupt handler for GPIO pin interrupts. 249 | * 250 | * @param void *fn:interrupt handler for GPIO pin interrupts. 251 | * @param void *arg:interrupt handler's arg 252 | * 253 | * @return null 254 | */ 255 | void gpio_intr_handler_register(void *fn, void *arg); 256 | 257 | /** 258 | * @brief Configure GPIO wake up to light sleep,Only level way is effective. 259 | * 260 | * @param uint32 i : Gpio sequence number 261 | * @param GPIO_INT_TYPE intr_state : the level of wake up to light sleep 262 | * 263 | * @return null 264 | */ 265 | void gpio_pin_wakeup_enable(uint32 i, GPIO_INT_TYPE intr_state); 266 | 267 | /** 268 | * @brief Disable GPIO wake up to light sleep. 269 | * 270 | * @param null 271 | * 272 | * @return null 273 | */ 274 | void gpio_pin_wakeup_disable(); 275 | 276 | /** 277 | * @brief Config interrupt types of GPIO pin. 278 | * 279 | * @param uint32 i : The GPIO sequence number. 280 | * @param GPIO_INT_TYPE intr_state : GPIO interrupt types. 281 | * 282 | * @return null 283 | */ 284 | void gpio_pin_intr_state_set(uint32 i, GPIO_INT_TYPE intr_state); 285 | 286 | /** 287 | * @brief Sample the value of GPIO input pins and returns a bitmask. 288 | * 289 | * @param null 290 | * 291 | * @return bitmask of GPIO pins input 292 | */ 293 | uint32 gpio_input_get(void); 294 | 295 | /** 296 | * @} 297 | */ 298 | 299 | /** 300 | * @} 301 | */ 302 | 303 | #ifdef __cplusplus 304 | } 305 | #endif 306 | 307 | #endif 308 | --------------------------------------------------------------------------------