diff --git a/cores/esp8266/TZ.h b/cores/esp8266/TZ.h index 61e247e27..cd083e7fd 100644 --- a/cores/esp8266/TZ.h +++ b/cores/esp8266/TZ.h @@ -1,10 +1,11 @@ // autogenerated from https://raw.githubusercontent.com/nayarsystems/posix_tz_db/master/zones.csv // by script /tools/TZupdate.sh -// Tue Jul 7 07:38:29 UTC 2020 +// Thu Nov 12 04:07:03 UTC 2020 // // This database is autogenerated from IANA timezone database -// https://www.iana.org/time-zones +// https://raw.githubusercontent.com/nayarsystems/posix_tz_db/master/zones.csv +// (using https://www.iana.org/time-zones) // and can be updated on demand in this repository // or by yourself using the above script @@ -211,10 +212,10 @@ #define TZ_America_Winnipeg PSTR("CST6CDT,M3.2.0,M11.1.0") #define TZ_America_Yakutat PSTR("AKST9AKDT,M3.2.0,M11.1.0") #define TZ_America_Yellowknife PSTR("MST7MDT,M3.2.0,M11.1.0") -#define TZ_Antarctica_Casey PSTR("<+08>-8") +#define TZ_Antarctica_Casey PSTR("<+11>-11") #define TZ_Antarctica_Davis PSTR("<+07>-7") #define TZ_Antarctica_DumontDUrville PSTR("<+10>-10") -#define TZ_Antarctica_Macquarie PSTR("<+11>-11") +#define TZ_Antarctica_Macquarie PSTR("AEST-10AEDT,M10.1.0,M4.1.0/3") #define TZ_Antarctica_Mawson PSTR("<+05>-5") #define TZ_Antarctica_McMurdo PSTR("NZST-12NZDT,M9.5.0,M4.1.0/3") #define TZ_Antarctica_Palmer PSTR("<-03>3") @@ -248,8 +249,8 @@ #define TZ_Asia_Dubai PSTR("<+04>-4") #define TZ_Asia_Dushanbe PSTR("<+05>-5") #define TZ_Asia_Famagusta PSTR("EET-2EEST,M3.5.0/3,M10.5.0/4") -#define TZ_Asia_Gaza PSTR("EET-2EEST,M3.5.5/0,M10.5.6/1") -#define TZ_Asia_Hebron PSTR("EET-2EEST,M3.5.5/0,M10.5.6/1") +#define TZ_Asia_Gaza PSTR("EET-2EEST,M3.4.4/48,M10.4.4/49") +#define TZ_Asia_Hebron PSTR("EET-2EEST,M3.4.4/48,M10.4.4/49") #define TZ_Asia_Ho_Chi_Minh PSTR("<+07>-7") #define TZ_Asia_Hong_Kong PSTR("HKT-8") #define TZ_Asia_Hovd PSTR("<+07>-7") diff --git a/cores/esp8266/WString.cpp b/cores/esp8266/WString.cpp index 056bbeb98..3dda69bda 100644 --- a/cores/esp8266/WString.cpp +++ b/cores/esp8266/WString.cpp @@ -617,17 +617,33 @@ int String::indexOf(char ch, unsigned int fromIndex) const { return temp - buffer(); } +int String::indexOf(const __FlashStringHelper *s2) const { + return indexOf(s2, 0); +} + +int String::indexOf(const __FlashStringHelper *s2, unsigned int fromIndex) const { + return indexOf((const char*) s2, fromIndex); +} + +int String::indexOf(const char *s2) const { + return indexOf(s2, 0); +} + +int String::indexOf(const char *s2, unsigned int fromIndex) const { + if (fromIndex >= len()) + return -1; + const char *found = strstr_P(buffer() + fromIndex, s2); + if (found == NULL) + return -1; + return found - buffer(); +} + int String::indexOf(const String &s2) const { return indexOf(s2, 0); } int String::indexOf(const String &s2, unsigned int fromIndex) const { - if (fromIndex >= len()) - return -1; - const char *found = strstr(buffer() + fromIndex, s2.buffer()); - if (found == NULL) - return -1; - return found - buffer(); + return indexOf(s2.c_str(), fromIndex); } int String::lastIndexOf(char theChar) const { diff --git a/cores/esp8266/WString.h b/cores/esp8266/WString.h index c9b79f21c..262cfda0a 100644 --- a/cores/esp8266/WString.h +++ b/cores/esp8266/WString.h @@ -235,6 +235,10 @@ class String { // search int indexOf(char ch) const; int indexOf(char ch, unsigned int fromIndex) const; + int indexOf(const char *str) const; + int indexOf(const char *str, unsigned int fromIndex) const; + int indexOf(const __FlashStringHelper *str) const; + int indexOf(const __FlashStringHelper *str, unsigned int fromIndex) const; int indexOf(const String &str) const; int indexOf(const String &str, unsigned int fromIndex) const; int lastIndexOf(char ch) const; diff --git a/doc/esp8266wifi/server-examples.rst b/doc/esp8266wifi/server-examples.rst index 5a684d5cc..cdd18fe81 100644 --- a/doc/esp8266wifi/server-examples.rst +++ b/doc/esp8266wifi/server-examples.rst @@ -39,17 +39,19 @@ Then let's write a short function ``prepareHtmlPage()``, that will return a ``St String prepareHtmlPage() { - String htmlPage = - String("HTTP/1.1 200 OK\r\n") + - "Content-Type: text/html\r\n" + - "Connection: close\r\n" + // the connection will be closed after completion of the response - "Refresh: 5\r\n" + // refresh the page automatically every 5 sec - "\r\n" + - "" + - "" + - "Analog input: " + String(analogRead(A0)) + - "" + - "\r\n"; + String htmlPage; + htmlPage.reserve(1024); // prevent ram fragmentation + htmlPage = F("HTTP/1.1 200 OK\r\n" + "Content-Type: text/html\r\n" + "Connection: close\r\n" // the connection will be closed after completion of the response + "Refresh: 5\r\n" // refresh the page automatically every 5 sec + "\r\n" + "" + "" + "Analog input: "); + htmlPage += analogRead(A0); + htmlPage += F("" + "\r\n"); return htmlPage; } @@ -79,7 +81,7 @@ The content contains two basic `HTML `__ tags, .. code:: cpp - String(analogRead(A0)) + analogRead(A0) The Page is Served ~~~~~~~~~~~~~~~~~~ @@ -90,7 +92,7 @@ Serving of this web page will be done in the ``loop()`` where server is waiting void loop() { - WiFiClient client = server.available(); + WiFiClient client = server.available(); if (client) { // we have a new client sending some request @@ -126,6 +128,18 @@ The whole process is concluded by stopping the connection with client: client.stop(); +But before that, we must not interrupt client's request: + +.. code:: cpp + + while (client.available()) { + // but first, let client finish its request + // that's diplomatic compliance to protocols + // (and otherwise some clients may complain, like curl) + // (that is an example, prefer using a proper webserver library) + client.read(); + } + Put it Together ~~~~~~~~~~~~~~~ @@ -163,24 +177,26 @@ Complete sketch is presented below. // prepare a web page to be send to a client (web browser) String prepareHtmlPage() { - String htmlPage = - String("HTTP/1.1 200 OK\r\n") + - "Content-Type: text/html\r\n" + - "Connection: close\r\n" + // the connection will be closed after completion of the response - "Refresh: 5\r\n" + // refresh the page automatically every 5 sec - "\r\n" + - "" + - "" + - "Analog input: " + String(analogRead(A0)) + - "" + - "\r\n"; + String htmlPage; + htmlPage.reserve(1024); // prevent ram fragmentation + htmlPage = F("HTTP/1.1 200 OK\r\n" + "Content-Type: text/html\r\n" + "Connection: close\r\n" // the connection will be closed after completion of the response + "Refresh: 5\r\n" // refresh the page automatically every 5 sec + "\r\n" + "" + "" + "Analog input: "); + htmlPage += analogRead(A0); + htmlPage += F("" + "\r\n"); return htmlPage; } void loop() { - WiFiClient client = server.available(); + WiFiClient client = server.available(); // wait for a client (web browser) to connect if (client) { @@ -200,7 +216,14 @@ Complete sketch is presented below. } } } - delay(1); // give the web browser time to receive the data + + while (client.available()) { + // but first, let client finish its request + // that's diplomatic compliance to protocols + // (and otherwise some clients may complain, like curl) + // (that is an example, prefer using a proper webserver library) + client.read(); + } // close the connection: client.stop(); diff --git a/libraries/Servo/src/Servo.cpp b/libraries/Servo/src/Servo.cpp index 3dc2c7753..aff9afebb 100644 --- a/libraries/Servo/src/Servo.cpp +++ b/libraries/Servo/src/Servo.cpp @@ -27,15 +27,15 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA uint32_t Servo::_servoMap = 0; // similiar to map but will have increased accuracy that provides a more -// symetric api (call it and use result to reverse will provide the original value) +// symmetrical api (call it and use result to reverse will provide the original value) int improved_map(int value, int minIn, int maxIn, int minOut, int maxOut) { const int rangeIn = maxIn - minIn; const int rangeOut = maxOut - minOut; const int deltaIn = value - minIn; // fixed point math constants to improve accurancy of divide and rounding - const int fixedHalfDecimal = 1; - const int fixedDecimal = fixedHalfDecimal * 2; + constexpr int fixedHalfDecimal = 1; + constexpr int fixedDecimal = fixedHalfDecimal * 2; return ((deltaIn * rangeOut * fixedDecimal) / (rangeIn) + fixedHalfDecimal) / fixedDecimal + minOut; } @@ -46,9 +46,9 @@ int improved_map(int value, int minIn, int maxIn, int minOut, int maxOut) Servo::Servo() { _attached = false; - _valueUs = DEFAULT_PULSE_WIDTH; - _minUs = MIN_PULSE_WIDTH; - _maxUs = MAX_PULSE_WIDTH; + _valueUs = DEFAULT_NEUTRAL_PULSE_WIDTH; + _minUs = DEFAULT_MIN_PULSE_WIDTH; + _maxUs = DEFAULT_MAX_PULSE_WIDTH; } Servo::~Servo() { @@ -58,10 +58,15 @@ Servo::~Servo() { uint8_t Servo::attach(int pin) { - return attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH); + return attach(pin, DEFAULT_MIN_PULSE_WIDTH, DEFAULT_MAX_PULSE_WIDTH); } uint8_t Servo::attach(int pin, uint16_t minUs, uint16_t maxUs) +{ + return attach(pin, minUs, maxUs, _valueUs); +} + +uint8_t Servo::attach(int pin, uint16_t minUs, uint16_t maxUs, int value) { if (!_attached) { digitalWrite(pin, LOW); @@ -76,7 +81,7 @@ uint8_t Servo::attach(int pin, uint16_t minUs, uint16_t maxUs) _maxUs = max((uint16_t)250, min((uint16_t)3000, maxUs)); _minUs = max((uint16_t)200, min(_maxUs, minUs)); - write(_valueUs); + write(value); return pin; } @@ -85,20 +90,20 @@ void Servo::detach() { if (_attached) { _servoMap &= ~(1 << _pin); + startWaveform(_pin, 0, REFRESH_INTERVAL, 1); + delay(REFRESH_INTERVAL / 1000); // long enough to complete active period under all circumstances. stopWaveform(_pin); _attached = false; - digitalWrite(_pin, LOW); + _valueUs = DEFAULT_NEUTRAL_PULSE_WIDTH; } } void Servo::write(int value) { - // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds) - if (value < _minUs) { + // treat any value less than 200 as angle in degrees (values equal or larger are handled as microseconds) + if (value < 200) { // assumed to be 0-180 degrees servo value = constrain(value, 0, 180); - // writeMicroseconds will contrain the calculated value for us - // for any user defined min and max, but we must use default min max value = improved_map(value, 0, 180, _minUs, _maxUs); } writeMicroseconds(value); @@ -106,6 +111,7 @@ void Servo::write(int value) void Servo::writeMicroseconds(int value) { + value = constrain(value, _minUs, _maxUs); _valueUs = value; if (_attached) { _servoMap &= ~(1 << _pin); @@ -117,8 +123,7 @@ void Servo::writeMicroseconds(int value) int Servo::read() // return the value as degrees { - // read returns the angle for an assumed 0-180, so we calculate using - // the normal min/max constants and not user defined ones + // read returns the angle for an assumed 0-180 return improved_map(readMicroseconds(), _minUs, _maxUs, 0, 180); } diff --git a/libraries/Servo/src/Servo.h b/libraries/Servo/src/Servo.h index 45f593c0d..38d78709a 100644 --- a/libraries/Servo/src/Servo.h +++ b/libraries/Servo/src/Servo.h @@ -27,9 +27,9 @@ // // Servo - Class for manipulating servo motors connected to Arduino pins. // -// attach(pin ) - Attaches a servo motor to an i/o pin. -// attach(pin, min, max ) - Attaches to a pin setting min and max values in microseconds -// default min is 544, max is 2400 +// attach(pin) - Attaches a servo motor to an i/o pin. +// attach(pin, min, max) - Attaches to a pin setting min and max values in microseconds +// default min is 1000, max is 2000 // // write() - Sets the servo angle in degrees. (invalid angle that is valid as pulse in microseconds is treated as microseconds) // writeMicroseconds() - Sets the servo pulse width in microseconds @@ -44,13 +44,17 @@ #include -// the following are in us (microseconds) -// -#define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo -#define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo -#define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached -#define REFRESH_INTERVAL 20000 // minumim time to refresh servos in microseconds -#define MAX_SERVOS 12 +// The following values are in us (microseconds). +// Since the defaults can be overwritten in the new attach() member function, +// they were modified from the Arduino AVR defaults to be in the safe range +// of publically available specifications. While this implies that many 180° +// servos do not operate the full 0° to 180° sweep using these, it also prevents +// unsuspecting damage. For Arduino AVR, the same change is being discussed. +#define DEFAULT_MIN_PULSE_WIDTH 1000 // uncalibrated default, the shortest duty cycle sent to a servo +#define DEFAULT_MAX_PULSE_WIDTH 2000 // uncalibrated default, the longest duty cycle sent to a servo +#define DEFAULT_NEUTRAL_PULSE_WIDTH 1500 // default duty cycle when servo is attached +#define REFRESH_INTERVAL 20000 // classic default period to refresh servos in microseconds +#define MAX_SERVOS 9 // D0-D8 #if !defined(ESP8266) @@ -63,8 +67,16 @@ class Servo public: Servo(); ~Servo(); - uint8_t attach(int pin); // attach the given pin to the next free channel, sets pinMode, returns channel number or 0 if failure - uint8_t attach(int pin, uint16_t min, uint16_t max); // as above but also sets min and max values for writes. + // attach the given pin to the next free channel, sets pinMode, returns channel number or 0 if failure. + // returns channel number or 0 if failure. + uint8_t attach(int pin); + // attach the given pin to the next free channel, sets pinMode, min, and max values for write(). + // returns channel number or 0 if failure. + uint8_t attach(int pin, uint16_t min, uint16_t max); + // attach the given pin to the next free channel, sets pinMode, min, and max values for write(), + // and sets the initial value, the same as write(). + // returns channel number or 0 if failure. + uint8_t attach(int pin, uint16_t min, uint16_t max, int value); void detach(); void write(int value); // if value is < 200 its treated as an angle, otherwise as pulse width in microseconds void writeMicroseconds(int value); // Write pulse width in microseconds diff --git a/platform.txt b/platform.txt index c68d1985f..5e2c9be54 100644 --- a/platform.txt +++ b/platform.txt @@ -55,7 +55,7 @@ compiler.libc.path={runtime.platform.path}/tools/sdk/libc/xtensa-lx106-elf compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include" "-I{compiler.sdk.path}/{build.lwip_include}" "-I{compiler.libc.path}/include" "-I{build.path}/core" compiler.c.cmd=xtensa-lx106-elf-gcc -compiler.c.flags=-c {compiler.warning_flags} -std=c17 {build.stacksmash_flags} -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -ffunction-sections -fdata-sections {build.exception_flags} {build.sslflags} +compiler.c.flags=-c {compiler.warning_flags} -std=gnu17 {build.stacksmash_flags} -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -ffunction-sections -fdata-sections {build.exception_flags} {build.sslflags} compiler.S.cmd=xtensa-lx106-elf-gcc compiler.S.flags=-c -g -x assembler-with-cpp -MMD -mlongcalls diff --git a/tests/host/core/test_string.cpp b/tests/host/core/test_string.cpp index f9fb30a6d..1150ba591 100644 --- a/tests/host/core/test_string.cpp +++ b/tests/host/core/test_string.cpp @@ -245,6 +245,10 @@ TEST_CASE("String nulls", "[core][String]") REQUIRE(s.lastIndexOf("tacos") == -1); REQUIRE(s.lastIndexOf('t', 0) == -1); REQUIRE(s.lastIndexOf('t') == -1); + REQUIRE(s.indexOf(String("tacos"), 1) == -1); + REQUIRE(s.indexOf(String("tacos")) == -1); + REQUIRE(s.indexOf(F("tacos"), 1) == -1); + REQUIRE(s.indexOf(F("tacos")) == -1); REQUIRE(s.indexOf("tacos", 1) == -1); REQUIRE(s.indexOf("tacos") == -1); REQUIRE(s.indexOf('t', 1) == -1); diff --git a/tools/TZupdate.sh b/tools/TZupdate.sh index 4c0d09e80..3c6f41e15 100755 --- a/tools/TZupdate.sh +++ b/tools/TZupdate.sh @@ -36,7 +36,8 @@ cat << EOF // $(date -u) // // This database is autogenerated from IANA timezone database -// https://www.iana.org/time-zones +// ${csv} +// (using https://www.iana.org/time-zones) // and can be updated on demand in this repository // or by yourself using the above script diff --git a/tools/platformio-build.py b/tools/platformio-build.py index 1af8ff9a3..9dfc9277d 100644 --- a/tools/platformio-build.py +++ b/tools/platformio-build.py @@ -54,7 +54,7 @@ env.Append( ASFLAGS=["-x", "assembler-with-cpp"], CFLAGS=[ - "-std=c17", + "-std=gnu17", "-Wpointer-arith", "-Wno-implicit-function-declaration", "-Wl,-EL", diff --git a/tools/sdk/include/sntp.h b/tools/sdk/include/sntp.h index bb85e678b..23275f182 100644 --- a/tools/sdk/include/sntp.h +++ b/tools/sdk/include/sntp.h @@ -18,7 +18,7 @@ uint32 sntp_get_current_timestamp(); /** * get real time (GTM + 8 time zone) */ -char* sntp_get_real_time(long t); +char* sntp_get_real_time(time_t t); /** * SNTP get time_zone default GMT + 8 */ diff --git a/tools/sdk/libc/xtensa-lx106-elf/lib/crt0.o b/tools/sdk/libc/xtensa-lx106-elf/lib/crt0.o index 9e0d1fef3..6fdc0ae02 100644 Binary files a/tools/sdk/libc/xtensa-lx106-elf/lib/crt0.o and b/tools/sdk/libc/xtensa-lx106-elf/lib/crt0.o differ diff --git a/tools/sdk/libc/xtensa-lx106-elf/lib/libc.a b/tools/sdk/libc/xtensa-lx106-elf/lib/libc.a index 5d82b0321..0e99ad467 100644 Binary files a/tools/sdk/libc/xtensa-lx106-elf/lib/libc.a and b/tools/sdk/libc/xtensa-lx106-elf/lib/libc.a differ diff --git a/tools/sdk/libc/xtensa-lx106-elf/lib/libg.a b/tools/sdk/libc/xtensa-lx106-elf/lib/libg.a index 5d82b0321..0e99ad467 100644 Binary files a/tools/sdk/libc/xtensa-lx106-elf/lib/libg.a and b/tools/sdk/libc/xtensa-lx106-elf/lib/libg.a differ diff --git a/tools/sdk/libc/xtensa-lx106-elf/lib/libm.a b/tools/sdk/libc/xtensa-lx106-elf/lib/libm.a index cf427e2d9..7f250e2fc 100644 Binary files a/tools/sdk/libc/xtensa-lx106-elf/lib/libm.a and b/tools/sdk/libc/xtensa-lx106-elf/lib/libm.a differ