+
+const byte DNS_PORT = 53;
+IPAddress apIP(192, 168, 1, 1);
+DNSServer dnsServer;
+ESP8266WebServer webServer(80);
+
+String responseHTML = ""
+ "CaptivePortal"
+ "Hello World!
This is a captive portal example. All requests will "
+ "be redirected here.
";
+
+void setup() {
+ WiFi.mode(WIFI_AP);
+ WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
+ WiFi.softAP("DNSServer CaptivePortal example");
+
+ // if DNSServer is started with "*" for domain name, it will reply with
+ // provided IP to all DNS request
+ dnsServer.start(DNS_PORT, "*", apIP);
+
+ // replay to all requests with same HTML
+ webServer.onNotFound([]() {
+ webServer.send(200, "text/html", responseHTML);
+ });
+ webServer.begin();
+}
+
+void loop() {
+ dnsServer.processNextRequest();
+ webServer.handleClient();
+}
diff --git a/hardware/esp8266com/esp8266/libraries/DNSServer/examples/DNSServer/DNSServer.ino b/hardware/esp8266com/esp8266/libraries/DNSServer/examples/DNSServer/DNSServer.ino
new file mode 100644
index 0000000000..2916d5ab3c
--- /dev/null
+++ b/hardware/esp8266com/esp8266/libraries/DNSServer/examples/DNSServer/DNSServer.ino
@@ -0,0 +1,41 @@
+#include
+#include
+#include
+
+const byte DNS_PORT = 53;
+IPAddress apIP(192, 168, 1, 1);
+DNSServer dnsServer;
+ESP8266WebServer webServer(80);
+
+void setup() {
+ WiFi.mode(WIFI_AP);
+ WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
+ WiFi.softAP("DNSServer example");
+
+ // modify TTL associated with the domain name (in seconds)
+ // default is 60 seconds
+ dnsServer.setTTL(300);
+ // set which return code will be used for all other domains (e.g. sending
+ // ServerFailure instead of NonExistentDomain will reduce number of queries
+ // sent by clients)
+ // default is DNSReplyCode::NonExistentDomain
+ dnsServer.setErrorReplyCode(DNSReplyCode::ServerFailure);
+
+ // start DNS server for a specific domain name
+ dnsServer.start(DNS_PORT, "www.example.com", apIP);
+
+ // simple HTTP server to see that DNS server is working
+ webServer.onNotFound([]() {
+ String message = "Hello World!\n\n";
+ message += "URI: ";
+ message += webServer.uri();
+
+ webServer.send(200, "text/plain", message);
+ });
+ webServer.begin();
+}
+
+void loop() {
+ dnsServer.processNextRequest();
+ webServer.handleClient();
+}
diff --git a/hardware/esp8266com/esp8266/libraries/DNSServer/library.properties b/hardware/esp8266com/esp8266/libraries/DNSServer/library.properties
new file mode 100644
index 0000000000..71f0ae5440
--- /dev/null
+++ b/hardware/esp8266com/esp8266/libraries/DNSServer/library.properties
@@ -0,0 +1,9 @@
+name=DNSServer
+version=1.1.0
+author=Kristijan Novoselić
+maintainer=Kristijan Novoselić,
+sentence=A simple DNS server for ESP8266.
+paragraph=This library implements a simple DNS server.
+category=Communication
+url=
+architectures=esp8266
diff --git a/hardware/esp8266com/esp8266/libraries/DNSServer/src/DNSServer.cpp b/hardware/esp8266com/esp8266/libraries/DNSServer/src/DNSServer.cpp
new file mode 100644
index 0000000000..10fc81d4a9
--- /dev/null
+++ b/hardware/esp8266com/esp8266/libraries/DNSServer/src/DNSServer.cpp
@@ -0,0 +1,134 @@
+#include "DNSServer.h"
+#include
+#include
+
+DNSServer::DNSServer()
+{
+ _ttl = htonl(60);
+ _errorReplyCode = DNSReplyCode::NonExistentDomain;
+}
+
+bool DNSServer::start(const uint16_t &port, const String &domainName,
+ const IPAddress &resolvedIP)
+{
+ _port = port;
+ _domainName = domainName;
+ _resolvedIP[0] = resolvedIP[0];
+ _resolvedIP[1] = resolvedIP[1];
+ _resolvedIP[2] = resolvedIP[2];
+ _resolvedIP[3] = resolvedIP[3];
+ downcaseAndRemoveWwwPrefix(_domainName);
+ return _udp.begin(_port) == 1;
+}
+
+void DNSServer::setErrorReplyCode(const DNSReplyCode &replyCode)
+{
+ _errorReplyCode = replyCode;
+}
+
+void DNSServer::setTTL(const uint32_t &ttl)
+{
+ _ttl = htonl(ttl);
+}
+
+void DNSServer::stop()
+{
+ _udp.stop();
+}
+
+void DNSServer::downcaseAndRemoveWwwPrefix(String &domainName)
+{
+ domainName.toLowerCase();
+ domainName.replace("www.", "");
+}
+
+void DNSServer::processNextRequest()
+{
+ _currentPacketSize = _udp.parsePacket();
+ if (_currentPacketSize)
+ {
+ _buffer = (unsigned char*)malloc(_currentPacketSize * sizeof(char));
+ _udp.read(_buffer, _currentPacketSize);
+ _dnsHeader = (DNSHeader*) _buffer;
+
+ if (_dnsHeader->QR == DNS_QR_QUERY &&
+ _dnsHeader->OPCode == DNS_OPCODE_QUERY &&
+ requestIncludesOnlyOneQuestion() &&
+ (_domainName == "*" || getDomainNameWithoutWwwPrefix() == _domainName)
+ )
+ {
+ replyWithIP();
+ }
+ else if (_dnsHeader->QR == DNS_QR_QUERY)
+ {
+ replyWithCustomCode();
+ }
+
+ free(_buffer);
+ }
+}
+
+bool DNSServer::requestIncludesOnlyOneQuestion()
+{
+ return ntohs(_dnsHeader->QDCount) == 1 &&
+ _dnsHeader->ANCount == 0 &&
+ _dnsHeader->NSCount == 0 &&
+ _dnsHeader->ARCount == 0;
+}
+
+String DNSServer::getDomainNameWithoutWwwPrefix()
+{
+ String parsedDomainName = "";
+ unsigned char *start = _buffer + 12;
+ if (*start == 0)
+ {
+ return parsedDomainName;
+ }
+ int pos = 0;
+ while(true)
+ {
+ unsigned char labelLength = *(start + pos);
+ for(int i = 0; i < labelLength; i++)
+ {
+ pos++;
+ parsedDomainName += (char)*(start + pos);
+ }
+ pos++;
+ if (*(start + pos) == 0)
+ {
+ downcaseAndRemoveWwwPrefix(parsedDomainName);
+ return parsedDomainName;
+ }
+ else
+ {
+ parsedDomainName += ".";
+ }
+ }
+}
+
+void DNSServer::replyWithIP()
+{
+ _dnsHeader->QR = DNS_QR_RESPONSE;
+ _dnsHeader->ANCount = _dnsHeader->QDCount;
+ _dnsHeader->QDCount = 0;
+
+ _udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
+ _udp.write(_buffer, _currentPacketSize);
+ _udp.write((unsigned char*)&_ttl, 4);
+ // Length of RData is 4 bytes (because, in this case, RData is IPv4)
+ _udp.write((uint8_t)0);
+ _udp.write((uint8_t)4);
+ _udp.write(_resolvedIP, sizeof(_resolvedIP));
+ _udp.endPacket();
+}
+
+void DNSServer::replyWithCustomCode()
+{
+ _dnsHeader->QR = DNS_QR_RESPONSE;
+ _dnsHeader->RCode = (unsigned char)_errorReplyCode;
+ _dnsHeader->QDCount = 0;
+
+ _udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
+ _udp.write(_buffer, sizeof(DNSHeader));
+ _udp.endPacket();
+}
diff --git a/hardware/esp8266com/esp8266/libraries/DNSServer/src/DNSServer.h b/hardware/esp8266com/esp8266/libraries/DNSServer/src/DNSServer.h
new file mode 100644
index 0000000000..d58efbbdd3
--- /dev/null
+++ b/hardware/esp8266com/esp8266/libraries/DNSServer/src/DNSServer.h
@@ -0,0 +1,71 @@
+#ifndef DNSServer_h
+#define DNSServer_h
+#include
+
+#define DNS_QR_QUERY 0
+#define DNS_QR_RESPONSE 1
+#define DNS_OPCODE_QUERY 0
+
+enum class DNSReplyCode
+{
+ NoError = 0,
+ FormError = 1,
+ ServerFailure = 2,
+ NonExistentDomain = 3,
+ NotImplemented = 4,
+ Refused = 5,
+ YXDomain = 6,
+ YXRRSet = 7,
+ NXRRSet = 8
+};
+
+struct DNSHeader
+{
+ uint16_t ID; // identification number
+ unsigned char RD : 1; // recursion desired
+ unsigned char TC : 1; // truncated message
+ unsigned char AA : 1; // authoritive answer
+ unsigned char OPCode : 4; // message_type
+ unsigned char QR : 1; // query/response flag
+ unsigned char RCode : 4; // response code
+ unsigned char Z : 3; // its z! reserved
+ unsigned char RA : 1; // recursion available
+ uint16_t QDCount; // number of question entries
+ uint16_t ANCount; // number of answer entries
+ uint16_t NSCount; // number of authority entries
+ uint16_t ARCount; // number of resource entries
+};
+
+class DNSServer
+{
+ public:
+ DNSServer();
+ void processNextRequest();
+ void setErrorReplyCode(const DNSReplyCode &replyCode);
+ void setTTL(const uint32_t &ttl);
+
+ // Returns true if successful, false if there are no sockets available
+ bool start(const uint16_t &port,
+ const String &domainName,
+ const IPAddress &resolvedIP);
+ // stops the DNS server
+ void stop();
+
+ private:
+ WiFiUDP _udp;
+ uint16_t _port;
+ String _domainName;
+ unsigned char _resolvedIP[4];
+ int _currentPacketSize;
+ unsigned char* _buffer;
+ DNSHeader* _dnsHeader;
+ uint32_t _ttl;
+ DNSReplyCode _errorReplyCode;
+
+ void downcaseAndRemoveWwwPrefix(String &domainName);
+ String getDomainNameWithoutWwwPrefix();
+ bool requestIncludesOnlyOneQuestion();
+ void replyWithIP();
+ void replyWithCustomCode();
+};
+#endif
diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WebServer/examples/SDWebServer/SDWebServer.ino b/hardware/esp8266com/esp8266/libraries/ESP8266WebServer/examples/SDWebServer/SDWebServer.ino
index 4e63f68e51..88a2093a58 100644
--- a/hardware/esp8266com/esp8266/libraries/ESP8266WebServer/examples/SDWebServer/SDWebServer.ino
+++ b/hardware/esp8266com/esp8266/libraries/ESP8266WebServer/examples/SDWebServer/SDWebServer.ino
@@ -183,16 +183,15 @@ void printDirectory() {
server.setContentLength(CONTENT_LENGTH_UNKNOWN);
server.send(200, "text/json", "");
WiFiClient client = server.client();
-
+
+ server.sendContent("[");
for (int cnt = 0; true; ++cnt) {
File entry = dir.openNextFile();
if (!entry)
break;
String output;
- if (cnt == 0)
- output = '[';
- else
+ if (cnt > 0)
output = ',';
output += "{\"type\":\"";
diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WebServer/examples/SDWebServer/SdRoot/edit/index.htm b/hardware/esp8266com/esp8266/libraries/ESP8266WebServer/examples/SDWebServer/SdRoot/edit/index.htm
index f555770e16..5b8432a696 100644
--- a/hardware/esp8266com/esp8266/libraries/ESP8266WebServer/examples/SDWebServer/SdRoot/edit/index.htm
+++ b/hardware/esp8266com/esp8266/libraries/ESP8266WebServer/examples/SDWebServer/SdRoot/edit/index.htm
@@ -377,7 +377,7 @@
var leaf = document.createElement("li");
leaf.id = (((path == "/")?"":path)+"/"+name).toLowerCase();
var label = document.createElement("span");
- label.innerText = name.toLowerCase();
+ label.textContent = name.toLowerCase();
leaf.appendChild(label);
leaf.onclick = function(e){
if(isTextFile(leaf.id)){
@@ -403,7 +403,7 @@
leaf.appendChild(check);
var label = document.createElement("label");
label.for = check.id;
- label.innerText = name.toLowerCase();
+ label.textContent = name.toLowerCase();
leaf.appendChild(label);
check.onchange = function(e){
if(check.checked){
diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp b/hardware/esp8266com/esp8266/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp
index 5c94ee8181..df067f0c9d 100644
--- a/hardware/esp8266com/esp8266/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp
+++ b/hardware/esp8266com/esp8266/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp
@@ -140,11 +140,10 @@ void ESP8266WebServer::send(int code, const char* content_type, String content)
content_type = "text/html";
sendHeader("Content-Type", content_type, true);
- if (_contentLength != CONTENT_LENGTH_UNKNOWN) {
- size_t length = (_contentLength == CONTENT_LENGTH_NOT_SET) ?
- content.length() : _contentLength;
- String lengthStr(length);
- sendHeader("Content-Length", lengthStr.c_str());
+ if (_contentLength != CONTENT_LENGTH_UNKNOWN && _contentLength != CONTENT_LENGTH_NOT_SET) {
+ sendHeader("Content-Length", String(_contentLength).c_str());
+ } else if(content.length() > 0){
+ sendHeader("Content-Length", String(content.length()).c_str());
}
sendHeader("Connection", "close");
sendHeader("Access-Control-Allow-Origin", "*");
diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/examples/NTPClient/NTPClient.ino b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/examples/NTPClient/NTPClient.ino
index 4a9771b5fd..4176c511b2 100644
--- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/examples/NTPClient/NTPClient.ino
+++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/examples/NTPClient/NTPClient.ino
@@ -27,7 +27,11 @@ char pass[] = "********"; // your network password
unsigned int localPort = 2390; // local port to listen for UDP packets
-IPAddress timeServer(129, 6, 15, 28); // time.nist.gov NTP server
+/* Don't hardwire the IP address or we won't get the benefits of the pool.
+ * Lookup the IP address for the host name instead */
+//IPAddress timeServer(129, 6, 15, 28); // time.nist.gov NTP server
+IPAddress timeServerIP; // time.nist.gov NTP server address
+const char* ntpServerName = "time.nist.gov";
const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message
@@ -65,7 +69,10 @@ void setup()
void loop()
{
- sendNTPpacket(timeServer); // send an NTP packet to a time server
+ //get a random server from the pool
+ WiFi.hostByName(ntpServerName, timeServerIP);
+
+ sendNTPpacket(timeServerIP); // send an NTP packet to a time server
// wait to see if a reply is available
delay(1000);
diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/examples/WiFiAccessPoint/WiFiAccessPoint.ino b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/examples/WiFiAccessPoint/WiFiAccessPoint.ino
index 9bd390064c..1a1130747e 100644
--- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/examples/WiFiAccessPoint/WiFiAccessPoint.ino
+++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/examples/WiFiAccessPoint/WiFiAccessPoint.ino
@@ -55,9 +55,6 @@ void setup() {
/* You can remove the password parameter if you want the AP to be open. */
WiFi.softAP(ssid, password);
- while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
-
- Serial.println("done");
IPAddress myIP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(myIP);
diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp
index 5a3db61432..61cb74630b 100644
--- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp
+++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.cpp
@@ -33,6 +33,8 @@ extern "C" {
#include "lwip/dns.h"
}
+#include "WiFiClient.h"
+#include "WiFiUdp.h"
extern "C" void esp_schedule();
extern "C" void esp_yield();
@@ -40,11 +42,16 @@ extern "C" void esp_yield();
ESP8266WiFiClass::ESP8266WiFiClass()
: _useApMode(false)
, _useClientMode(false)
+, _useStaticIp(false)
{
+ wifi_set_event_handler_cb((wifi_event_handler_cb_t)&ESP8266WiFiClass::_eventCallback);
}
void ESP8266WiFiClass::mode(WiFiMode m)
{
+ if(wifi_get_opmode() == (uint8)m) {
+ return;
+ }
ETS_UART_INTR_DISABLE();
wifi_set_opmode(m);
ETS_UART_INTR_ENABLE();
@@ -100,7 +107,8 @@ int ESP8266WiFiClass::begin(const char* ssid, const char *passphrase, int32_t ch
wifi_set_channel(channel);
}
- wifi_station_dhcpc_start();
+ if(!_useStaticIp)
+ wifi_station_dhcpc_start();
return status();
}
@@ -112,6 +120,8 @@ uint8_t ESP8266WiFiClass::waitForConnectResult(){
return status();
}
+
+// You will have to set the DNS-Server manually later since this will not enable DHCP
void ESP8266WiFiClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet)
{
struct ip_info info;
@@ -121,6 +131,26 @@ void ESP8266WiFiClass::config(IPAddress local_ip, IPAddress gateway, IPAddress s
wifi_station_dhcpc_stop();
wifi_set_ip_info(STATION_IF, &info);
+
+ _useStaticIp = true;
+}
+
+void ESP8266WiFiClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns)
+{
+ struct ip_info info;
+ info.ip.addr = static_cast(local_ip);
+ info.gw.addr = static_cast(gateway);
+ info.netmask.addr = static_cast(subnet);
+
+ wifi_station_dhcpc_stop();
+ wifi_set_ip_info(STATION_IF, &info);
+
+ // Set DNS-Server
+ ip_addr_t d;
+ d.addr = static_cast(dns);
+ dns_setserver(0,&d);
+
+ _useStaticIp = true;
}
int ESP8266WiFiClass::disconnect()
@@ -203,12 +233,32 @@ uint8_t* ESP8266WiFiClass::macAddress(uint8_t* mac)
return mac;
}
+String ESP8266WiFiClass::macAddress(void)
+{
+ uint8_t mac[6];
+ char macStr[18] = {0};
+ wifi_get_macaddr(STATION_IF, mac);
+
+ sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+ return String(macStr);
+}
+
uint8_t* ESP8266WiFiClass::softAPmacAddress(uint8_t* mac)
{
wifi_get_macaddr(SOFTAP_IF, mac);
return mac;
}
+String ESP8266WiFiClass::softAPmacAddress(void)
+{
+ uint8_t mac[6];
+ char macStr[18] = {0};
+ wifi_get_macaddr(SOFTAP_IF, mac);
+
+ sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+ return String(macStr);
+}
+
IPAddress ESP8266WiFiClass::localIP()
{
struct ip_info ip;
@@ -251,6 +301,16 @@ uint8_t* ESP8266WiFiClass::BSSID(void)
return reinterpret_cast(conf.bssid);
}
+String ESP8266WiFiClass::BSSIDstr(void)
+{
+ static struct station_config conf;
+ char mac[18] = {0};
+ wifi_station_get_config(&conf);
+ sprintf(mac,"%02X:%02X:%02X:%02X:%02X:%02X", conf.bssid[0], conf.bssid[1], conf.bssid[2], conf.bssid[3], conf.bssid[4], conf.bssid[5]);
+ return String(mac);
+}
+
+
int32_t ESP8266WiFiClass::channel(void) {
return wifi_get_channel();
}
@@ -298,10 +358,14 @@ void ESP8266WiFiClass::_scanDone(void* result, int status)
int8_t ESP8266WiFiClass::scanNetworks()
{
- if ((wifi_get_opmode() & 1) == 0)//1 and 3 have STA enabled
- {
+ if(_useApMode) {
+ // turn on AP+STA mode
mode(WIFI_AP_STA);
+ } else {
+ // turn on STA mode
+ mode(WIFI_STA);
}
+
int status = wifi_station_get_connect_status();
if (status != STATION_GOT_IP && status != STATION_IDLE)
{
@@ -353,6 +417,17 @@ uint8_t * ESP8266WiFiClass::BSSID(uint8_t i)
return it->bssid;
}
+String ESP8266WiFiClass::BSSIDstr(uint8_t i)
+{
+ char mac[18] = {0};
+ struct bss_info* it = reinterpret_cast(_getScanInfoByIndex(i));
+ if (!it)
+ return String("");
+
+ sprintf(mac,"%02X:%02X:%02X:%02X:%02X:%02X", it->bssid[0], it->bssid[1], it->bssid[2], it->bssid[3], it->bssid[4], it->bssid[5]);
+ return String(mac);
+}
+
int32_t ESP8266WiFiClass::channel(uint8_t i)
{
struct bss_info* it = reinterpret_cast(_getScanInfoByIndex(i));
@@ -462,9 +537,12 @@ void ESP8266WiFiClass::beginSmartConfig()
if (_smartConfigStarted)
return;
- if ((wifi_get_opmode() & 1) == 0)//1 and 3 have STA enabled
- {
+ if(_useApMode) {
+ // turn on AP+STA mode
mode(WIFI_AP_STA);
+ } else {
+ // turn on STA mode
+ mode(WIFI_STA);
}
_smartConfigStarted = true;
@@ -498,6 +576,17 @@ void ESP8266WiFiClass::_smartConfigDone(void* result)
wifi_station_connect();
}
+void ESP8266WiFiClass::_eventCallback(void* arg)
+{
+ System_Event_t* event = reinterpret_cast(arg);
+ DEBUGV("wifi evt: %d\r\n", event->event);
+
+ if (event->event == EVENT_STAMODE_DISCONNECTED) {
+ WiFiClient::stopAll();
+ WiFiUDP::stopAll();
+ }
+}
+
void ESP8266WiFiClass::printDiag(Print& p)
{
diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h
index 1a3a7b3668..7234399054 100644
--- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h
+++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h
@@ -75,7 +75,6 @@ class ESP8266WiFiClass
*/
void softAP(const char* ssid, const char* passphrase, int channel = 1);
-
/* Change Ip configuration settings disabling the dhcp client
*
* param local_ip: Static ip configuration
@@ -84,6 +83,15 @@ class ESP8266WiFiClass
*/
void config(IPAddress local_ip, IPAddress gateway, IPAddress subnet);
+ /* Change Ip configuration settings disabling the dhcp client
+ *
+ * param local_ip: Static ip configuration
+ * param gateway: Static gateway configuration
+ * param subnet: Static Subnet mask
+ * param dns: Defined DNS
+ */
+ void config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns);
+
/* Configure access point
*
* param local_ip: access point IP
@@ -103,15 +111,19 @@ class ESP8266WiFiClass
* Get the station interface MAC address.
*
* return: pointer to uint8_t array with length WL_MAC_ADDR_LENGTH
+ * return: String
*/
uint8_t* macAddress(uint8_t* mac);
+ String macAddress(void);
/*
* Get the softAP interface MAC address.
*
* return: pointer to uint8_t array with length WL_MAC_ADDR_LENGTH
+ * return: String
*/
uint8_t* softAPmacAddress(uint8_t* mac);
+ String softAPmacAddress(void);
/*
* Get the station interface IP address.
@@ -151,10 +163,17 @@ class ESP8266WiFiClass
/*
* Return the current bssid / mac associated with the network if configured
*
- * return: bssid string
+ * return: bssid uint8_t *
*/
uint8_t * BSSID(void);
+ /*
+ * Return the current bssid / mac associated with the network if configured
+ *
+ * return: bssid string
+ */
+ String BSSIDstr(void);
+
/*
* Return the current channel associated with the network
*
@@ -209,10 +228,17 @@ class ESP8266WiFiClass
/**
* return MAC / BSSID of scanned wifi
* @param networkItem specify from which network item want to get the information
- * @return uint8_t * to MAC / BSSID of scanned wifi
+ * @return uint8_t * MAC / BSSID of scanned wifi
*/
uint8_t * BSSID(uint8_t networkItem);
+ /**
+ * return MAC / BSSID of scanned wifi
+ * @param networkItem specify from which network item want to get the information
+ * @return String MAC / BSSID of scanned wifi
+ */
+ String BSSIDstr(uint8_t networkItem);
+
/**
* return channel of scanned wifi
* @param networkItem specify from which network item want to get the information
@@ -288,11 +314,13 @@ class ESP8266WiFiClass
static void _scanDone(void* result, int status);
void * _getScanInfoByIndex(int i);
static void _smartConfigDone(void* result);
+ static void _eventCallback(void *event);
bool _smartConfigStarted = false;
bool _useApMode;
bool _useClientMode;
-
+ bool _useStaticIp;
+
static size_t _scanCount;
static void* _scanResult;
diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp
index e0a7ddeb22..47f201f4da 100644
--- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp
+++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/ESP8266WiFiMulti.cpp
@@ -47,6 +47,10 @@ wl_status_t ESP8266WiFiMulti::run(void) {
uint8 bestBSSID[6];
int32_t bestChannel;
+ DEBUG_WIFI_MULTI("[WIFI] delete old wifi config...\n");
+ WiFi.disconnect();
+
+ DEBUG_WIFI_MULTI("[WIFI] start scan\n");
// WiFi.scanNetworks will return the number of networks found
int8_t n = WiFi.scanNetworks();
@@ -68,7 +72,6 @@ wl_status_t ESP8266WiFiMulti::run(void) {
WiFi.getNetworkInfo(i, ssid_scan, sec_scan, rssi_scan, BSSID_scan, chan_scan, hidden_scan);
-
bool known = false;
for(uint32_t x = 0; x < APlist.size(); x++) {
WifiAPlist_t entry = APlist[x];
@@ -148,7 +151,17 @@ bool ESP8266WiFiMulti::APlistAdd(const char* ssid, const char *passphrase) {
WifiAPlist_t newAP;
- newAP.ssid = (char*) malloc(strlen(ssid));
+ if(!ssid || strlen(ssid) > 31) {
+ // fail SSID to long or missing!
+ return false;
+ }
+
+ if(passphrase && strlen(passphrase) > 63) {
+ // fail passphrase to long!
+ return false;
+ }
+
+ newAP.ssid = (char*) malloc((strlen(ssid) + 1));
if(!newAP.ssid) {
return false;
@@ -157,16 +170,14 @@ bool ESP8266WiFiMulti::APlistAdd(const char* ssid, const char *passphrase) {
strcpy(newAP.ssid, ssid);
if(passphrase && *passphrase != 0x00) {
- newAP.passphrase = (char*) malloc(strlen(passphrase));
- }
-
- if(!newAP.passphrase) {
- free(newAP.ssid);
- return false;
+ newAP.passphrase = (char*) malloc((strlen(passphrase) + 1));
+ if(!newAP.passphrase) {
+ free(newAP.ssid);
+ return false;
+ }
+ strcpy(newAP.passphrase, passphrase);
}
- strcpy(newAP.passphrase, passphrase);
-
APlist.push_back(newAP);
return true;
}
diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiClient.cpp b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiClient.cpp
index 534c7fa895..9117a41923 100644
--- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiClient.cpp
+++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiClient.cpp
@@ -34,36 +34,48 @@ extern "C"
#include "WiFiClient.h"
#include "WiFiServer.h"
#include "lwip/opt.h"
+#include "lwip/ip.h"
#include "lwip/tcp.h"
#include "lwip/inet.h"
+#include "lwip/netif.h"
#include "cbuf.h"
#include "include/ClientContext.h"
#include "c_types.h"
-ICACHE_FLASH_ATTR WiFiClient::WiFiClient()
+uint16_t WiFiClient::_localPort = 0;
+
+template<>
+WiFiClient* SList::_s_first = 0;
+
+
+WiFiClient::WiFiClient()
: _client(0)
{
+ WiFiClient::_add(this);
}
-ICACHE_FLASH_ATTR WiFiClient::WiFiClient(ClientContext* client) : _client(client)
+WiFiClient::WiFiClient(ClientContext* client) : _client(client)
{
_client->ref();
+ WiFiClient::_add(this);
}
-ICACHE_FLASH_ATTR WiFiClient::~WiFiClient()
+WiFiClient::~WiFiClient()
{
+ WiFiClient::_remove(this);
if (_client)
_client->unref();
}
-ICACHE_FLASH_ATTR WiFiClient::WiFiClient(const WiFiClient& other)
+WiFiClient::WiFiClient(const WiFiClient& other)
{
_client = other._client;
if (_client)
_client->ref();
+ WiFiClient::_add(this);
}
-WiFiClient& ICACHE_FLASH_ATTR WiFiClient::operator=(const WiFiClient& other)
+WiFiClient& WiFiClient::operator=(const WiFiClient& other)
{
if (_client)
_client->unref();
@@ -74,7 +86,7 @@ WiFiClient& ICACHE_FLASH_ATTR WiFiClient::operator=(const WiFiClient& other)
}
-int ICACHE_FLASH_ATTR WiFiClient::connect(const char* host, uint16_t port)
+int WiFiClient::connect(const char* host, uint16_t port)
{
IPAddress remote_addr;
if (WiFi.hostByName(host, remote_addr))
@@ -84,17 +96,31 @@ int ICACHE_FLASH_ATTR WiFiClient::connect(const char* host, uint16_t port)
return 0;
}
-int ICACHE_FLASH_ATTR WiFiClient::connect(IPAddress ip, uint16_t port)
+int WiFiClient::connect(IPAddress ip, uint16_t port)
{
+ ip_addr_t addr;
+ addr.addr = ip;
+
if (_client)
stop();
+ // if the default interface is down, tcp_connect exits early without
+ // ever calling tcp_err
+ // http://lists.gnu.org/archive/html/lwip-devel/2010-05/msg00001.html
+ netif* interface = ip_route(&addr);
+ if (!interface) {
+ DEBUGV("no route to host\r\n");
+ return 1;
+ }
+
tcp_pcb* pcb = tcp_new();
if (!pcb)
return 0;
- ip_addr_t addr;
- addr.addr = ip;
+ if (_localPort > 0) {
+ pcb->local_port = _localPort++;
+ }
+
tcp_arg(pcb, this);
tcp_err(pcb, &WiFiClient::_s_err);
tcp_connect(pcb, &addr, port, reinterpret_cast(&WiFiClient::_s_connected));
@@ -108,7 +134,7 @@ int ICACHE_FLASH_ATTR WiFiClient::connect(IPAddress ip, uint16_t port)
return 0;
}
-int8_t ICACHE_FLASH_ATTR WiFiClient::_connected(void* pcb, int8_t err)
+int8_t WiFiClient::_connected(void* pcb, int8_t err)
{
tcp_pcb* tpcb = reinterpret_cast(pcb);
_client = new ClientContext(tpcb, 0, 0);
@@ -117,31 +143,31 @@ int8_t ICACHE_FLASH_ATTR WiFiClient::_connected(void* pcb, int8_t err)
return ERR_OK;
}
-void ICACHE_FLASH_ATTR WiFiClient::_err(int8_t err)
+void WiFiClient::_err(int8_t err)
{
DEBUGV(":err %d\r\n", err);
esp_schedule();
}
-void ICACHE_FLASH_ATTR WiFiClient::setNoDelay(bool nodelay) {
+void WiFiClient::setNoDelay(bool nodelay) {
if (!_client)
return;
_client->setNoDelay(nodelay);
}
-bool ICACHE_FLASH_ATTR WiFiClient::getNoDelay() {
+bool WiFiClient::getNoDelay() {
if (!_client)
return false;
return _client->getNoDelay();
}
-size_t ICACHE_FLASH_ATTR WiFiClient::write(uint8_t b)
+size_t WiFiClient::write(uint8_t b)
{
return write(&b, 1);
}
-size_t ICACHE_FLASH_ATTR WiFiClient::write(const uint8_t *buf, size_t size)
+size_t WiFiClient::write(const uint8_t *buf, size_t size)
{
if (!_client || !size)
{
@@ -153,7 +179,7 @@ size_t ICACHE_FLASH_ATTR WiFiClient::write(const uint8_t *buf, size_t size)
extern "C" uint32_t esp_micros_at_task_start();
-int ICACHE_FLASH_ATTR WiFiClient::available()
+int WiFiClient::available()
{
static uint32_t lastPollTime = 0;
if (!_client)
@@ -168,7 +194,7 @@ int ICACHE_FLASH_ATTR WiFiClient::available()
return result;
}
-int ICACHE_FLASH_ATTR WiFiClient::read()
+int WiFiClient::read()
{
if (!available())
return -1;
@@ -177,12 +203,12 @@ int ICACHE_FLASH_ATTR WiFiClient::read()
}
-int ICACHE_FLASH_ATTR WiFiClient::read(uint8_t* buf, size_t size)
+int WiFiClient::read(uint8_t* buf, size_t size)
{
return (int) _client->read(reinterpret_cast(buf), size);
}
-int ICACHE_FLASH_ATTR WiFiClient::peek()
+int WiFiClient::peek()
{
if (!available())
return -1;
@@ -190,13 +216,13 @@ int ICACHE_FLASH_ATTR WiFiClient::peek()
return _client->peek();
}
-void ICACHE_FLASH_ATTR WiFiClient::flush()
+void WiFiClient::flush()
{
if (_client)
_client->flush();
}
-void ICACHE_FLASH_ATTR WiFiClient::stop()
+void WiFiClient::stop()
{
if (!_client)
return;
@@ -205,7 +231,7 @@ void ICACHE_FLASH_ATTR WiFiClient::stop()
_client = 0;
}
-uint8_t ICACHE_FLASH_ATTR WiFiClient::connected()
+uint8_t WiFiClient::connected()
{
if (!_client)
return 0;
@@ -213,14 +239,14 @@ uint8_t ICACHE_FLASH_ATTR WiFiClient::connected()
return _client->state() == ESTABLISHED || available();
}
-uint8_t ICACHE_FLASH_ATTR WiFiClient::status()
+uint8_t WiFiClient::status()
{
if (!_client)
return CLOSED;
return _client->state();
}
-ICACHE_FLASH_ATTR WiFiClient::operator bool()
+ WiFiClient::operator bool()
{
return _client != 0;
}
@@ -241,13 +267,24 @@ uint16_t WiFiClient::remotePort()
return _client->getRemotePort();
}
-int8_t ICACHE_FLASH_ATTR WiFiClient::_s_connected(void* arg, void* tpcb, int8_t err)
+int8_t WiFiClient::_s_connected(void* arg, void* tpcb, int8_t err)
{
return reinterpret_cast(arg)->_connected(tpcb, err);
}
-void ICACHE_FLASH_ATTR WiFiClient::_s_err(void* arg, int8_t err)
+void WiFiClient::_s_err(void* arg, int8_t err)
{
reinterpret_cast(arg)->_err(err);
}
+void WiFiClient::stopAll()
+{
+ for (WiFiClient* it = _s_first; it; it = it->_next) {
+ ClientContext* c = it->_client;
+ if (c) {
+ c->abort();
+ c->unref();
+ it->_client = 0;
+ }
+ }
+}
diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiClient.h b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiClient.h
index f4063cbbaf..161ca0be1c 100644
--- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiClient.h
+++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiClient.h
@@ -26,11 +26,12 @@
#include "Client.h"
#include "IPAddress.h"
#include
+#include "include/slist.h"
class ClientContext;
class WiFiServer;
-class WiFiClient : public Client {
+class WiFiClient : public Client, public SList {
protected:
WiFiClient(ClientContext* client);
@@ -61,6 +62,7 @@ class WiFiClient : public Client {
uint16_t remotePort();
bool getNoDelay();
void setNoDelay(bool nodelay);
+ static void setLocalPortStart(uint16_t port) { _localPort = port; }
template size_t write(T &src){
uint8_t obuf[1460];
@@ -88,6 +90,8 @@ class WiFiClient : public Client {
using Print::write;
+ static void stopAll();
+
private:
static int8_t _s_connected(void* arg, void* tpcb, int8_t err);
@@ -97,7 +101,7 @@ class WiFiClient : public Client {
void _err(int8_t err);
ClientContext* _client;
-
+ static uint16_t _localPort;
};
diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiUdp.cpp b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiUdp.cpp
index 7696d747b7..8e304abbb2 100644
--- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiUdp.cpp
+++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiUdp.cpp
@@ -40,14 +40,22 @@ extern "C"
#include "lwip/mem.h"
#include "include/UdpContext.h"
+
+template<>
+WiFiUDP* SList::_s_first = 0;
+
/* Constructor */
-WiFiUDP::WiFiUDP() : _ctx(0) {}
+WiFiUDP::WiFiUDP() : _ctx(0)
+{
+ WiFiUDP::_add(this);
+}
WiFiUDP::WiFiUDP(const WiFiUDP& other)
{
_ctx = other._ctx;
if (_ctx)
_ctx->ref();
+ WiFiUDP::_add(this);
}
WiFiUDP& WiFiUDP::operator=(const WiFiUDP& rhs)
@@ -60,6 +68,7 @@ WiFiUDP& WiFiUDP::operator=(const WiFiUDP& rhs)
WiFiUDP::~WiFiUDP()
{
+ WiFiUDP::_remove(this);
if (_ctx)
_ctx->unref();
}
@@ -258,3 +267,11 @@ uint16_t WiFiUDP::localPort()
return _ctx->getLocalPort();
}
+
+void WiFiUDP::stopAll()
+{
+ for (WiFiUDP* it = _s_first; it; it = it->_next) {
+ it->stop();
+ }
+}
+
diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiUdp.h b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiUdp.h
index f8d76cd057..16aa0a3be9 100644
--- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiUdp.h
+++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/WiFiUdp.h
@@ -23,12 +23,13 @@
#define WIFIUDP_H
#include
+#include
#define UDP_TX_PACKET_MAX_SIZE 8192
class UdpContext;
-class WiFiUDP : public UDP {
+class WiFiUDP : public UDP, public SList {
private:
UdpContext* _ctx;
@@ -103,6 +104,8 @@ class WiFiUDP : public UDP {
// Return the local port for outgoing packets
uint16_t localPort();
+ static void stopAll();
+
};
#endif //WIFIUDP_H
diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/ClientContext.h b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/ClientContext.h
index 79c68127f9..d1f728eefe 100644
--- a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/ClientContext.h
+++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/ClientContext.h
@@ -261,8 +261,17 @@ class ClientContext {
}
void _error(err_t err) {
- DEBUGV(":er %d\r\n", err);
- close();
+ DEBUGV(":er %d %d %d\r\n", err, _size_sent, _send_waiting);
+ if (err != ERR_ABRT) {
+ abort();
+ }
+ else {
+ tcp_arg(_pcb, NULL);
+ tcp_sent(_pcb, NULL);
+ tcp_recv(_pcb, NULL);
+ tcp_err(_pcb, NULL);
+ _pcb = NULL;
+ }
if(_size_sent && _send_waiting) {
esp_schedule();
}
diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/slist.h b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/slist.h
new file mode 100644
index 0000000000..4ce42de6cc
--- /dev/null
+++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFi/src/include/slist.h
@@ -0,0 +1,38 @@
+#ifndef SLIST_H
+#define SLIST_H
+
+template
+class SList {
+public:
+ SList() : _next(0) { }
+
+protected:
+
+ static void _add(T* self) {
+ T* tmp = _s_first;
+ _s_first = self;
+ self->_next = tmp;
+ }
+
+ static void _remove(T* self) {
+ if (_s_first == self) {
+ _s_first = self->_next;
+ self->_next = 0;
+ return;
+ }
+
+ for (T* prev = _s_first; prev->_next; _s_first = _s_first->_next) {
+ if (prev->_next == self) {
+ prev->_next = self->_next;
+ self->_next = 0;
+ return;
+ }
+ }
+ }
+
+ static T* _s_first;
+ T* _next;
+};
+
+
+#endif //SLIST_H
diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFiMesh/examples/HelloMesh/HelloMesh.ino b/hardware/esp8266com/esp8266/libraries/ESP8266WiFiMesh/examples/HelloMesh/HelloMesh.ino
new file mode 100644
index 0000000000..0423c20cfb
--- /dev/null
+++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFiMesh/examples/HelloMesh/HelloMesh.ino
@@ -0,0 +1,44 @@
+#include
+#include
+
+/* Create the mesh node object */
+ESP8266WiFiMesh mesh_node = ESP8266WiFiMesh(ESP.getChipId(), manageRequest);
+
+/**
+ * Callback for when other nodes send you data
+ *
+ * @request The string received from another node in the mesh
+ * @returns The string to send back to the other node
+ */
+String manageRequest(String request)
+{
+ /* Print out received message */
+ Serial.print("received: ");
+ Serial.println(request);
+
+ /* return a string to send back */
+ return String("Hello world response.");
+}
+
+void setup()
+{
+ Serial.begin(115200);
+ delay(10);
+
+ Serial.println();
+ Serial.println();
+ Serial.println("Setting up mesh node...");
+
+ /* Initialise the mesh node */
+ mesh_node.begin();
+}
+
+void loop()
+{
+ /* Accept any incoming connections */
+ mesh_node.acceptRequest();
+
+ /* Scan for other nodes and send them a message */
+ mesh_node.attemptScan("Hello world request.");
+ delay(1000);
+}
diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFiMesh/keywords.txt b/hardware/esp8266com/esp8266/libraries/ESP8266WiFiMesh/keywords.txt
new file mode 100644
index 0000000000..14657d805c
--- /dev/null
+++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFiMesh/keywords.txt
@@ -0,0 +1,23 @@
+#######################################
+# Syntax Coloring Map For ESP8266WiFiMesh
+#######################################
+
+#######################################
+# Library (KEYWORD3)
+#######################################
+
+ESP8266WiFiMesh KEYWORD3
+
+#######################################
+# Datatypes (KEYWORD1)
+#######################################
+
+ESP8266WiFiMesh KEYWORD1
+
+#######################################
+# Methods and Functions (KEYWORD2)
+#######################################
+
+begin KEYWORD2
+attemptScan KEYWORD2
+acceptRequest KEYWORD2
diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFiMesh/library.properties b/hardware/esp8266com/esp8266/libraries/ESP8266WiFiMesh/library.properties
new file mode 100644
index 0000000000..dc6ba9a4da
--- /dev/null
+++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFiMesh/library.properties
@@ -0,0 +1,9 @@
+name=ESP8266WiFiMesh
+version=1.0
+author=Julian Fell
+maintainer=
+sentence=Mesh network library
+paragraph=The library sets up a Mesh Node which acts as a router, creating a Mesh Network with other nodes.
+category=Communication
+url=
+architectures=esp8266
diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFiMesh/src/ESP8266WiFiMesh.cpp b/hardware/esp8266com/esp8266/libraries/ESP8266WiFiMesh/src/ESP8266WiFiMesh.cpp
new file mode 100644
index 0000000000..6d3e544d7c
--- /dev/null
+++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFiMesh/src/ESP8266WiFiMesh.cpp
@@ -0,0 +1,168 @@
+/*
+ ESP8266WiFiMesh.cpp - Mesh network node
+ Sets up a Mesh Node which acts as a router, creating a Mesh Network with other nodes. All information
+ is passed in both directions, but it is up to the user what the data sent is and how it is dealt with.
+
+ Copyright (c) 2015 Julian Fell. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include
+#include
+#include
+#include
+
+#include "ESP8266WiFiMesh.h"
+
+#define SSID_PREFIX "Mesh_Node"
+#define SERVER_IP_ADDR "192.168.4.1"
+#define SERVER_PORT 4011
+
+ESP8266WiFiMesh::ESP8266WiFiMesh(uint32_t chip_id, std::function handler)
+: _server(SERVER_PORT)
+{
+ _chip_id = chip_id;
+ _ssid = String( String( SSID_PREFIX ) + String( _chip_id ) );
+ _ssid_prefix = String( SSID_PREFIX );
+ _handler = handler;
+}
+
+void ESP8266WiFiMesh::begin()
+{
+ WiFi.mode(WIFI_AP_STA);
+ WiFi.softAP( _ssid.c_str() );
+ _server.begin();
+}
+
+/**
+ * Wait for a WiFiClient to connect
+ *
+ * @returns: True if the client is ready, false otherwise.
+ *
+ */
+bool ESP8266WiFiMesh::waitForClient(WiFiClient curr_client, int max_wait)
+{
+ int wait = max_wait;
+ while(curr_client.connected() && !curr_client.available() && wait--)
+ delay(3);
+
+ /* Return false if the client isn't ready to communicate */
+ if (WiFi.status() == WL_DISCONNECTED || !curr_client.connected())
+ return false;
+
+ return true;
+}
+
+/**
+ * Send the supplied message then read back the other node's response
+ * and pass that to the user-supplied handler.
+ *
+ * @target_ssid The name of the AP the other node has set up.
+ * @message The string to send to the node.
+ * @returns: True if the exchange was a succes, false otherwise.
+ *
+ */
+bool ESP8266WiFiMesh::exchangeInfo(String message, WiFiClient curr_client)
+{
+ curr_client.println( message.c_str() );
+
+ if (!waitForClient(curr_client, 1000))
+ return false;
+
+ String response = curr_client.readStringUntil('\r');
+ curr_client.readStringUntil('\n');
+
+ if (response.length() <= 2)
+ return false;
+
+ /* Pass data to user callback */
+ _handler(response);
+ return true;
+}
+
+/**
+ * Connect to the AP at ssid, send them a message then disconnect.
+ *
+ * @target_ssid The name of the AP the other node has set up.
+ * @message The string to send to the node.
+ *
+ */
+void ESP8266WiFiMesh::connectToNode(String target_ssid, String message)
+{
+ WiFiClient curr_client;
+ WiFi.begin( target_ssid.c_str() );
+
+ int wait = 1500;
+ while((WiFi.status() == WL_DISCONNECTED) && wait--)
+ delay(3);
+
+ /* If the connection timed out */
+ if (WiFi.status() != 3)
+ return;
+
+ /* Connect to the node's server */
+ if (!curr_client.connect(SERVER_IP_ADDR, SERVER_PORT))
+ return;
+
+ if (!exchangeInfo(message, curr_client))
+ return;
+
+ curr_client.stop();
+ WiFi.disconnect();
+}
+
+void ESP8266WiFiMesh::attemptScan(String message)
+{
+ /* Scan for APs */
+ int n = WiFi.scanNetworks();
+
+ for (int i = 0; i < n; ++i) {
+ String current_ssid = WiFi.SSID(i);
+ int index = current_ssid.indexOf( _ssid_prefix );
+ uint32_t target_chip_id = (current_ssid.substring(index + _ssid_prefix.length())).toInt();
+
+ /* Connect to any _suitable_ APs which contain _ssid_prefix */
+ if (index >= 0 && (target_chip_id < _chip_id)) {
+
+ WiFi.mode(WIFI_STA);
+ delay(100);
+ connectToNode(current_ssid, message);
+ WiFi.mode(WIFI_AP_STA);
+ delay(100);
+ }
+ }
+}
+
+void ESP8266WiFiMesh::acceptRequest()
+{
+ while (true) {
+ _client = _server.available();
+ if (!_client)
+ break;
+
+ if (!waitForClient(_client, 1500)) {
+ continue;
+ }
+
+ /* Read in request and pass it to the supplied handler */
+ String request = _client.readStringUntil('\r');
+ _client.readStringUntil('\n');
+
+ String response = _handler(request);
+
+ /* Send the response back to the client */
+ if (_client.connected())
+ _client.println(response);
+ }
+}
diff --git a/hardware/esp8266com/esp8266/libraries/ESP8266WiFiMesh/src/ESP8266WiFiMesh.h b/hardware/esp8266com/esp8266/libraries/ESP8266WiFiMesh/src/ESP8266WiFiMesh.h
new file mode 100644
index 0000000000..dd959731bb
--- /dev/null
+++ b/hardware/esp8266com/esp8266/libraries/ESP8266WiFiMesh/src/ESP8266WiFiMesh.h
@@ -0,0 +1,75 @@
+/*
+ ESP8266WiFiMesh.h - Mesh network node
+ Sets up a Mesh Node which acts as a router, creating a Mesh Network with other nodes. All information
+ is passed in both directions, but it is up to the user what the data sent is and how it is dealt with.
+
+ Copyright (c) 2015 Julian Fell. All rights reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef __WIFIMESH_H__
+#define __WIFIMESH_H__
+
+#include
+#include
+#include
+
+class ESP8266WiFiMesh {
+
+private:
+ String _ssid;
+ String _ssid_prefix;
+ uint32_t _chip_id;
+
+ std::function _handler;
+
+ WiFiServer _server;
+ WiFiClient _client;
+
+ void connectToNode(String target_ssid, String message);
+ bool exchangeInfo(String message, WiFiClient curr_client);
+ bool waitForClient(WiFiClient curr_client, int max_wait);
+
+public:
+
+ /**
+ * WiFiMesh Constructor method. Creates a WiFi Mesh Node, ready to be initialised.
+ *
+ * @chip_id A unique identifier number for the node.
+ * @handler The callback handler for dealing with received messages. Takes a string as an argument which
+ * is the string received from another node and returns the string to send back.
+ *
+ */
+ ESP8266WiFiMesh(uint32_t chip_id, std::function handler);
+
+ /**
+ * Initialises the node.
+ */
+ void begin();
+
+ /**
+ * Scan for other nodes, and exchange the chosen message with any that are found.
+ *
+ * @message The message to send to all other nodes.
+ *
+ */
+ void attemptScan(String message);
+
+ /**
+ * If any clients are connected, accept their requests and call the hander function for each one.
+ */
+ void acceptRequest();
+};
+
+#endif
diff --git a/hardware/esp8266com/esp8266/libraries/SPI/SPI.cpp b/hardware/esp8266com/esp8266/libraries/SPI/SPI.cpp
index 7d52528ef1..4e73021220 100644
--- a/hardware/esp8266com/esp8266/libraries/SPI/SPI.cpp
+++ b/hardware/esp8266com/esp8266/libraries/SPI/SPI.cpp
@@ -121,14 +121,14 @@ void SPIClass::setBitOrder(uint8_t bitOrder) {
* @return
*/
static uint32_t ClkRegToFreq(spiClk_t * reg) {
- return (SPI_MAX_SPEED / ((reg->regPre + 1) * (reg->regN + 1)));
+ return (ESP8266_CLOCK / ((reg->regPre + 1) * (reg->regN + 1)));
}
void SPIClass::setFrequency(uint32_t freq) {
static uint32_t lastSetFrequency = 0;
static uint32_t lastSetRegister = 0;
- if(freq >= SPI_MAX_SPEED) {
+ if(freq >= ESP8266_CLOCK) {
setClockDivider(0x80000000);
return;
}
@@ -164,7 +164,7 @@ void SPIClass::setFrequency(uint32_t freq) {
reg.regN = calN;
while(calPreVari++ <= 1) { // test different variants for Pre (we calculate in int so we miss the decimals, testing is the easyest and fastest way)
- calPre = (((SPI_MAX_SPEED / (reg.regN + 1)) / freq) - 1) + calPreVari;
+ calPre = (((ESP8266_CLOCK / (reg.regN + 1)) / freq) - 1) + calPreVari;
if(calPre > 0x1FFF) {
reg.regPre = 0x1FFF; // 8191
} else if(calPre <= 0) {
diff --git a/hardware/esp8266com/esp8266/libraries/SPI/SPI.h b/hardware/esp8266com/esp8266/libraries/SPI/SPI.h
index 68d2a3dc6c..141f30ef4b 100644
--- a/hardware/esp8266com/esp8266/libraries/SPI/SPI.h
+++ b/hardware/esp8266com/esp8266/libraries/SPI/SPI.h
@@ -28,7 +28,6 @@
// This defines are not representing the real Divider of the ESP8266
// the Defines match to an AVR Arduino on 16MHz for better compatibility
-#if F_CPU == 80000000L
#define SPI_CLOCK_DIV2 0x00101001 //8 MHz
#define SPI_CLOCK_DIV4 0x00241001 //4 MHz
#define SPI_CLOCK_DIV8 0x004c1001 //2 MHz
@@ -36,16 +35,6 @@
#define SPI_CLOCK_DIV32 0x013c1001 //500 KHz
#define SPI_CLOCK_DIV64 0x027c1001 //250 KHz
#define SPI_CLOCK_DIV128 0x04fc1001 //125 KHz
-#else
-#define SPI_CLOCK_DIV2 0x00241001 //8 MHz
-#define SPI_CLOCK_DIV4 0x004c1001 //4 MHz
-#define SPI_CLOCK_DIV8 0x009c1001 //2 MHz
-#define SPI_CLOCK_DIV16 0x013c1001 //1 MHz
-#define SPI_CLOCK_DIV32 0x027c1001 //500 KHz
-#define SPI_CLOCK_DIV64 0x04fc1001 //250 KHz
-#endif
-
-#define SPI_MAX_SPEED (80000000L)
const uint8_t SPI_MODE0 = 0x00; ///< CPOL: 0 CPHA: 0
const uint8_t SPI_MODE1 = 0x01; ///< CPOL: 0 CPHA: 1
diff --git a/hardware/esp8266com/esp8266/libraries/Servo/examples/Sweep/Sweep.ino b/hardware/esp8266com/esp8266/libraries/Servo/examples/Sweep/Sweep.ino
new file mode 100644
index 0000000000..fe4e343cef
--- /dev/null
+++ b/hardware/esp8266com/esp8266/libraries/Servo/examples/Sweep/Sweep.ino
@@ -0,0 +1,39 @@
+/* Sweep
+ by BARRAGAN
+ This example code is in the public domain.
+
+ modified 28 May 2015
+ by Michael C. Miller
+ modified 8 Nov 2013
+ by Scott Fitzgerald
+
+ http://arduino.cc/en/Tutorial/Sweep
+*/
+
+#include
+
+Servo myservo; // create servo object to control a servo
+ // twelve servo objects can be created on most boards
+
+
+void setup()
+{
+ myservo.attach(2); // attaches the servo on GIO2 to the servo object
+}
+
+void loop()
+{
+ int pos;
+
+ for(pos = 0; pos <= 180; pos += 1) // goes from 0 degrees to 180 degrees
+ { // in steps of 1 degree
+ myservo.write(pos); // tell servo to go to position in variable 'pos'
+ delay(15); // waits 15ms for the servo to reach the position
+ }
+ for(pos = 180; pos>=0; pos-=1) // goes from 180 degrees to 0 degrees
+ {
+ myservo.write(pos); // tell servo to go to position in variable 'pos'
+ delay(15); // waits 15ms for the servo to reach the position
+ }
+}
+
diff --git a/hardware/esp8266com/esp8266/libraries/Servo/keywords.txt b/hardware/esp8266com/esp8266/libraries/Servo/keywords.txt
new file mode 100644
index 0000000000..0a7ca1e3d8
--- /dev/null
+++ b/hardware/esp8266com/esp8266/libraries/Servo/keywords.txt
@@ -0,0 +1,24 @@
+#######################################
+# Syntax Coloring Map Servo
+#######################################
+
+#######################################
+# Datatypes (KEYWORD1)
+#######################################
+
+Servo KEYWORD1 Servo
+
+#######################################
+# Methods and Functions (KEYWORD2)
+#######################################
+attach KEYWORD2
+detach KEYWORD2
+write KEYWORD2
+read KEYWORD2
+attached KEYWORD2
+writeMicroseconds KEYWORD2
+readMicroseconds KEYWORD2
+
+#######################################
+# Constants (LITERAL1)
+#######################################
diff --git a/hardware/esp8266com/esp8266/libraries/Servo/library.properties b/hardware/esp8266com/esp8266/libraries/Servo/library.properties
new file mode 100644
index 0000000000..28b1eedf71
--- /dev/null
+++ b/hardware/esp8266com/esp8266/libraries/Servo/library.properties
@@ -0,0 +1,9 @@
+name=Servo
+version=1.0.2
+author=Michael C. Miller
+maintainer=GitHub/esp8266/arduino
+sentence=Allows Esp8266 boards to control a variety of servo motors.
+paragraph=This library can control a great number of servos.
It makes careful use of timers: the library can control 12 servos using only 1 timer.
+category=Device Control
+url=http://arduino.cc/en/Reference/Servo
+architectures=esp8266
diff --git a/hardware/esp8266com/esp8266/libraries/Servo/src/Servo.h b/hardware/esp8266com/esp8266/libraries/Servo/src/Servo.h
new file mode 100644
index 0000000000..10cfd32835
--- /dev/null
+++ b/hardware/esp8266com/esp8266/libraries/Servo/src/Servo.h
@@ -0,0 +1,93 @@
+/*
+ Servo.h - Interrupt driven Servo library for Esp8266 using timers
+ Copyright (c) 2015 Michael C. Miller. All right reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+// A servo is activated by creating an instance of the Servo class passing
+// the desired pin to the attach() method.
+// The servos are pulsed in the background using the value most recently
+// written using the write() method.
+//
+// This library uses time0 and timer1.
+// Note that timer0 may be repurposed when the first servo is attached.
+//
+// Timers are seized as needed in groups of 12 servos - 24 servos use two
+// timers, there are only two timers for the esp8266 so the support stops here
+// The sequence used to sieze timers is defined in timers.h
+//
+// The methods are:
+//
+// 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
+//
+// 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
+// read() - Gets the last written servo pulse width as an angle between 0 and 180.
+// readMicroseconds() - Gets the last written servo pulse width in microseconds. (was read_us() in first release)
+// attached() - Returns true if there is a servo attached.
+// detach() - Stops an attached servos from pulsing its i/o pin.
+
+
+#ifndef Servo_h
+#define Servo_h
+
+#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
+
+// NOTE: to maintain a strict refresh interval the user needs to not exceede 8 servos
+#define SERVOS_PER_TIMER 12 // the maximum number of servos controlled by one timer
+#define MAX_SERVOS (ServoTimerSequence_COUNT * SERVOS_PER_TIMER)
+
+#if defined(ESP8266)
+
+#include "esp8266/ServoTimers.h"
+
+#else
+
+#error "This library only supports esp8266 boards."
+
+#endif
+
+class Servo
+{
+public:
+ 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, int min, int max); // as above but also sets min and max values for writes.
+ 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
+ int read(); // returns current pulse width as an angle between 0 and 180 degrees
+ int readMicroseconds(); // returns current pulse width in microseconds for this servo (was read_us() in first release)
+ bool attached(); // return true if this servo is attached, otherwise false
+private:
+ uint8_t _servoIndex; // index into the channel data for this servo
+ uint16_t _minUs;
+ uint16_t _maxUs;
+};
+
+#endif
diff --git a/hardware/esp8266com/esp8266/libraries/Servo/src/esp8266/Servo.cpp b/hardware/esp8266com/esp8266/libraries/Servo/src/esp8266/Servo.cpp
new file mode 100644
index 0000000000..bbc7bb26ff
--- /dev/null
+++ b/hardware/esp8266com/esp8266/libraries/Servo/src/esp8266/Servo.cpp
@@ -0,0 +1,249 @@
+/*
+ Copyright (c) 2015 Michael C. Miller. All right reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#if defined(ESP8266)
+
+#include
+#include
+
+
+#define INVALID_SERVO 255 // flag indicating an invalid servo index
+
+const uint32_t c_CycleCompensation = 4; // compensation us to trim adjust for digitalWrite delays
+
+struct ServoInfo {
+ uint8_t pin : 6; // a pin number from 0 to 63
+ uint8_t isActive : 1; // true if this channel is enabled, pin not pulsed if false
+};
+
+struct ServoState {
+ ServoInfo info;
+ volatile uint16_t usPulse;
+};
+
+#if !defined (SERVO_EXCLUDE_TIMER0)
+ServoTimer0 s_servoTimer0;
+#endif
+
+#if !defined (SERVO_EXCLUDE_TIMER1)
+ServoTimer1 s_servoTimer1;
+#endif
+
+static ServoState s_servos[MAX_SERVOS]; // static array of servo structures
+
+static uint8_t s_servoCount = 0; // the total number of attached s_servos
+
+
+// inconvenience macros
+#define SERVO_INDEX_TO_TIMER(servoIndex) ((ServoTimerSequence)(servoIndex / SERVOS_PER_TIMER)) // returns the timer controlling this servo
+#define SERVO_INDEX(timerId, channel) ((timerId * SERVOS_PER_TIMER) + channel) // macro to access servo index by timer and channel
+
+//------------------------------------------------------------------------------
+// Interrupt handler template method that takes a class that implements
+// a standard set of methods for the timer abstraction
+//------------------------------------------------------------------------------
+template void Servo_Handler(T* timer)
+{
+ noInterrupts();
+
+ uint8_t servoIndex;
+
+ // clear interrupt
+ timer->ResetInterrupt();
+
+ if (timer->isEndOfCycle()) {
+ timer->StartCycle();
+ }
+ else {
+ servoIndex = SERVO_INDEX(timer->timerId(), timer->getCurrentChannel());
+ if (servoIndex < s_servoCount && s_servos[servoIndex].info.isActive) {
+ // pulse this channel low if activated
+ digitalWrite(s_servos[servoIndex].info.pin, LOW);
+ }
+ timer->nextChannel();
+ }
+
+ servoIndex = SERVO_INDEX(timer->timerId(), timer->getCurrentChannel());
+
+ if (servoIndex < s_servoCount && timer->getCurrentChannel() < SERVOS_PER_TIMER) {
+ timer->SetPulseCompare(timer->usToTicks(s_servos[servoIndex].usPulse) - c_CycleCompensation);
+
+ if (s_servos[servoIndex].info.isActive) { // check if activated
+ digitalWrite(s_servos[servoIndex].info.pin, HIGH); // its an active channel so pulse it high
+ }
+ }
+ else {
+ // finished all channels so wait for the refresh period to expire before starting over
+ // allow a few ticks to ensure the next match is not missed
+ uint32_t refreshCompare = timer->usToTicks(REFRESH_INTERVAL);
+ if ((timer->GetCycleCount() + c_CycleCompensation * 2) < refreshCompare) {
+ timer->SetCycleCompare(refreshCompare - c_CycleCompensation);
+ }
+ else {
+ // at least REFRESH_INTERVAL has elapsed
+ timer->SetCycleCompare(timer->GetCycleCount() + c_CycleCompensation * 2);
+ }
+
+ timer->setEndOfCycle();
+ }
+
+ interrupts();
+}
+
+static void initISR(ServoTimerSequence timerId)
+{
+#if !defined (SERVO_EXCLUDE_TIMER0)
+ if (timerId == ServoTimerSequence_Timer0)
+ s_servoTimer0.InitInterrupt([]() {Servo_Handler(&s_servoTimer0); });
+#endif
+#if !defined (SERVO_EXCLUDE_TIMER1)
+ if (timerId == ServoTimerSequence_Timer1)
+ s_servoTimer1.InitInterrupt([]() {Servo_Handler(&s_servoTimer1); });
+#endif
+}
+
+static void finISR(ServoTimerSequence timerId)
+{
+#if !defined (SERVO_EXCLUDE_TIMER0)
+ if (timerId == ServoTimerSequence_Timer0)
+ s_servoTimer0.StopInterrupt();
+#endif
+#if !defined (SERVO_EXCLUDE_TIMER1)
+ if (timerId == ServoTimerSequence_Timer1)
+ s_servoTimer1.StopInterrupt();
+#endif
+}
+
+// returns true if any servo is active on this timer
+static boolean isTimerActive(ServoTimerSequence timerId)
+{
+ for (uint8_t channel = 0; channel < SERVOS_PER_TIMER; channel++) {
+ if (s_servos[SERVO_INDEX(timerId, channel)].info.isActive) {
+ return true;
+ }
+ }
+ return false;
+}
+
+//-------------------------------------------------------------------
+// Servo class methods
+
+Servo::Servo()
+{
+ if (s_servoCount < MAX_SERVOS) {
+ // assign a servo index to this instance
+ _servoIndex = s_servoCount++;
+ // store default values
+ s_servos[_servoIndex].usPulse = DEFAULT_PULSE_WIDTH;
+ }
+ else {
+ _servoIndex = INVALID_SERVO; // too many servos
+ }
+}
+
+uint8_t Servo::attach(int pin)
+{
+ return attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
+}
+
+uint8_t Servo::attach(int pin, int minUs, int maxUs)
+{
+ ServoTimerSequence timerId;
+
+ Serial.print("_servoIndex ");
+ Serial.println(_servoIndex);
+
+ if (_servoIndex < MAX_SERVOS) {
+ pinMode(pin, OUTPUT); // set servo pin to output
+ digitalWrite(pin, LOW);
+ s_servos[_servoIndex].info.pin = pin;
+
+ // keep the min and max within 200-3000 us, these are extreme
+ // ranges and should support extreme servos while maintaining
+ // reasonable ranges
+ _maxUs = max(250, min(3000, maxUs));
+ _minUs = max(200, min(_maxUs, minUs));
+
+ // initialize the timerId if it has not already been initialized
+ timerId = SERVO_INDEX_TO_TIMER(_servoIndex);
+ if (!isTimerActive(timerId)) {
+ initISR(timerId);
+ }
+ s_servos[_servoIndex].info.isActive = true; // this must be set after the check for isTimerActive
+ }
+ return _servoIndex;
+}
+
+void Servo::detach()
+{
+ ServoTimerSequence timerId;
+
+ s_servos[_servoIndex].info.isActive = false;
+ timerId = SERVO_INDEX_TO_TIMER(_servoIndex);
+ if (!isTimerActive(timerId)) {
+ finISR(timerId);
+ }
+}
+
+void Servo::write(int value)
+{
+ // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
+ if (value < MIN_PULSE_WIDTH) {
+ // assumed to be 0-180 degrees servo
+ value = max(0, min(180, value));
+ value = map(value, 0, 180, _minUs, _maxUs);
+ }
+ writeMicroseconds(value);
+}
+
+void Servo::writeMicroseconds(int value)
+{
+ // ensure channel is valid
+ if ((_servoIndex < MAX_SERVOS)) {
+ // ensure pulse width is valid
+ value = max(_minUs, min(_maxUs, value));
+
+ s_servos[_servoIndex].usPulse = value;
+ }
+}
+
+int Servo::read() // return the value as degrees
+{
+ return map(readMicroseconds(), _minUs, _maxUs, 0, 180);
+}
+
+int Servo::readMicroseconds()
+{
+ unsigned int pulsewidth;
+ if (_servoIndex != INVALID_SERVO) {
+ pulsewidth = s_servos[_servoIndex].usPulse;
+ }
+ else {
+ pulsewidth = 0;
+ }
+
+ return pulsewidth;
+}
+
+bool Servo::attached()
+{
+ return s_servos[_servoIndex].info.isActive;
+}
+
+#endif
+
diff --git a/hardware/esp8266com/esp8266/libraries/Servo/src/esp8266/ServoTimers.h b/hardware/esp8266com/esp8266/libraries/Servo/src/esp8266/ServoTimers.h
new file mode 100644
index 0000000000..56ee18671b
--- /dev/null
+++ b/hardware/esp8266com/esp8266/libraries/Servo/src/esp8266/ServoTimers.h
@@ -0,0 +1,227 @@
+/*
+ Copyright (c) 2015 Michael C. Miller. All right reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+//
+// Defines for timer abstractions used with Servo library
+//
+// ServoTimerSequence enumerates the sequence that the timers should be allocated
+// ServoTimerSequence_COUNT indicates how many timers are available.
+//
+enum ServoTimerSequence {
+
+#if !defined (SERVO_EXCLUDE_TIMER0)
+ ServoTimerSequence_Timer0,
+#endif
+
+#if !defined (SERVO_EXCLUDE_TIMER1)
+ ServoTimerSequence_Timer1,
+#endif
+
+ ServoTimerSequence_COUNT
+};
+
+
+#if !defined (SERVO_EXCLUDE_TIMER0)
+
+struct ServoTimer0
+{
+public:
+ ServoTimer0()
+ {
+ setEndOfCycle();
+ }
+
+
+ uint32_t usToTicks(uint32_t us) const
+ {
+ return (clockCyclesPerMicrosecond() * us); // converts microseconds to tick
+ }
+ uint32_t ticksToUs(uint32_t ticks) const
+ {
+ return (ticks / clockCyclesPerMicrosecond()); // converts from ticks back to microseconds
+ }
+
+ void InitInterrupt(timercallback handler)
+ {
+ timer0_isr_init();
+ timer0_attachInterrupt(handler);
+ }
+
+ void ResetInterrupt() {}; // timer0 doesn't have a clear interrupt
+
+ void StopInterrupt()
+ {
+ timer0_detachInterrupt();
+ }
+
+ void SetPulseCompare(uint32_t value)
+ {
+ timer0_write(ESP.getCycleCount() + value);
+ }
+
+ void SetCycleCompare(uint32_t value)
+ {
+ timer0_write(_cycleStart + value);
+ }
+
+ uint32_t GetCycleCount() const
+ {
+ return ESP.getCycleCount() - _cycleStart;
+ }
+
+
+ void StartCycle()
+ {
+ _cycleStart = ESP.getCycleCount();
+ _currentChannel = 0;
+ }
+
+ int8_t getCurrentChannel() const
+ {
+ return _currentChannel;
+ }
+
+ void nextChannel()
+ {
+ _currentChannel++;
+ }
+
+ void setEndOfCycle()
+ {
+ _currentChannel = -1;
+ }
+
+ bool isEndOfCycle() const
+ {
+ return (_currentChannel == -1);
+ }
+
+ ServoTimerSequence timerId() const
+ {
+ return ServoTimerSequence_Timer0;
+ }
+
+private:
+ volatile uint32_t _cycleStart;
+ volatile int8_t _currentChannel;
+};
+
+#endif
+
+
+#if !defined (SERVO_EXCLUDE_TIMER1)
+
+struct ServoTimer1
+{
+public:
+ ServoTimer1()
+ {
+ setEndOfCycle();
+ }
+
+
+ uint32_t usToTicks(uint32_t us) const
+ {
+ return (clockCyclesPerMicrosecond() / 16 * us); // converts microseconds to tick
+ }
+ uint32_t ticksToUs(uint32_t ticks) const
+ {
+ return (ticks / clockCyclesPerMicrosecond() * 16); // converts from ticks back to microseconds
+ }
+
+ void InitInterrupt(timercallback handler)
+ {
+ timer1_isr_init();
+ timer1_attachInterrupt(handler);
+ timer1_enable(TIM_DIV16, TIM_EDGE, TIM_SINGLE);
+ timer1_write(usToTicks(REFRESH_INTERVAL));
+ }
+
+ void ResetInterrupt() {}; // timer1 doesn't have a clear interrupt
+
+ void StopInterrupt()
+ {
+ timer1_detachInterrupt();
+ }
+
+ void SetPulseCompare(uint32_t value)
+ {
+ _cycleTicks += value;
+ timer1_write(value);
+ }
+
+ void SetCycleCompare(uint32_t value)
+ {
+ if (value <= _cycleTicks)
+ {
+ value = 1;
+ }
+ else
+ {
+ value -= _cycleTicks;
+ }
+ timer1_write(value);
+ }
+
+ uint32_t GetCycleCount() const
+ {
+ return _cycleTicks;
+ }
+
+
+ void StartCycle()
+ {
+ _cycleTicks = 0;
+ _currentChannel = 0;
+ }
+
+ int8_t getCurrentChannel() const
+ {
+ return _currentChannel;
+ }
+
+ void nextChannel()
+ {
+ _currentChannel++;
+ }
+
+ void setEndOfCycle()
+ {
+ _currentChannel = -1;
+ }
+
+ bool isEndOfCycle() const
+ {
+ return (_currentChannel == -1);
+ }
+
+ ServoTimerSequence timerId() const
+ {
+ return ServoTimerSequence_Timer1;
+ }
+
+private:
+ volatile uint32_t _cycleTicks;
+ volatile int8_t _currentChannel;
+};
+
+#endif
+
+
+
+
diff --git a/hardware/esp8266com/esp8266/libraries/TFT_Touch_Shield_V2/TFTv2.cpp b/hardware/esp8266com/esp8266/libraries/TFT_Touch_Shield_V2/TFTv2.cpp
index a8ba79f832..48f1c910c8 100644
--- a/hardware/esp8266com/esp8266/libraries/TFT_Touch_Shield_V2/TFTv2.cpp
+++ b/hardware/esp8266com/esp8266/libraries/TFT_Touch_Shield_V2/TFTv2.cpp
@@ -30,7 +30,7 @@ void TFT::TFTinit (void)
pinMode(4, OUTPUT);
pinMode(15, OUTPUT);
SPI.begin();
- SPI.setClockDivider(2);
+ SPI.setClockDivider(SPI_CLOCK_DIV2);
TFT_CS_HIGH;
TFT_DC_HIGH;
@@ -570,4 +570,4 @@ INT8U TFT::drawFloat(float floatNumber,INT16U poX, INT16U poY,INT16U size,INT16U
TFT Tft=TFT();
/*********************************************************************************************************
END FILE
-*********************************************************************************************************/
\ No newline at end of file
+*********************************************************************************************************/
diff --git a/hardware/esp8266com/esp8266/libraries/esp8266/examples/Blink/Blink.ino b/hardware/esp8266com/esp8266/libraries/esp8266/examples/Blink/Blink.ino
new file mode 100644
index 0000000000..578f368864
--- /dev/null
+++ b/hardware/esp8266com/esp8266/libraries/esp8266/examples/Blink/Blink.ino
@@ -0,0 +1,24 @@
+/*
+ ESP8266 Blink by Simon Peter
+ Blink the blue LED on the ESP-01 module
+ This example code is in the public domain
+
+ The blue LED on the ESP-01 module is connected to GPIO1
+ (which is also the TXD pin; so we cannot use Serial.print() at the same time)
+
+ Note that this sketch uses BUILTIN_LED to find the pin with the internal LED
+*/
+
+void setup() {
+ pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output
+}
+
+// the loop function runs over and over again forever
+void loop() {
+ digitalWrite(BUILTIN_LED, LOW); // Turn the LED on (Note that LOW is the voltage level
+ // but actually the LED is on; this is because
+ // it is acive low on the ESP-01)
+ delay(1000); // Wait for a second
+ digitalWrite(BUILTIN_LED, HIGH); // Turn the LED off by making the voltage HIGH
+ delay(2000); // Wait for two seconds (to demonstrate the active low LED)
+}
diff --git a/hardware/esp8266com/esp8266/libraries/esp8266/examples/BlinkWithoutDelay/BlinkWithoutDelay.ino b/hardware/esp8266com/esp8266/libraries/esp8266/examples/BlinkWithoutDelay/BlinkWithoutDelay.ino
new file mode 100644
index 0000000000..740211d6d1
--- /dev/null
+++ b/hardware/esp8266com/esp8266/libraries/esp8266/examples/BlinkWithoutDelay/BlinkWithoutDelay.ino
@@ -0,0 +1,33 @@
+/*
+ ESP8266 BlinkWithoutDelay by Simon Peter
+ Blink the blue LED on the ESP-01 module
+ Based on the Arduino Blink without Delay example
+ This example code is in the public domain
+
+ The blue LED on the ESP-01 module is connected to GPIO1
+ (which is also the TXD pin; so we cannot use Serial.print() at the same time)
+
+ Note that this sketch uses BUILTIN_LED to find the pin with the internal LED
+*/
+
+int ledState = LOW;
+
+unsigned long previousMillis = 0;
+const long interval = 1000;
+
+void setup() {
+ pinMode(BUILTIN_LED, OUTPUT);
+}
+
+void loop()
+{
+ unsigned long currentMillis = millis();
+ if(currentMillis - previousMillis >= interval) {
+ previousMillis = currentMillis;
+ if (ledState == LOW)
+ ledState = HIGH; // Note that this switches the LED *off*
+ else
+ ledState = LOW; // Note that this switches the LED *on*
+ digitalWrite(BUILTIN_LED, ledState);
+ }
+}
diff --git a/hardware/esp8266com/esp8266/platform.txt b/hardware/esp8266com/esp8266/platform.txt
index c2cfa053e5..2695115c28 100644
--- a/hardware/esp8266com/esp8266/platform.txt
+++ b/hardware/esp8266com/esp8266/platform.txt
@@ -74,12 +74,12 @@ recipe.objcopy.eep.pattern=
## Create hex
#recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex"
-recipe.objcopy.hex.pattern="{runtime.tools.esptool.path}/{compiler.esptool.cmd}" -eo "{build.path}/{build.project_name}.elf" -bo "{build.path}/{build.project_name}_00000.bin" -bm {build.flash_mode} -bf {build.flash_freq} -bz {build.flash_size} -bs .text -bs .data -bs .rodata -bc -ec -eo "{build.path}/{build.project_name}.elf" -es .irom0.text "{build.path}/{build.project_name}_10000.bin" -ec
+recipe.objcopy.hex.pattern="{runtime.tools.esptool.path}/{compiler.esptool.cmd}" -eo "{runtime.platform.path}/bootloaders/eboot/eboot.elf" -bo "{build.path}/{build.project_name}.bin" -bm {build.flash_mode} -bf {build.flash_freq} -bz {build.flash_size} -bs .text -bp 4096 -ec -eo "{build.path}/{build.project_name}.elf" -bs .irom0.text -bs .text -bs .data -bs .rodata -bc -ec
## Compute size
recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf"
-recipe.size.regex=^(?:\.text|\.data|\.rodata|\.irom0\.text|)\s+([0-9]+).*
-#recipe.size.regex.data=^(?:\.data|\.bss|\.noinit)\s+([0-9]+).*
+recipe.size.regex=^(?:\.irom0\.text|\.text|\.data|\.rodata|)\s+([0-9]+).*
+recipe.size.regex.data=^(?:\.data|\.rodata|\.bss)\s+([0-9]+).*
#recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).*
# ------------------------------
@@ -91,4 +91,4 @@ tools.esptool.path={runtime.platform.path}/tools
tools.esptool.upload.protocol=esp
tools.esptool.upload.params.verbose=-vv
tools.esptool.upload.params.quiet=
-tools.esptool.upload.pattern="{path}/{cmd}" {upload.verbose} -cd {upload.resetmethod} -cb {upload.speed} -cp "{serial.port}" -ca 0x00000 -cf "{build.path}/{build.project_name}_00000.bin" -ca 0x10000 -cf "{build.path}/{build.project_name}_10000.bin"
+tools.esptool.upload.pattern="{path}/{cmd}" {upload.verbose} -cd {upload.resetmethod} -cb {upload.speed} -cp "{serial.port}" -ca 0x00000 -cf "{build.path}/{build.project_name}.bin"
diff --git a/hardware/esp8266com/esp8266/tools/sdk/include/ets_sys.h b/hardware/esp8266com/esp8266/tools/sdk/include/ets_sys.h
index 7908699bb5..2aaa3321a2 100644
--- a/hardware/esp8266com/esp8266/tools/sdk/include/ets_sys.h
+++ b/hardware/esp8266com/esp8266/tools/sdk/include/ets_sys.h
@@ -39,10 +39,14 @@ typedef struct _ETSTIMER_ {
typedef void (*int_handler_t)(void*);
-#define ETS_SPI_INUM 2
+#define ETS_SLC_INUM 1
+#define ETS_SPI_INUM 2
#define ETS_GPIO_INUM 4
#define ETS_UART_INUM 5
#define ETS_UART1_INUM 5
+#define ETS_CCOMPARE0_INUM 6
+#define ETS_SOFT_INUM 7
+#define ETS_WDT_INUM 8
#define ETS_FRC_TIMER1_INUM 9 /* use edge*/
#define ETS_INTR_LOCK() \
@@ -51,26 +55,61 @@ typedef void (*int_handler_t)(void*);
#define ETS_INTR_UNLOCK() \
ets_intr_unlock()
+#define ETS_INTR_ENABLE(inum) \
+ ets_isr_unmask((1< 0)?NOT_A_PIN:0)
+#define digitalPinToInterrupt(p) (((p) < EXTERNAL_NUM_INTERRUPTS)?p:NOT_A_PIN)
+#define digitalPinHasPWM(p) (((p) < NUM_DIGITAL_PINS)?p:NOT_A_PIN)
+
+static const uint8_t SDA = 4;
+static const uint8_t SCL = 5;
+
+static const uint8_t SS = 15;
+static const uint8_t MOSI = 13;
+static const uint8_t MISO = 12;
+static const uint8_t SCK = 14;
+
+static const uint8_t BUILTIN_LED = 0;
+
+static const uint8_t A0 = 17;
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX
+// pins are NOT connected to anything by default.
+#define SERIAL_PORT_MONITOR Serial
+#define SERIAL_PORT_USBVIRTUAL Serial
+#define SERIAL_PORT_HARDWARE Serial
+#define SERIAL_PORT_HARDWARE_OPEN Serial
+
+#endif /* Pins_Arduino_h */
+
diff --git a/libraries/Adafruit_ILI9341/Adafruit_ILI9341.cpp b/libraries/Adafruit_ILI9341/Adafruit_ILI9341.cpp
index 05d376aed9..2af27e83e6 100644
--- a/libraries/Adafruit_ILI9341/Adafruit_ILI9341.cpp
+++ b/libraries/Adafruit_ILI9341/Adafruit_ILI9341.cpp
@@ -264,7 +264,7 @@ uint16_t Adafruit_ILI9341::getWidth(void){
#ifdef SPI_HAS_TRANSACTION
#ifdef ESP8266
-SPISettings spiSettings = SPISettings(SPI_MAX_SPEED, MSBFIRST, SPI_MODE0);
+SPISettings spiSettings = SPISettings(ESP8266_CLOCK, MSBFIRST, SPI_MODE0);
#else
SPISettings spiSettings = SPISettings(8000000, MSBFIRST, SPI_MODE0);
#endif