UIPEthernet library for Arduino IDE, Eclipse with arduino plugin and MBED/SMeshStudio (AVR,STM32F,ESP8266,Intel ARC32,Nordic nRF51,Teensy boards,Realtek Ameba(RTL8195A,RTL8710)), ENC28j60 network chip. Compatible with Wiznet W5100 Ethernet library API. Compiled and tested on Nucleo-F302R8. Master repository is: https://github.com/UIPEthernet/UIPEthernet/

Files at this revision

API Documentation at this revision

Comitter:
cassyarduino
Date:
Mon Mar 27 22:31:01 2017 +0200
Parent:
37:a848e40373ac
Child:
39:deeb00b81cc9
Commit message:
Release: 2.0.4

Changed in this revision

Dhcp.cpp Show annotated file Show diff for this revision Revisions of this file
Dhcp.h Show annotated file Show diff for this revision Revisions of this file
README.md Show annotated file Show diff for this revision Revisions of this file
library.json Show annotated file Show diff for this revision Revisions of this file
library.properties Show annotated file Show diff for this revision Revisions of this file
utility/Enc28J60Network.h Show annotated file Show diff for this revision Revisions of this file
--- a/Dhcp.cpp	Wed Feb 22 13:40:36 2017 +0000
+++ b/Dhcp.cpp	Mon Mar 27 22:31:01 2017 +0200
@@ -17,17 +17,15 @@
 #include "utility/logging.h"
 #include "utility/uip.h"
 
-int DhcpClass::beginWithDHCP(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout)
+int DhcpClass::beginWithDHCP(uint8_t *mac)
 {
     #if ACTLOGLEVEL>=LOG_DEBUG_V1
-      LogObject.uart_send_str(F("DhcpClass::beginWithDHCP(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout) DEBUG_V1:Function started"));
+      LogObject.uart_send_strln(F("DhcpClass::beginWithDHCP(uint8_t *mac) DEBUG_V1:Function started"));
     #endif
     _dhcpLeaseTime=0;
     _dhcpT1=0;
     _dhcpT2=0;
     _lastCheck=0;
-    _timeout = timeout;
-    _responseTimeout = responseTimeout;
 
     // zero out _dhcpMacAddr
     memset(_dhcpMacAddr, 0, 6); 
@@ -40,16 +38,16 @@
 
 void DhcpClass::reset_DHCP_lease(void){
     #if ACTLOGLEVEL>=LOG_DEBUG_V1
-      LogObject.uart_send_str(F("DhcpClass::reset_DHCP_lease(void) DEBUG_V1:Function started"));
+      LogObject.uart_send_strln(F("DhcpClass::reset_DHCP_lease(void) DEBUG_V1:Function started"));
     #endif
-    // zero out _dhcpSubnetMask, _dhcpGatewayIp, _dhcpLocalIp, _dhcpDhcpServerIp, _dhcpDnsServerIp
-    memset(_dhcpLocalIp, 0, 20);
+    // zero out _dhcpipv4struct.SubnetMask, _dhcpipv4struct.GatewayIp, _dhcpipv4struct.LocalIp, _dhcpipv4struct.DhcpServerIp, _dhcpipv4struct.DnsServerIp
+    memset(&_dhcpipv4struct, 0, sizeof(_dhcpipv4struct));
 }
 
 //return:0 on error, 1 if request is sent and response is received
 int DhcpClass::request_DHCP_lease(void){
     #if ACTLOGLEVEL>=LOG_DEBUG_V1
-      LogObject.uart_send_str(F("DhcpClass::request_DHCP_lease(void) DEBUG_V1:Function started"));
+      LogObject.uart_send_strln(F("DhcpClass::request_DHCP_lease(void) DEBUG_V1:Function started"));
     #endif
     
     uint8_t messageType = 0;
@@ -83,7 +81,7 @@
         if(_dhcp_state == STATE_DHCP_START)
         {
             #if ACTLOGLEVEL>=LOG_DEBUG_V1
-              LogObject.uart_send_str(F("DhcpClass::request_DHCP_lease(void) DEBUG_V1:dhcp_state=STATE_DHCP_START -> send_DHCP_MESSAGE DHCP_DISCOVER"));
+              LogObject.uart_send_strln(F("DhcpClass::request_DHCP_lease(void) DEBUG_V1:dhcp_state=STATE_DHCP_START -> send_DHCP_MESSAGE DHCP_DISCOVER"));
             #endif
             _dhcpTransactionId++;
             
@@ -92,7 +90,7 @@
         }
         else if(_dhcp_state == STATE_DHCP_REREQUEST){
             #if ACTLOGLEVEL>=LOG_DEBUG_V1
-              LogObject.uart_send_str(F("DhcpClass::request_DHCP_lease(void) DEBUG_V1:dhcp_state=STATE_DHCP_REREQUEST -> send_DHCP_MESSAGE DHCP_REQUEST"));
+              LogObject.uart_send_strln(F("DhcpClass::request_DHCP_lease(void) DEBUG_V1:dhcp_state=STATE_DHCP_REREQUEST -> send_DHCP_MESSAGE DHCP_REQUEST"));
             #endif
             _dhcpTransactionId++;
             send_DHCP_MESSAGE(DHCP_REQUEST, ((millis() - startTime)/1000));
@@ -101,11 +99,11 @@
         else if(_dhcp_state == STATE_DHCP_DISCOVER)
         {
             uint32_t respId;
-            messageType = parseDHCPResponse(_responseTimeout, respId);
+            messageType = parseDHCPResponse(respId);
             if(messageType == DHCP_OFFER)
             {
                 #if ACTLOGLEVEL>=LOG_DEBUG_V1
-                  LogObject.uart_send_str(F("DhcpClass::request_DHCP_lease(void) DEBUG_V1:dhcp_state=STATE_DHCP_DISCOVER,messageType=DHCP_OFFER -> send_DHCP_MESSAGE DHCP_REQUEST"));
+                  LogObject.uart_send_strln(F("DhcpClass::request_DHCP_lease(void) DEBUG_V1:dhcp_state=STATE_DHCP_DISCOVER,messageType=DHCP_OFFER -> send_DHCP_MESSAGE DHCP_REQUEST"));
                 #endif
                 // We'll use the transaction ID that the offer came with,
                 // rather than the one we were up to
@@ -117,11 +115,11 @@
         else if(_dhcp_state == STATE_DHCP_REQUEST)
         {
             uint32_t respId;
-            messageType = parseDHCPResponse(_responseTimeout, respId);
+            messageType = parseDHCPResponse(respId);
             if(messageType == DHCP_ACK)
             {
                 #if ACTLOGLEVEL>=LOG_DEBUG_V1
-                  LogObject.uart_send_str(F("DhcpClass::request_DHCP_lease(void) DEBUG_V1:dhcp_state=STATE_DHCP_REQUEST,messageType=DHCP_ACK"));
+                  LogObject.uart_send_strln(F("DhcpClass::request_DHCP_lease(void) DEBUG_V1:dhcp_state=STATE_DHCP_REQUEST,messageType=DHCP_ACK"));
                 #endif
                 _dhcp_state = STATE_DHCP_LEASED;
                 result = 1;
@@ -151,8 +149,11 @@
             _dhcp_state = STATE_DHCP_START;
         }
         
-        if(result != 1 && ((millis() - startTime) > _timeout))
+        if(result != 1 && ((millis() - startTime) > DHCP_TIMEOUT))
             break;
+    #if defined(ESP8266)
+       wdt_reset();
+    #endif
     }
     
     // We're done with the socket now
@@ -165,14 +166,14 @@
 void DhcpClass::presend_DHCP(void)
 {
     #if ACTLOGLEVEL>=LOG_DEBUG_V1
-      LogObject.uart_send_str(F("DhcpClass::presend_DHCP(void) DEBUG_V1:Function started (Empty function)"));
+      LogObject.uart_send_strln(F("DhcpClass::presend_DHCP(void) DEBUG_V1:Function started (Empty function)"));
     #endif
 }
 
 void DhcpClass::send_DHCP_MESSAGE(uint8_t messageType, uint16_t secondsElapsed)
 {
     #if ACTLOGLEVEL>=LOG_DEBUG_V1
-      LogObject.uart_send_str(F("DhcpClass::send_DHCP_MESSAGE(uint8_t messageType, uint16_t secondsElapsed) DEBUG_V1:Function started"));
+      LogObject.uart_send_strln(F("DhcpClass::send_DHCP_MESSAGE(uint8_t messageType, uint16_t secondsElapsed) DEBUG_V1:Function started"));
     #endif
     uint8_t buffer[32];
     memset(buffer, 0, 32);
@@ -258,17 +259,17 @@
     {
         buffer[0] = dhcpRequestedIPaddr;
         buffer[1] = 0x04;
-        buffer[2] = _dhcpLocalIp[0];
-        buffer[3] = _dhcpLocalIp[1];
-        buffer[4] = _dhcpLocalIp[2];
-        buffer[5] = _dhcpLocalIp[3];
+        buffer[2] = _dhcpipv4struct.LocalIp[0];
+        buffer[3] = _dhcpipv4struct.LocalIp[1];
+        buffer[4] = _dhcpipv4struct.LocalIp[2];
+        buffer[5] = _dhcpipv4struct.LocalIp[3];
 
         buffer[6] = dhcpServerIdentifier;
         buffer[7] = 0x04;
-        buffer[8] = _dhcpDhcpServerIp[0];
-        buffer[9] = _dhcpDhcpServerIp[1];
-        buffer[10] = _dhcpDhcpServerIp[2];
-        buffer[11] = _dhcpDhcpServerIp[3];
+        buffer[8] = _dhcpipv4struct.DhcpServerIp[0];
+        buffer[9] = _dhcpipv4struct.DhcpServerIp[1];
+        buffer[10] = _dhcpipv4struct.DhcpServerIp[2];
+        buffer[11] = _dhcpipv4struct.DhcpServerIp[3];
 
         //put data in W5100 transmit buffer
         _dhcpUdpSocket.write(buffer, 12);
@@ -290,10 +291,10 @@
     _dhcpUdpSocket.endPacket();
 }
 
-uint8_t DhcpClass::parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId)
+uint8_t DhcpClass::parseDHCPResponse(uint32_t& transactionId)
 {
     #if ACTLOGLEVEL>=LOG_DEBUG_V1
-      LogObject.uart_send_str(F("DhcpClass::parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId) DEBUG_V1:Function started"));
+      LogObject.uart_send_strln(F("DhcpClass::parseDHCPResponse(uint32_t& transactionId) DEBUG_V1:Function started"));
     #endif
     uint8_t type = 0;
     uint8_t opt_len = 0;
@@ -302,7 +303,7 @@
 
     while(_dhcpUdpSocket.parsePacket() <= 0)
     {
-        if((millis() - startTime) > responseTimeout)
+        if((millis() - startTime) > DHCP_RESPONSE_TIMEOUT)
         {
             return 255;
         }
@@ -322,7 +323,7 @@
             return 0;
         }
 
-        memcpy(_dhcpLocalIp, fixedMsg.yiaddr, 4);
+        memcpy(_dhcpipv4struct.LocalIp, fixedMsg.yiaddr, 4);
 
         // Skip to the option part
         // Doing this a byte at a time so we don't have to put a big buffer
@@ -349,12 +350,12 @@
                 
                 case subnetMask :
                     opt_len = _dhcpUdpSocket.read();
-                    _dhcpUdpSocket.read((char*)_dhcpSubnetMask, 4);
+                    _dhcpUdpSocket.read((char*)_dhcpipv4struct.SubnetMask, 4);
                     break;
                 
                 case routersOnSubnet :
                     opt_len = _dhcpUdpSocket.read();
-                    _dhcpUdpSocket.read((char*)_dhcpGatewayIp, 4);
+                    _dhcpUdpSocket.read((char*)_dhcpipv4struct.GatewayIp, 4);
                     for (int i = 0; i < opt_len-4; i++)
                     {
                         _dhcpUdpSocket.read();
@@ -363,7 +364,7 @@
                 
                 case dns :
                     opt_len = _dhcpUdpSocket.read();
-                    _dhcpUdpSocket.read((char*)_dhcpDnsServerIp, 4);
+                    _dhcpUdpSocket.read((char*)_dhcpipv4struct.DnsServerIp, 4);
                     for (int i = 0; i < opt_len-4; i++)
                     {
                         _dhcpUdpSocket.read();
@@ -372,10 +373,10 @@
                 
                 case dhcpServerIdentifier :
                     opt_len = _dhcpUdpSocket.read();
-                    if( IPAddress(_dhcpDhcpServerIp) == IPAddress(0,0,0,0) ||
-                        IPAddress(_dhcpDhcpServerIp) == _dhcpUdpSocket.remoteIP() )
+                    if( IPAddress(_dhcpipv4struct.DhcpServerIp) == IPAddress(0,0,0,0) ||
+                        IPAddress(_dhcpipv4struct.DhcpServerIp) == _dhcpUdpSocket.remoteIP() )
                     {
-                        _dhcpUdpSocket.read((char*)_dhcpDhcpServerIp, sizeof(_dhcpDhcpServerIp));
+                        _dhcpUdpSocket.read((char*)_dhcpipv4struct.DhcpServerIp, sizeof(_dhcpipv4struct.DhcpServerIp));
                     }
                     else
                     {
@@ -435,7 +436,7 @@
 */
 int DhcpClass::checkLease(void){
     #if ACTLOGLEVEL>=LOG_DEBUG_V1
-      LogObject.uart_send_str(F("DhcpClass::checkLease(void) DEBUG_V1:Function started"));
+      LogObject.uart_send_strln(F("DhcpClass::checkLease(void) DEBUG_V1:Function started"));
     #endif
 
     //this uses a signed / unsigned trick to deal with millis overflow
@@ -493,46 +494,46 @@
 IPAddress DhcpClass::getLocalIp(void)
 {
     #if ACTLOGLEVEL>=LOG_DEBUG_V1
-      LogObject.uart_send_str(F("DhcpClass::getLocalIp(void) DEBUG_V1:Function started"));
+      LogObject.uart_send_strln(F("DhcpClass::getLocalIp(void) DEBUG_V1:Function started"));
     #endif
-    return IPAddress(_dhcpLocalIp);
+    return IPAddress(_dhcpipv4struct.LocalIp);
 }
 
 IPAddress DhcpClass::getSubnetMask(void)
 {
     #if ACTLOGLEVEL>=LOG_DEBUG_V1
-      LogObject.uart_send_str(F("DhcpClass::getSubnetMask(void) DEBUG_V1:Function started"));
+      LogObject.uart_send_strln(F("DhcpClass::getSubnetMask(void) DEBUG_V1:Function started"));
     #endif
-    return IPAddress(_dhcpSubnetMask);
+    return IPAddress(_dhcpipv4struct.SubnetMask);
 }
 
 IPAddress DhcpClass::getGatewayIp(void)
 {
     #if ACTLOGLEVEL>=LOG_DEBUG_V1
-      LogObject.uart_send_str(F("DhcpClass::getGatewayIp(void) DEBUG_V1:Function started"));
+      LogObject.uart_send_strln(F("DhcpClass::getGatewayIp(void) DEBUG_V1:Function started"));
     #endif
-    return IPAddress(_dhcpGatewayIp);
+    return IPAddress(_dhcpipv4struct.GatewayIp);
 }
 
 IPAddress DhcpClass::getDhcpServerIp(void)
 {
     #if ACTLOGLEVEL>=LOG_DEBUG_V1
-      LogObject.uart_send_str(F("DhcpClass::getDhcpServerIp(void) DEBUG_V1:Function started"));
+      LogObject.uart_send_strln(F("DhcpClass::getDhcpServerIp(void) DEBUG_V1:Function started"));
     #endif
-    return IPAddress(_dhcpDhcpServerIp);
+    return IPAddress(_dhcpipv4struct.DhcpServerIp);
 }
 
 IPAddress DhcpClass::getDnsServerIp(void)
 {
     #if ACTLOGLEVEL>=LOG_DEBUG_V1
-      LogObject.uart_send_str(F("DhcpClass::getDnsServerIp(void) DEBUG_V1:Function started"));
+      LogObject.uart_send_strln(F("DhcpClass::getDnsServerIp(void) DEBUG_V1:Function started"));
     #endif
-    return IPAddress(_dhcpDnsServerIp);
+    return IPAddress(_dhcpipv4struct.DnsServerIp);
 }
 
 void DhcpClass::printByte(char * buf, uint8_t n ) {
     #if ACTLOGLEVEL>=LOG_DEBUG_V1
-      LogObject.uart_send_str(F("DhcpClass::printByte(char * buf, uint8_t n ) DEBUG_V1:Function started"));
+      LogObject.uart_send_strln(F("DhcpClass::printByte(char * buf, uint8_t n ) DEBUG_V1:Function started"));
     #endif
   char *str = &buf[1];
   buf[0]='0';
--- a/Dhcp.h	Wed Feb 22 13:40:36 2017 +0000
+++ b/Dhcp.h	Mon Mar 27 22:31:01 2017 +0200
@@ -46,6 +46,8 @@
 
 #define HOST_NAME "ENC28J"
 #define DEFAULT_LEASE	(900) //default lease time in seconds
+#define DHCP_TIMEOUT            60000
+#define DHCP_RESPONSE_TIMEOUT   4000
 
 #define DHCP_CHECK_NONE         (0)
 #define DHCP_CHECK_RENEW_FAIL   (1)
@@ -139,23 +141,26 @@
 	uint8_t  chaddr[6];
 }RIP_MSG_FIXED;
 
+typedef struct
+{
+  uint8_t  LocalIp[4];
+  uint8_t  SubnetMask[4];
+  uint8_t  GatewayIp[4];
+  uint8_t  DhcpServerIp[4];
+  uint8_t  DnsServerIp[4];
+} TIPV4Struct;
+
 class DhcpClass {
 private:
   uint32_t _dhcpInitialTransactionId;
   uint32_t _dhcpTransactionId;
   uint8_t  _dhcpMacAddr[6];
-  uint8_t  _dhcpLocalIp[4];
-  uint8_t  _dhcpSubnetMask[4];
-  uint8_t  _dhcpGatewayIp[4];
-  uint8_t  _dhcpDhcpServerIp[4];
-  uint8_t  _dhcpDnsServerIp[4];
+  TIPV4Struct _dhcpipv4struct;
   uint32_t _dhcpLeaseTime;
   uint32_t _dhcpT1, _dhcpT2;
   signed long _renewInSec;
   signed long _rebindInSec;
   signed long _lastCheck;
-  unsigned long _timeout;
-  unsigned long _responseTimeout;
   unsigned long _secTimeout;
   uint8_t _dhcp_state;
   UIPUDP _dhcpUdpSocket;
@@ -166,7 +171,7 @@
   void send_DHCP_MESSAGE(uint8_t, uint16_t);
   void printByte(char *, uint8_t);
   
-  uint8_t parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId);
+  uint8_t parseDHCPResponse(uint32_t& transactionId);
 public:
   IPAddress getLocalIp(void);
   IPAddress getSubnetMask(void);
@@ -174,7 +179,7 @@
   IPAddress getDhcpServerIp(void);
   IPAddress getDnsServerIp(void);
   
-  int beginWithDHCP(uint8_t *, unsigned long timeout = 60000, unsigned long responseTimeout = 4000);
+  int beginWithDHCP(uint8_t *);
   int checkLease(void);
 };
 #endif
--- a/README.md	Wed Feb 22 13:40:36 2017 +0000
+++ b/README.md	Mon Mar 27 22:31:01 2017 +0200
@@ -1,40 +1,43 @@
-# UIPEthernet
-UIPEthernet library for Arduinos (Atmel AVR-s,Atmel SAM3X8E ARM Cortex-M3,STM32F series,ESP8266,Intel ARC32(Genuino101),Nordic nRF51(RFduino),Teensy boards,Realtek Ameba(RTL8195A,RTL8710)), ENC28j60 network chip compatible with Wiznet W5100 API
-
-Original UIPEthernet writed by Norbert Truchsess.
-
-You can find wiring diagram for more board in the hardware directory.
-
-Modifications:
-- Replaced import to include, because gcc say 'import is deprecated'.
-- Added support for STM32F, and ESP8266 MCU-s.
-- Merged martinayotte's modification (Correct s_dhcp ~40K more memory usage with STM32F MCU-s.)
-- Moved htons,ntohs,htonl,ntohl definitions to uip.h.
-- Corrected infinite loops.
-- Set the version to 2.0.3
-- Corrected ESP8266 exception(28).
-- Added watchdog reset calls in functions for stable running on ESP8266.
-- Added geterevid function to get ENC28j60 chip erevid (revision information).
-- Changed linkStatus to static for outside call.
-- Added functions bypass, if can't communicate with ethernet device.
-- Changed debuging/logging. Remove individual debuging. Add global and scalable debuging feature.
-You can setup debuging/logging level in utility/logging.h
-You can use this header file in Your scetch too.
-Add "LogObject" define for serial logging/debuging with board specific default setting.
-- Added support to MBED/SMeshStudio IDE. (Compiled and tested on Nucleo-F302R8. (STM32F302R8))
-
-- Added Abstract Print class to MBED for full compatibility (Can use print, println with uip objects.)
-- Errata#12 corrected (by seydamir).
-- Created v2.0.2 release.
-
-If You use NodeMCU please check wiring first:
-https://github.com/UIPEthernet/UIPEthernet/blob/master/hardware/NodeMCU_enc28j60_wiring.PNG
-
-- You can save 5K flash if you disable UDP support.
-- Correction code of Errata#12 modified.
-- Added support for Intel ARC32(Genuino101), Nordic nRF51(RFduino), Teensy boards
-- Issue#4 corrected
-- Added support for Realtek Ameba(RTL8195A,RTL8710)
-- Added support Eclipse with arduino plugin
-- Added direct broadcast support
-
+# UIPEthernet
+UIPEthernet library for Arduinos (Atmel AVR-s,Atmel SAM3X8E ARM Cortex-M3,STM32F series,ESP8266,Intel ARC32(Genuino101),Nordic nRF51(RFduino),Teensy boards,Realtek Ameba(RTL8195A,RTL8710)), ENC28j60 network chip compatible with Wiznet W5100 API
+
+Original UIPEthernet writed by Norbert Truchsess.
+
+You can find wiring diagram for more board in the hardware directory.
+
+Modifications:
+- Replaced import to include, because gcc say 'import is deprecated'.
+- Added support for STM32F, and ESP8266 MCU-s.
+- Merged martinayotte's modification (Correct s_dhcp ~40K more memory usage with STM32F MCU-s.)
+- Moved htons,ntohs,htonl,ntohl definitions to uip.h.
+- Corrected infinite loops.
+- Set the version to 2.0.3
+- Corrected ESP8266 exception(28).
+- Added watchdog reset calls in functions for stable running on ESP8266.
+- Added geterevid function to get ENC28j60 chip erevid (revision information).
+- Changed linkStatus to static for outside call.
+- Added functions bypass, if can't communicate with ethernet device.
+- Changed debuging/logging. Remove individual debuging. Add global and scalable debuging feature.
+You can setup debuging/logging level in utility/logging.h
+You can use this header file in Your scetch too.
+Add "LogObject" define for serial logging/debuging with board specific default setting.
+- Added support to MBED/SMeshStudio IDE. (Compiled and tested on Nucleo-F302R8. (STM32F302R8))
+
+- Added Abstract Print class to MBED for full compatibility (Can use print, println with uip objects.)
+- Errata#12 corrected (by seydamir).
+- Created v2.0.2 release.
+
+If You use NodeMCU please check wiring first:
+https://github.com/UIPEthernet/UIPEthernet/blob/master/hardware/NodeMCU_enc28j60_wiring.PNG
+
+- You can save 5K flash if you disable UDP support.
+- Correction code of Errata#12 modified.
+- Added support for Intel ARC32(Genuino101), Nordic nRF51(RFduino), Teensy boards
+- Issue#4 corrected
+- Added support for Realtek Ameba(RTL8195A,RTL8710)
+- Added direct broadcast support
+- Issue#5 corrected: You can save 5K flash memory with disable UDP support.
+- Issue#6 corrected: Added support Eclipse with arduino plugin
+- Issue#8, and Issue#9 corrected: Modified DHCP code: Moved timeouts define to dhcp.h
+- Issue#11 corrected: Changed ENC28J60_CONTROL_CS pin to 10 on Arduino Due
+- New release:2.0.4
--- a/library.json	Wed Feb 22 13:40:36 2017 +0000
+++ b/library.json	Mon Mar 27 22:31:01 2017 +0200
@@ -16,9 +16,9 @@
       "maintainer": true
     }
   ],
-  "version": "2.0.3",
+  "version": "2.0.4",
   "frameworks": "arduino, mbed",
-  "platforms": "atmelavr, atmelsam, espressif8266",
+  "platforms": "atmelavr, atmelsam, espressif8266, intel_arc32, nordicnrf51, nxplpc, ststm32, teensy",
   "export":
   {
     "exclude": [
--- a/library.properties	Wed Feb 22 13:40:36 2017 +0000
+++ b/library.properties	Mon Mar 27 22:31:01 2017 +0200
@@ -6,7 +6,7 @@
 paragraph=implements the same API as stock Ethernet-lib. Just replace the include of Ethernet.h with UIPEthernet.h
 url=https://github.com/UIPEthernet/UIPEthernet
 category=Communication
-version=2.0.3
+version=2.0.4
 dependencies=
 core-dependencies=arduino (>=1.5.0)
 includes=UIPEthernet.h,utility/logging.h
--- a/utility/Enc28J60Network.h	Wed Feb 22 13:40:36 2017 +0000
+++ b/utility/Enc28J60Network.h	Mon Mar 27 22:31:01 2017 +0200
@@ -80,7 +80,8 @@
       #define ENC28J60_CONTROL_CS     SS //PC_0 A5 10
    #elif defined(ARDUINO_ARCH_SAM)
       // Arduino Due (ARDUINO_ARCH_SAM) BOARD_SPI_DEFAULT_SS (SS3) defined to pin 78
-      #define ENC28J60_CONTROL_CS     BOARD_SPI_DEFAULT_SS
+      //#define ENC28J60_CONTROL_CS     BOARD_SPI_DEFAULT_SS
+      #define ENC28J60_CONTROL_CS     BOARD_SPI_SS0
    #elif defined(__ARDUINO_ARC__) //Intel ARC32 Genuino 101
       #define ENC28J60_CONTROL_CS     SS
    #elif defined(__RFduino__) //RFduino