From 946735a12e8f5aa0849bbdfecfe3fd5e1ec4995e Mon Sep 17 00:00:00 2001 From: Khoi Hoang <57012152+khoih-prog@users.noreply.github.com> Date: Thu, 24 Nov 2022 17:25:10 -0500 Subject: [PATCH] Update `LibraryPatches` --- LibraryPatches/Ethernet/src/Ethernet.cpp | 338 ++- LibraryPatches/Ethernet/src/Ethernet.h | 569 ++-- .../Ethernet/src/EthernetServer.cpp | 332 +-- LibraryPatches/Ethernet/src/utility/w5100.cpp | 1065 +++---- LibraryPatches/Ethernet/src/utility/w5100.h | 843 +++--- LibraryPatches/Ethernet2/src/Ethernet2.cpp | 86 +- LibraryPatches/Ethernet2/src/Ethernet2.h | 142 +- LibraryPatches/Ethernet2/src/EthernetUdp2.cpp | 144 +- LibraryPatches/Ethernet2/src/EthernetUdp2.h | 208 +- LibraryPatches/Ethernet3/src/Ethernet3.cpp | 232 +- LibraryPatches/Ethernet3/src/Ethernet3.h | 199 +- .../EthernetLarge/src/EthernetLarge.cpp | 335 ++- .../EthernetLarge/src/EthernetLarge.h | 557 ++-- .../EthernetLarge/src/EthernetServer.cpp | 382 ++- .../EthernetLarge/src/utility/w5100.cpp | 1057 +++---- .../EthernetLarge/src/utility/w5100.h | 835 +++--- .../UIPEthernet-2.0.9/UIPEthernet.cpp | 1309 +++++---- .../UIPEthernet-2.0.9/UIPEthernet.h | 334 +-- .../utility/Enc28J60Network.cpp | 2529 ++++++++-------- .../utility/Enc28J60Network.h | 675 ++--- LibraryPatches/UIPEthernet/UIPEthernet.cpp | 1339 +++++---- LibraryPatches/UIPEthernet/UIPEthernet.h | 317 +- .../UIPEthernet/utility/Enc28J60Network.cpp | 2580 +++++++++-------- .../UIPEthernet/utility/Enc28J60Network.h | 663 ++--- LibraryPatches/esp32/cores/esp32/Server.h | 30 +- 25 files changed, 8946 insertions(+), 8154 deletions(-) diff --git a/LibraryPatches/Ethernet/src/Ethernet.cpp b/LibraryPatches/Ethernet/src/Ethernet.cpp index 0f3db05..cc6899e 100644 --- a/LibraryPatches/Ethernet/src/Ethernet.cpp +++ b/LibraryPatches/Ethernet/src/Ethernet.cpp @@ -9,17 +9,17 @@ Version: 1.0.9 Copyright 2018 Paul Stoffregen - + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -34,11 +34,11 @@ 1.0.2 K Hoang 20/02/2020 Add support to UIPEthernet library for ENC28J60 1.0.3 K Hoang 23/02/2020 Add support to SAM DUE / SAMD21 boards 1.0.4 K Hoang 16/04/2020 Add support to SAMD51 boards - 1.0.5 K Hoang 24/04/2020 Add support to nRF52 boards, such as AdaFruit Feather nRF52832, nRF52840 Express, BlueFruit Sense, - Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B30_ublox, etc. + 1.0.5 K Hoang 24/04/2020 Add support to nRF52 boards, such as AdaFruit Feather nRF52832, nRF52840 Express, BlueFruit Sense, + Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B30_ublox, etc. More Custom Ethernet libraries supported such as Ethernet2, Ethernet3, EthernetLarge - 1.0.6 K Hoang 27/04/2020 Add support to ESP32/ESP8266 boards - 1.0.7 K Hoang 30/04/2020 Add ENC28J60 support to ESP32/ESP8266 boards + 1.0.6 K Hoang 27/04/2020 Add support to ESP32/ESP8266 boards + 1.0.7 K Hoang 30/04/2020 Add ENC28J60 support to ESP32/ESP8266 boards 1.0.8 K Hoang 12/05/2020 Fix W5x00 support for ESP8266 boards. 1.0.9 K Hoang 15/05/2020 Add EthernetWrapper.h for easier W5x00 support as well as more Ethernet libs in the future. *****************************************************************************************************************************/ @@ -48,45 +48,45 @@ #include "utility/w5100.h" #include "Dhcp.h" -#define ETHERNET_DEBUG 1 +#define ETHERNET_DEBUG 1 IPAddress EthernetClass::_dnsServerAddress; DhcpClass* EthernetClass::_dhcp = NULL; // KH -void EthernetClass::setRstPin(uint8_t pinRST) +void EthernetClass::setRstPin(uint8_t pinRST) { _pinRST = pinRST; pinMode(_pinRST, OUTPUT); digitalWrite(_pinRST, HIGH); } -void EthernetClass::setCsPin(uint8_t pinCS) +void EthernetClass::setCsPin(uint8_t pinCS) { _pinCS = pinCS; W5100.setSS(pinCS); - -#if ( ETHERNET_DEBUG > 0 ) + +#if ( ETHERNET_DEBUG > 0 ) Serial.print("Input pinCS = "); - Serial.println(pinCS); + Serial.println(pinCS); Serial.print("_pinCS = "); - Serial.println(_pinCS); -#endif + Serial.println(_pinCS); +#endif } -void EthernetClass::initMaxSockNum(uint8_t maxSockNum) +void EthernetClass::initMaxSockNum(uint8_t maxSockNum) { _maxSockNum = maxSockNum; } -uint8_t EthernetClass::softreset() +uint8_t EthernetClass::softreset() { return W5100.softReset(); } -void EthernetClass::hardreset() +void EthernetClass::hardreset() { - if(_pinRST != 0) + if (_pinRST != 0) { digitalWrite(_pinRST, LOW); delay(1); @@ -94,227 +94,253 @@ void EthernetClass::hardreset() delay(150); } } - + int EthernetClass::begin(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout) { - DhcpClass s_dhcp; - _dhcp = &s_dhcp; + DhcpClass s_dhcp; + _dhcp = &s_dhcp; -#if ( ETHERNET_DEBUG > 0 ) +#if ( ETHERNET_DEBUG > 0 ) Serial.print("_pinCS = "); - Serial.print(_pinCS); + Serial.print(_pinCS); #endif - - // Initialise the basic info - if (W5100.init() == 0) - return 0; - - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - W5100.setMACAddress(mac); - W5100.setIPAddress(IPAddress(0,0,0,0).raw_address()); - SPI.endTransaction(); - - // Now try to get our config info from a DHCP server - int ret = _dhcp->beginWithDHCP(mac, timeout, responseTimeout); - if (ret == 1) - { - // We've successfully found a DHCP server and got our configuration - // info, so set things accordingly - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - W5100.setIPAddress(_dhcp->getLocalIp().raw_address()); - W5100.setGatewayIp(_dhcp->getGatewayIp().raw_address()); - W5100.setSubnetMask(_dhcp->getSubnetMask().raw_address()); - SPI.endTransaction(); - _dnsServerAddress = _dhcp->getDnsServerIp(); - socketPortRand(micros()); - } - return ret; + + // Initialise the basic info + if (W5100.init() == 0) + return 0; + + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.setMACAddress(mac); + W5100.setIPAddress(IPAddress(0, 0, 0, 0).raw_address()); + SPI.endTransaction(); + + // Now try to get our config info from a DHCP server + int ret = _dhcp->beginWithDHCP(mac, timeout, responseTimeout); + + if (ret == 1) + { + // We've successfully found a DHCP server and got our configuration + // info, so set things accordingly + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.setIPAddress(_dhcp->getLocalIp().raw_address()); + W5100.setGatewayIp(_dhcp->getGatewayIp().raw_address()); + W5100.setSubnetMask(_dhcp->getSubnetMask().raw_address()); + SPI.endTransaction(); + _dnsServerAddress = _dhcp->getDnsServerIp(); + socketPortRand(micros()); + } + + return ret; } void EthernetClass::begin(uint8_t *mac, IPAddress ip) { - // Assume the DNS server will be the machine on the same network as the local IP - // but with last octet being '1' - IPAddress dns = ip; - dns[3] = 1; - begin(mac, ip, dns); + // Assume the DNS server will be the machine on the same network as the local IP + // but with last octet being '1' + IPAddress dns = ip; + dns[3] = 1; + begin(mac, ip, dns); } void EthernetClass::begin(uint8_t *mac, IPAddress ip, IPAddress dns) { - // Assume the gateway will be the machine on the same network as the local IP - // but with last octet being '1' - IPAddress gateway = ip; - gateway[3] = 1; - begin(mac, ip, dns, gateway); + // Assume the gateway will be the machine on the same network as the local IP + // but with last octet being '1' + IPAddress gateway = ip; + gateway[3] = 1; + begin(mac, ip, dns, gateway); } void EthernetClass::begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway) { - IPAddress subnet(255, 255, 255, 0); - begin(mac, ip, dns, gateway, subnet); + IPAddress subnet(255, 255, 255, 0); + begin(mac, ip, dns, gateway, subnet); } void EthernetClass::begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) { - // Initialise the basic info - if (W5100.init() == 0) - return; - - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - W5100.setMACAddress(mac); - + // Initialise the basic info + if (W5100.init() == 0) + return; + + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.setMACAddress(mac); + #if ( defined(ESP8266) || defined(ESP32) ) W5100.setIPAddress(ip.raw_address()); - W5100.setGatewayIp(gateway.raw_address()); - W5100.setSubnetMask(subnet.raw_address()); + W5100.setGatewayIp(gateway.raw_address()); + W5100.setSubnetMask(subnet.raw_address()); #elif (ARDUINO > 106 || TEENSYDUINO > 121) - W5100.setIPAddress(ip._address.bytes); - W5100.setGatewayIp(gateway._address.bytes); - W5100.setSubnetMask(subnet._address.bytes); + W5100.setIPAddress(ip._address.bytes); + W5100.setGatewayIp(gateway._address.bytes); + W5100.setSubnetMask(subnet._address.bytes); #else - W5100.setIPAddress(ip._address); - W5100.setGatewayIp(gateway._address); - W5100.setSubnetMask(subnet._address); + W5100.setIPAddress(ip._address); + W5100.setGatewayIp(gateway._address); + W5100.setSubnetMask(subnet._address); #endif - SPI.endTransaction(); - _dnsServerAddress = dns; + SPI.endTransaction(); + _dnsServerAddress = dns; } void EthernetClass::init(uint8_t sspin) { - W5100.setSS(sspin); + W5100.setSS(sspin); } EthernetLinkStatus EthernetClass::linkStatus() { - switch (W5100.getLinkStatus()) { - case UNKNOWN: return Unknown; - case LINK_ON: return LinkON; - case LINK_OFF: return LinkOFF; - default: return Unknown; - } + switch (W5100.getLinkStatus()) + { + case UNKNOWN: + return Unknown; + + case LINK_ON: + return LinkON; + + case LINK_OFF: + return LinkOFF; + + default: + return Unknown; + } } EthernetHardwareStatus EthernetClass::hardwareStatus() { - switch (W5100.getChip()) { - case 51: return EthernetW5100; - case 52: return EthernetW5200; - case 55: return EthernetW5500; - default: return EthernetNoHardware; - } + switch (W5100.getChip()) + { + case 51: + return EthernetW5100; + + case 52: + return EthernetW5200; + + case 55: + return EthernetW5500; + + default: + return EthernetNoHardware; + } } int EthernetClass::maintain() { - int rc = DHCP_CHECK_NONE; - if (_dhcp != NULL) { - // we have a pointer to dhcp, use it - rc = _dhcp->checkLease(); - switch (rc) - { - case DHCP_CHECK_NONE: - //nothing done - break; - case DHCP_CHECK_RENEW_OK: - case DHCP_CHECK_REBIND_OK: - //we might have got a new IP. - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - W5100.setIPAddress(_dhcp->getLocalIp().raw_address()); - W5100.setGatewayIp(_dhcp->getGatewayIp().raw_address()); - W5100.setSubnetMask(_dhcp->getSubnetMask().raw_address()); - SPI.endTransaction(); - _dnsServerAddress = _dhcp->getDnsServerIp(); - break; - default: - //this is actually an error, it will retry though - break; - } - } - return rc; + int rc = DHCP_CHECK_NONE; + + if (_dhcp != NULL) + { + // we have a pointer to dhcp, use it + rc = _dhcp->checkLease(); + + switch (rc) + { + case DHCP_CHECK_NONE: + //nothing done + break; + + case DHCP_CHECK_RENEW_OK: + case DHCP_CHECK_REBIND_OK: + //we might have got a new IP. + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.setIPAddress(_dhcp->getLocalIp().raw_address()); + W5100.setGatewayIp(_dhcp->getGatewayIp().raw_address()); + W5100.setSubnetMask(_dhcp->getSubnetMask().raw_address()); + SPI.endTransaction(); + _dnsServerAddress = _dhcp->getDnsServerIp(); + break; + + default: + //this is actually an error, it will retry though + break; + } + } + + return rc; } void EthernetClass::MACAddress(uint8_t *mac_address) { - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - W5100.getMACAddress(mac_address); - SPI.endTransaction(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.getMACAddress(mac_address); + SPI.endTransaction(); } IPAddress EthernetClass::localIP() { - IPAddress ret; - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - W5100.getIPAddress(ret.raw_address()); - SPI.endTransaction(); - return ret; + IPAddress ret; + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.getIPAddress(ret.raw_address()); + SPI.endTransaction(); + return ret; } IPAddress EthernetClass::subnetMask() { - IPAddress ret; - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - W5100.getSubnetMask(ret.raw_address()); - SPI.endTransaction(); - return ret; + IPAddress ret; + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.getSubnetMask(ret.raw_address()); + SPI.endTransaction(); + return ret; } IPAddress EthernetClass::gatewayIP() { - IPAddress ret; - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - W5100.getGatewayIp(ret.raw_address()); - SPI.endTransaction(); - return ret; + IPAddress ret; + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.getGatewayIp(ret.raw_address()); + SPI.endTransaction(); + return ret; } void EthernetClass::setMACAddress(const uint8_t *mac_address) { - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - W5100.setMACAddress(mac_address); - SPI.endTransaction(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.setMACAddress(mac_address); + SPI.endTransaction(); } void EthernetClass::setLocalIP(const IPAddress local_ip) { - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - IPAddress ip = local_ip; - W5100.setIPAddress(ip.raw_address()); - SPI.endTransaction(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + IPAddress ip = local_ip; + W5100.setIPAddress(ip.raw_address()); + SPI.endTransaction(); } void EthernetClass::setSubnetMask(const IPAddress subnet) { - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - IPAddress ip = subnet; - W5100.setSubnetMask(ip.raw_address()); - SPI.endTransaction(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + IPAddress ip = subnet; + W5100.setSubnetMask(ip.raw_address()); + SPI.endTransaction(); } void EthernetClass::setGatewayIP(const IPAddress gateway) { - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - IPAddress ip = gateway; - W5100.setGatewayIp(ip.raw_address()); - SPI.endTransaction(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + IPAddress ip = gateway; + W5100.setGatewayIp(ip.raw_address()); + SPI.endTransaction(); } void EthernetClass::setRetransmissionTimeout(uint16_t milliseconds) { - if (milliseconds > 6553) milliseconds = 6553; - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - W5100.setRetransmissionTime(milliseconds * 10); - SPI.endTransaction(); + if (milliseconds > 6553) + milliseconds = 6553; + + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.setRetransmissionTime(milliseconds * 10); + SPI.endTransaction(); } void EthernetClass::setRetransmissionCount(uint8_t num) { - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - W5100.setRetransmissionCount(num); - SPI.endTransaction(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.setRetransmissionCount(num); + SPI.endTransaction(); } EthernetClass Ethernet; diff --git a/LibraryPatches/Ethernet/src/Ethernet.h b/LibraryPatches/Ethernet/src/Ethernet.h index 6fee77f..1b634b5 100644 --- a/LibraryPatches/Ethernet/src/Ethernet.h +++ b/LibraryPatches/Ethernet/src/Ethernet.h @@ -9,17 +9,17 @@ Version: 1.0.9 Copyright 2018 Paul Stoffregen - + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -34,15 +34,15 @@ 1.0.2 K Hoang 20/02/2020 Add support to UIPEthernet library for ENC28J60 1.0.3 K Hoang 23/02/2020 Add support to SAM DUE / SAMD21 boards 1.0.4 K Hoang 16/04/2020 Add support to SAMD51 boards - 1.0.5 K Hoang 24/04/2020 Add support to nRF52 boards, such as AdaFruit Feather nRF52832, nRF52840 Express, BlueFruit Sense, - Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B30_ublox, etc. + 1.0.5 K Hoang 24/04/2020 Add support to nRF52 boards, such as AdaFruit Feather nRF52832, nRF52840 Express, BlueFruit Sense, + Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B30_ublox, etc. More Custom Ethernet libraries supported such as Ethernet2, Ethernet3, EthernetLarge - 1.0.6 K Hoang 27/04/2020 Add support to ESP32/ESP8266 boards - 1.0.7 K Hoang 30/04/2020 Add ENC28J60 support to ESP32/ESP8266 boards + 1.0.6 K Hoang 27/04/2020 Add support to ESP32/ESP8266 boards + 1.0.7 K Hoang 30/04/2020 Add ENC28J60 support to ESP32/ESP8266 boards 1.0.8 K Hoang 12/05/2020 Fix W5x00 support for ESP8266 boards. - 1.0.9 K Hoang 15/05/2020 Add EthernetWrapper.h for easier W5x00 support as well as more Ethernet libs in the future. + 1.0.9 K Hoang 15/05/2020 Add EthernetWrapper.h for easier W5x00 support as well as more Ethernet libs in the future. *****************************************************************************************************************************/ - + #ifndef ethernet_h_ #define ethernet_h_ @@ -59,9 +59,9 @@ // of RAM are used for each socket. Reducing the maximum can save RAM, but // you are limited to fewer simultaneous connections. #if defined(RAMEND) && defined(RAMSTART) && ((RAMEND - RAMSTART) <= 2048) -#define MAX_SOCK_NUM 2 //Reduce MAX_SOCK_NUM to 2 from 4, to increase buffer from 2k to 4K + #define MAX_SOCK_NUM 2 //Reduce MAX_SOCK_NUM to 2 from 4, to increase buffer from 2k to 4K #else -#define MAX_SOCK_NUM 4 //Reduce MAX_SOCK_NUM to 4 from 8, to increase buffer from 2k to 4K + #define MAX_SOCK_NUM 4 //Reduce MAX_SOCK_NUM to 4 from 8, to increase buffer from 2k to 4K #endif // By default, each socket uses 2K buffers inside the Wiznet chip. If @@ -80,17 +80,19 @@ #include "Server.h" #include "Udp.h" -enum EthernetLinkStatus { - Unknown, - LinkON, - LinkOFF +enum EthernetLinkStatus +{ + Unknown, + LinkON, + LinkOFF }; -enum EthernetHardwareStatus { - EthernetNoHardware, - EthernetW5100, - EthernetW5200, - EthernetW5500 +enum EthernetHardwareStatus +{ + EthernetNoHardware, + EthernetW5100, + EthernetW5200, + EthernetW5500 }; class EthernetUDP; @@ -98,96 +100,103 @@ class EthernetClient; class EthernetServer; class DhcpClass; -class EthernetClass { -private: - static IPAddress _dnsServerAddress; - static DhcpClass* _dhcp; -public: - // KH - uint8_t _maxSockNum; - uint8_t _pinCS; - uint8_t _pinRST; - - void setRstPin(uint8_t pinRST = 9); // for WIZ550io or USR-ES1, must set befor Ethernet.begin - void setCsPin(uint8_t pinCS = 10); // must set befor Ethernet.begin - - // Initialize with less sockets but more RX/TX Buffer - // maxSockNum = 1 Socket 0 -> RX/TX Buffer 16k - // maxSockNum = 2 Socket 0, 1 -> RX/TX Buffer 8k - // maxSockNum = 4 Socket 0...3 -> RX/TX Buffer 4k - // maxSockNum = 8 (Standard) all sockets -> RX/TX Buffer 2k - // be carefull of the MAX_SOCK_NUM, because in the moment it can't dynamicly changed - void initMaxSockNum(uint8_t maxSockNum = 8); - - uint8_t softreset(); // can set only after Ethernet.begin - void hardreset(); // You need to set the Rst pin - - // Initialise the Ethernet shield to use the provided MAC address and - // gain the rest of the configuration through DHCP. - // Returns 0 if the DHCP configuration failed, and 1 if it succeeded - int begin(uint8_t *mac, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); - int maintain(); - EthernetLinkStatus linkStatus(); - EthernetHardwareStatus hardwareStatus(); - - // Manual configuration - void begin(uint8_t *mac, IPAddress ip); - void begin(uint8_t *mac, IPAddress ip, IPAddress dns); - void begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway); - void begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet); - void init(uint8_t sspin = 10); - - void MACAddress(uint8_t *mac_address); - IPAddress localIP(); - IPAddress subnetMask(); - IPAddress gatewayIP(); - IPAddress dnsServerIP() { return _dnsServerAddress; } - - void setMACAddress(const uint8_t *mac_address); - void setLocalIP(const IPAddress local_ip); - void setSubnetMask(const IPAddress subnet); - void setGatewayIP(const IPAddress gateway); - void setDnsServerIP(const IPAddress dns_server) { _dnsServerAddress = dns_server; } - void setRetransmissionTimeout(uint16_t milliseconds); - void setRetransmissionCount(uint8_t num); - - friend class EthernetClient; - friend class EthernetServer; - friend class EthernetUDP; -private: - // Opens a socket(TCP or UDP or IP_RAW mode) - uint8_t socketBegin(uint8_t protocol, uint16_t port); - uint8_t socketBeginMulticast(uint8_t protocol, IPAddress ip,uint16_t port); - uint8_t socketStatus(uint8_t s); - // Close socket - void socketClose(uint8_t s); - // Establish TCP connection (Active connection) - void socketConnect(uint8_t s, uint8_t * addr, uint16_t port); - // disconnect the connection - void socketDisconnect(uint8_t s); - // Establish TCP connection (Passive connection) - uint8_t socketListen(uint8_t s); - // Send data (TCP) - uint16_t socketSend(uint8_t s, const uint8_t * buf, uint16_t len); - uint16_t socketSendAvailable(uint8_t s); - // Receive data (TCP) - int socketRecv(uint8_t s, uint8_t * buf, int16_t len); - uint16_t socketRecvAvailable(uint8_t s); - uint8_t socketPeek(uint8_t s); - // sets up a UDP datagram, the data for which will be provided by one - // or more calls to bufferData and then finally sent with sendUDP. - // return true if the datagram was successfully set up, or false if there was an error - bool socketStartUDP(uint8_t s, uint8_t* addr, uint16_t port); - // copy up to len bytes of data from buf into a UDP datagram to be - // sent later by sendUDP. Allows datagrams to be built up from a series of bufferData calls. - // return Number of bytes successfully buffered - uint16_t socketBufferData(uint8_t s, uint16_t offset, const uint8_t* buf, uint16_t len); - // Send a UDP datagram built up from a sequence of startUDP followed by one or more - // calls to bufferData. - // return true if the datagram was successfully sent, or false if there was an error - bool socketSendUDP(uint8_t s); - // Initialize the "random" source port number - void socketPortRand(uint16_t n); +class EthernetClass +{ + private: + static IPAddress _dnsServerAddress; + static DhcpClass* _dhcp; + public: + // KH + uint8_t _maxSockNum; + uint8_t _pinCS; + uint8_t _pinRST; + + void setRstPin(uint8_t pinRST = 9); // for WIZ550io or USR-ES1, must set befor Ethernet.begin + void setCsPin(uint8_t pinCS = 10); // must set befor Ethernet.begin + + // Initialize with less sockets but more RX/TX Buffer + // maxSockNum = 1 Socket 0 -> RX/TX Buffer 16k + // maxSockNum = 2 Socket 0, 1 -> RX/TX Buffer 8k + // maxSockNum = 4 Socket 0...3 -> RX/TX Buffer 4k + // maxSockNum = 8 (Standard) all sockets -> RX/TX Buffer 2k + // be carefull of the MAX_SOCK_NUM, because in the moment it can't dynamicly changed + void initMaxSockNum(uint8_t maxSockNum = 8); + + uint8_t softreset(); // can set only after Ethernet.begin + void hardreset(); // You need to set the Rst pin + + // Initialise the Ethernet shield to use the provided MAC address and + // gain the rest of the configuration through DHCP. + // Returns 0 if the DHCP configuration failed, and 1 if it succeeded + int begin(uint8_t *mac, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); + int maintain(); + EthernetLinkStatus linkStatus(); + EthernetHardwareStatus hardwareStatus(); + + // Manual configuration + void begin(uint8_t *mac, IPAddress ip); + void begin(uint8_t *mac, IPAddress ip, IPAddress dns); + void begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway); + void begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet); + void init(uint8_t sspin = 10); + + void MACAddress(uint8_t *mac_address); + IPAddress localIP(); + IPAddress subnetMask(); + IPAddress gatewayIP(); + IPAddress dnsServerIP() + { + return _dnsServerAddress; + } + + void setMACAddress(const uint8_t *mac_address); + void setLocalIP(const IPAddress local_ip); + void setSubnetMask(const IPAddress subnet); + void setGatewayIP(const IPAddress gateway); + void setDnsServerIP(const IPAddress dns_server) + { + _dnsServerAddress = dns_server; + } + void setRetransmissionTimeout(uint16_t milliseconds); + void setRetransmissionCount(uint8_t num); + + friend class EthernetClient; + friend class EthernetServer; + friend class EthernetUDP; + private: + // Opens a socket(TCP or UDP or IP_RAW mode) + uint8_t socketBegin(uint8_t protocol, uint16_t port); + uint8_t socketBeginMulticast(uint8_t protocol, IPAddress ip, uint16_t port); + uint8_t socketStatus(uint8_t s); + // Close socket + void socketClose(uint8_t s); + // Establish TCP connection (Active connection) + void socketConnect(uint8_t s, uint8_t * addr, uint16_t port); + // disconnect the connection + void socketDisconnect(uint8_t s); + // Establish TCP connection (Passive connection) + uint8_t socketListen(uint8_t s); + // Send data (TCP) + uint16_t socketSend(uint8_t s, const uint8_t * buf, uint16_t len); + uint16_t socketSendAvailable(uint8_t s); + // Receive data (TCP) + int socketRecv(uint8_t s, uint8_t * buf, int16_t len); + uint16_t socketRecvAvailable(uint8_t s); + uint8_t socketPeek(uint8_t s); + // sets up a UDP datagram, the data for which will be provided by one + // or more calls to bufferData and then finally sent with sendUDP. + // return true if the datagram was successfully set up, or false if there was an error + bool socketStartUDP(uint8_t s, uint8_t* addr, uint16_t port); + // copy up to len bytes of data from buf into a UDP datagram to be + // sent later by sendUDP. Allows datagrams to be built up from a series of bufferData calls. + // return Number of bytes successfully buffered + uint16_t socketBufferData(uint8_t s, uint16_t offset, const uint8_t* buf, uint16_t len); + // Send a UDP datagram built up from a sequence of startUDP followed by one or more + // calls to bufferData. + // return true if the datagram was successfully sent, or false if there was an error + bool socketSendUDP(uint8_t s); + // Initialize the "random" source port number + void socketPortRand(uint16_t n); }; extern EthernetClass Ethernet; @@ -195,172 +204,208 @@ extern EthernetClass Ethernet; #define UDP_TX_PACKET_MAX_SIZE 24 -class EthernetUDP : public UDP { -private: - uint16_t _port; // local port to listen on - IPAddress _remoteIP; // remote IP address for the incoming packet whilst it's being processed - uint16_t _remotePort; // remote port for the incoming packet whilst it's being processed - uint16_t _offset; // offset into the packet being sent - -protected: - uint8_t sockindex; - uint16_t _remaining; // remaining bytes of incoming packet yet to be processed - -public: - EthernetUDP() : sockindex(MAX_SOCK_NUM) {} // Constructor - virtual uint8_t begin(uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use - virtual uint8_t beginMulticast(IPAddress, uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use - virtual void stop(); // Finish with the UDP socket - - // Sending UDP packets - - // Start building up a packet to send to the remote host specific in ip and port - // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port - virtual int beginPacket(IPAddress ip, uint16_t port); - // Start building up a packet to send to the remote host specific in host and port - // Returns 1 if successful, 0 if there was a problem resolving the hostname or port - virtual int beginPacket(const char *host, uint16_t port); - // Finish off this packet and send it - // Returns 1 if the packet was sent successfully, 0 if there was an error - virtual int endPacket(); - // Write a single byte into the packet - virtual size_t write(uint8_t); - // Write size bytes from buffer into the packet - virtual size_t write(const uint8_t *buffer, size_t size); - - using Print::write; - - // Start processing the next available incoming packet - // Returns the size of the packet in bytes, or 0 if no packets are available - virtual int parsePacket(); - // Number of bytes remaining in the current packet - virtual int available(); - // Read a single byte from the current packet - virtual int read(); - // Read up to len bytes from the current packet and place them into buffer - // Returns the number of bytes read, or 0 if none are available - virtual int read(unsigned char* buffer, size_t len); - // Read up to len characters from the current packet and place them into buffer - // Returns the number of characters read, or 0 if none are available - virtual int read(char* buffer, size_t len) { return read((unsigned char*)buffer, len); }; - // Return the next byte from the current packet without moving on to the next byte - virtual int peek(); - virtual void flush(); // Finish reading the current packet - - // Return the IP address of the host who sent the current incoming packet - virtual IPAddress remoteIP() { return _remoteIP; }; - // Return the port of the host who sent the current incoming packet - virtual uint16_t remotePort() { return _remotePort; }; - virtual uint16_t localPort() { return _port; } +class EthernetUDP : public UDP +{ + private: + uint16_t _port; // local port to listen on + IPAddress _remoteIP; // remote IP address for the incoming packet whilst it's being processed + uint16_t _remotePort; // remote port for the incoming packet whilst it's being processed + uint16_t _offset; // offset into the packet being sent + + protected: + uint8_t sockindex; + uint16_t _remaining; // remaining bytes of incoming packet yet to be processed + + public: + EthernetUDP() : sockindex(MAX_SOCK_NUM) {} // Constructor + virtual uint8_t begin( + uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use + virtual uint8_t beginMulticast(IPAddress, + uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use + virtual void stop(); // Finish with the UDP socket + + // Sending UDP packets + + // Start building up a packet to send to the remote host specific in ip and port + // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port + virtual int beginPacket(IPAddress ip, uint16_t port); + // Start building up a packet to send to the remote host specific in host and port + // Returns 1 if successful, 0 if there was a problem resolving the hostname or port + virtual int beginPacket(const char *host, uint16_t port); + // Finish off this packet and send it + // Returns 1 if the packet was sent successfully, 0 if there was an error + virtual int endPacket(); + // Write a single byte into the packet + virtual size_t write(uint8_t); + // Write size bytes from buffer into the packet + virtual size_t write(const uint8_t *buffer, size_t size); + + using Print::write; + + // Start processing the next available incoming packet + // Returns the size of the packet in bytes, or 0 if no packets are available + virtual int parsePacket(); + // Number of bytes remaining in the current packet + virtual int available(); + // Read a single byte from the current packet + virtual int read(); + // Read up to len bytes from the current packet and place them into buffer + // Returns the number of bytes read, or 0 if none are available + virtual int read(unsigned char* buffer, size_t len); + // Read up to len characters from the current packet and place them into buffer + // Returns the number of characters read, or 0 if none are available + virtual int read(char* buffer, size_t len) + { + return read((unsigned char*)buffer, len); + }; + // Return the next byte from the current packet without moving on to the next byte + virtual int peek(); + virtual void flush(); // Finish reading the current packet + + // Return the IP address of the host who sent the current incoming packet + virtual IPAddress remoteIP() + { + return _remoteIP; + }; + // Return the port of the host who sent the current incoming packet + virtual uint16_t remotePort() + { + return _remotePort; + }; + virtual uint16_t localPort() + { + return _port; + } }; -class EthernetClient : public Client { -public: - - EthernetClient() : sockindex(MAX_SOCK_NUM), _timeout(5000) { } - EthernetClient(uint8_t s) : sockindex(s), _timeout(5000) { } - - uint8_t status(); - virtual int connect(IPAddress ip, uint16_t port); - virtual int connect(const char *host, uint16_t port); - virtual int availableForWrite(void); - virtual size_t write(uint8_t); - virtual size_t write(const uint8_t *buf, size_t size); - - virtual int available(); - virtual int read(); - virtual int read(uint8_t *buf, size_t size); - virtual int peek(); - virtual void flush(); - virtual void stop(); - virtual uint8_t connected(); - virtual operator bool() { return sockindex < MAX_SOCK_NUM; } - virtual bool operator==(const bool value) { return bool() == value; } - virtual bool operator!=(const bool value) { return bool() != value; } - virtual bool operator==(const EthernetClient&); - virtual bool operator!=(const EthernetClient& rhs) { return !this->operator==(rhs); } - uint8_t getSocketNumber() const { return sockindex; } - virtual uint16_t localPort(); - virtual IPAddress remoteIP(); - virtual uint16_t remotePort(); - virtual void setConnectionTimeout(uint16_t timeout) { _timeout = timeout; } - - friend class EthernetServer; - - using Print::write; - -private: - uint8_t sockindex; // MAX_SOCK_NUM means client not in use - uint16_t _timeout; +class EthernetClient : public Client +{ + public: + + EthernetClient() : sockindex(MAX_SOCK_NUM), _timeout(5000) { } + EthernetClient(uint8_t s) : sockindex(s), _timeout(5000) { } + + uint8_t status(); + virtual int connect(IPAddress ip, uint16_t port); + virtual int connect(const char *host, uint16_t port); + virtual int availableForWrite(void); + virtual size_t write(uint8_t); + virtual size_t write(const uint8_t *buf, size_t size); + + virtual int available(); + virtual int read(); + virtual int read(uint8_t *buf, size_t size); + virtual int peek(); + virtual void flush(); + virtual void stop(); + virtual uint8_t connected(); + virtual operator bool() + { + return sockindex < MAX_SOCK_NUM; + } + virtual bool operator==(const bool value) + { + return bool() == value; + } + virtual bool operator!=(const bool value) + { + return bool() != value; + } + virtual bool operator==(const EthernetClient&); + virtual bool operator!=(const EthernetClient& rhs) + { + return !this->operator==(rhs); + } + uint8_t getSocketNumber() const + { + return sockindex; + } + virtual uint16_t localPort(); + virtual IPAddress remoteIP(); + virtual uint16_t remotePort(); + virtual void setConnectionTimeout(uint16_t timeout) + { + _timeout = timeout; + } + + friend class EthernetServer; + + using Print::write; + + private: + uint8_t sockindex; // MAX_SOCK_NUM means client not in use + uint16_t _timeout; }; -class EthernetServer : public Server { -private: - uint16_t _port; -public: - EthernetServer(uint16_t port) : _port(port) { } - EthernetClient available(); - EthernetClient accept(); - virtual void begin(); - virtual size_t write(uint8_t); - virtual size_t write(const uint8_t *buf, size_t size); - virtual operator bool(); - using Print::write; - //void statusreport(); - - // TODO: make private when socket allocation moves to EthernetClass - static uint16_t server_port[MAX_SOCK_NUM]; +class EthernetServer : public Server +{ + private: + uint16_t _port; + public: + EthernetServer(uint16_t port) : _port(port) { } + EthernetClient available(); + EthernetClient accept(); + virtual void begin(); + virtual size_t write(uint8_t); + virtual size_t write(const uint8_t *buf, size_t size); + virtual operator bool(); + using Print::write; + //void statusreport(); + + // TODO: make private when socket allocation moves to EthernetClass + static uint16_t server_port[MAX_SOCK_NUM]; }; -class DhcpClass { -private: - uint32_t _dhcpInitialTransactionId; - uint32_t _dhcpTransactionId; - uint8_t _dhcpMacAddr[6]; +class DhcpClass +{ + private: + uint32_t _dhcpInitialTransactionId; + uint32_t _dhcpTransactionId; + uint8_t _dhcpMacAddr[6]; #ifdef __arm__ - uint8_t _dhcpLocalIp[4] __attribute__((aligned(4))); - uint8_t _dhcpSubnetMask[4] __attribute__((aligned(4))); - uint8_t _dhcpGatewayIp[4] __attribute__((aligned(4))); - uint8_t _dhcpDhcpServerIp[4] __attribute__((aligned(4))); - uint8_t _dhcpDnsServerIp[4] __attribute__((aligned(4))); + uint8_t _dhcpLocalIp[4] __attribute__((aligned(4))); + uint8_t _dhcpSubnetMask[4] __attribute__((aligned(4))); + uint8_t _dhcpGatewayIp[4] __attribute__((aligned(4))); + uint8_t _dhcpDhcpServerIp[4] __attribute__((aligned(4))); + uint8_t _dhcpDnsServerIp[4] __attribute__((aligned(4))); #else - uint8_t _dhcpLocalIp[4]; - uint8_t _dhcpSubnetMask[4]; - uint8_t _dhcpGatewayIp[4]; - uint8_t _dhcpDhcpServerIp[4]; - uint8_t _dhcpDnsServerIp[4]; + uint8_t _dhcpLocalIp[4]; + uint8_t _dhcpSubnetMask[4]; + uint8_t _dhcpGatewayIp[4]; + uint8_t _dhcpDhcpServerIp[4]; + uint8_t _dhcpDnsServerIp[4]; #endif - uint32_t _dhcpLeaseTime; - uint32_t _dhcpT1, _dhcpT2; - uint32_t _renewInSec; - uint32_t _rebindInSec; - unsigned long _timeout; - unsigned long _responseTimeout; - unsigned long _lastCheckLeaseMillis; - uint8_t _dhcp_state; - EthernetUDP _dhcpUdpSocket; - - int request_DHCP_lease(); - void reset_DHCP_lease(); - void presend_DHCP(); - void send_DHCP_MESSAGE(uint8_t, uint16_t); - void printByte(char *, uint8_t); - - uint8_t parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId); -public: - IPAddress getLocalIp(); - IPAddress getSubnetMask(); - IPAddress getGatewayIp(); - IPAddress getDhcpServerIp(); - IPAddress getDnsServerIp(); - - int beginWithDHCP(uint8_t *, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); - int checkLease(); + uint32_t _dhcpLeaseTime; + uint32_t _dhcpT1, _dhcpT2; + uint32_t _renewInSec; + uint32_t _rebindInSec; + unsigned long _timeout; + unsigned long _responseTimeout; + unsigned long _lastCheckLeaseMillis; + uint8_t _dhcp_state; + EthernetUDP _dhcpUdpSocket; + + int request_DHCP_lease(); + void reset_DHCP_lease(); + void presend_DHCP(); + void send_DHCP_MESSAGE(uint8_t, uint16_t); + void printByte(char *, uint8_t); + + uint8_t parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId); + public: + IPAddress getLocalIp(); + IPAddress getSubnetMask(); + IPAddress getGatewayIp(); + IPAddress getDhcpServerIp(); + IPAddress getDnsServerIp(); + + int beginWithDHCP(uint8_t *, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); + int checkLease(); }; #endif diff --git a/LibraryPatches/Ethernet/src/EthernetServer.cpp b/LibraryPatches/Ethernet/src/EthernetServer.cpp index 2f6b8fb..343b50f 100644 --- a/LibraryPatches/Ethernet/src/EthernetServer.cpp +++ b/LibraryPatches/Ethernet/src/EthernetServer.cpp @@ -9,17 +9,17 @@ Version: 1.0.9 Copyright 2018 Paul Stoffregen - + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -34,11 +34,11 @@ 1.0.2 K Hoang 20/02/2020 Add support to UIPEthernet library for ENC28J60 1.0.3 K Hoang 23/02/2020 Add support to SAM DUE / SAMD21 boards 1.0.4 K Hoang 16/04/2020 Add support to SAMD51 boards - 1.0.5 K Hoang 24/04/2020 Add support to nRF52 boards, such as AdaFruit Feather nRF52832, nRF52840 Express, BlueFruit Sense, - Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B30_ublox, etc. + 1.0.5 K Hoang 24/04/2020 Add support to nRF52 boards, such as AdaFruit Feather nRF52832, nRF52840 Express, BlueFruit Sense, + Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B30_ublox, etc. More Custom Ethernet libraries supported such as Ethernet2, Ethernet3, EthernetLarge - 1.0.6 K Hoang 27/04/2020 Add support to ESP32/ESP8266 boards - 1.0.7 K Hoang 30/04/2020 Add ENC28J60 support to ESP32/ESP8266 boards + 1.0.6 K Hoang 27/04/2020 Add support to ESP32/ESP8266 boards + 1.0.7 K Hoang 30/04/2020 Add ENC28J60 support to ESP32/ESP8266 boards 1.0.8 K Hoang 12/05/2020 Fix W5x00 support for ESP8266 boards. 1.0.9 K Hoang 15/05/2020 Add EthernetWrapper.h for easier W5x00 support as well as more Ethernet libs in the future. *****************************************************************************************************************************/ @@ -52,193 +52,199 @@ uint16_t EthernetServer::server_port[MAX_SOCK_NUM]; void EthernetServer::begin() { - uint8_t sockindex = Ethernet.socketBegin(SnMR::TCP, _port); - if (sockindex < MAX_SOCK_NUM) - { - if (Ethernet.socketListen(sockindex)) - { - server_port[sockindex] = _port; - } - else - { - Ethernet.socketDisconnect(sockindex); - } - } + uint8_t sockindex = Ethernet.socketBegin(SnMR::TCP, _port); + + if (sockindex < MAX_SOCK_NUM) + { + if (Ethernet.socketListen(sockindex)) + { + server_port[sockindex] = _port; + } + else + { + Ethernet.socketDisconnect(sockindex); + } + } } EthernetClient EthernetServer::available() { - bool listening = false; - uint8_t sockindex = MAX_SOCK_NUM; - uint8_t chip, maxindex=MAX_SOCK_NUM; - - chip = W5100.getChip(); - - if (!chip) - return EthernetClient(MAX_SOCK_NUM); - - //KH, set W5100 to max 2 sockets to increase buffer size - if (chip == 51) - { + bool listening = false; + uint8_t sockindex = MAX_SOCK_NUM; + uint8_t chip, maxindex = MAX_SOCK_NUM; + + chip = W5100.getChip(); + + if (!chip) + return EthernetClient(MAX_SOCK_NUM); + + //KH, set W5100 to max 2 sockets to increase buffer size + if (chip == 51) + { #ifdef ETHERNET_LARGE_BUFFERS - maxindex = 2; // W5100 chip never supports more than 4 sockets -#else - maxindex = 4; // W5100 chip never supports more than 4 sockets. Original -#endif - } - - for (uint8_t i=0; i < maxindex; i++) - { - if (server_port[i] == _port) - { - uint8_t stat = Ethernet.socketStatus(i); - if (stat == SnSR::ESTABLISHED || stat == SnSR::CLOSE_WAIT) - { - if (Ethernet.socketRecvAvailable(i) > 0) - { - sockindex = i; - } - else - { - // remote host closed connection, our end still open - if (stat == SnSR::CLOSE_WAIT) - { - Ethernet.socketDisconnect(i); - // status becomes LAST_ACK for short time - } - } - } - else if (stat == SnSR::LISTEN) - { - listening = true; - } - else if (stat == SnSR::CLOSED) - { - server_port[i] = 0; - } - } - } - - if (!listening) - { - begin(); - } - - return EthernetClient(sockindex); + maxindex = 2; // W5100 chip never supports more than 4 sockets +#else + maxindex = 4; // W5100 chip never supports more than 4 sockets. Original +#endif + } + + for (uint8_t i = 0; i < maxindex; i++) + { + if (server_port[i] == _port) + { + uint8_t stat = Ethernet.socketStatus(i); + + if (stat == SnSR::ESTABLISHED || stat == SnSR::CLOSE_WAIT) + { + if (Ethernet.socketRecvAvailable(i) > 0) + { + sockindex = i; + } + else + { + // remote host closed connection, our end still open + if (stat == SnSR::CLOSE_WAIT) + { + Ethernet.socketDisconnect(i); + // status becomes LAST_ACK for short time + } + } + } + else if (stat == SnSR::LISTEN) + { + listening = true; + } + else if (stat == SnSR::CLOSED) + { + server_port[i] = 0; + } + } + } + + if (!listening) + { + begin(); + } + + return EthernetClient(sockindex); } EthernetClient EthernetServer::accept() { - bool listening = false; - uint8_t sockindex = MAX_SOCK_NUM; - uint8_t chip, maxindex=MAX_SOCK_NUM; + bool listening = false; + uint8_t sockindex = MAX_SOCK_NUM; + uint8_t chip, maxindex = MAX_SOCK_NUM; + + chip = W5100.getChip(); - chip = W5100.getChip(); - - if (!chip) - return EthernetClient(MAX_SOCK_NUM); + if (!chip) + return EthernetClient(MAX_SOCK_NUM); //KH, set W5100 to max 2 sockets to increase buffer size - if (chip == 51) - { + if (chip == 51) + { #ifdef ETHERNET_LARGE_BUFFERS - maxindex = 2; // W5100 chip never supports more than 4 sockets -#else - maxindex = 4; // W5100 chip never supports more than 4 sockets. Original -#endif - } - - for (uint8_t i=0; i < maxindex; i++) - { - if (server_port[i] == _port) - { - uint8_t stat = Ethernet.socketStatus(i); - - if (sockindex == MAX_SOCK_NUM && (stat == SnSR::ESTABLISHED || stat == SnSR::CLOSE_WAIT)) - { - // Return the connected client even if no data received. - // Some protocols like FTP expect the server to send the - // first data. - sockindex = i; - server_port[i] = 0; // only return the client once - } - else if (stat == SnSR::LISTEN) + maxindex = 2; // W5100 chip never supports more than 4 sockets +#else + maxindex = 4; // W5100 chip never supports more than 4 sockets. Original +#endif + } + + for (uint8_t i = 0; i < maxindex; i++) + { + if (server_port[i] == _port) + { + uint8_t stat = Ethernet.socketStatus(i); + + if (sockindex == MAX_SOCK_NUM && (stat == SnSR::ESTABLISHED || stat == SnSR::CLOSE_WAIT)) + { + // Return the connected client even if no data received. + // Some protocols like FTP expect the server to send the + // first data. + sockindex = i; + server_port[i] = 0; // only return the client once + } + else if (stat == SnSR::LISTEN) { - listening = true; - } - else if (stat == SnSR::CLOSED) - { - server_port[i] = 0; - } - } - } - - if (!listening) - begin(); - - return EthernetClient(sockindex); + listening = true; + } + else if (stat == SnSR::CLOSED) + { + server_port[i] = 0; + } + } + } + + if (!listening) + begin(); + + return EthernetClient(sockindex); } EthernetServer::operator bool() { - uint8_t maxindex=MAX_SOCK_NUM; + uint8_t maxindex = MAX_SOCK_NUM; //KH, set W5100 to max 2 sockets to increase buffer size - if (W5100.getChip() == 51) - { + if (W5100.getChip() == 51) + { #ifdef ETHERNET_LARGE_BUFFERS - maxindex = 2; // W5100 chip never supports more than 4 sockets -#else - maxindex = 4; // W5100 chip never supports more than 4 sockets. Original -#endif - } - - for (uint8_t i=0; i < maxindex; i++) - { - if (server_port[i] == _port) - { - if (Ethernet.socketStatus(i) == SnSR::LISTEN) - { - return true; // server is listening for incoming clients - } - } - } - return false; + maxindex = 2; // W5100 chip never supports more than 4 sockets +#else + maxindex = 4; // W5100 chip never supports more than 4 sockets. Original +#endif + } + + for (uint8_t i = 0; i < maxindex; i++) + { + if (server_port[i] == _port) + { + if (Ethernet.socketStatus(i) == SnSR::LISTEN) + { + return true; // server is listening for incoming clients + } + } + } + + return false; } size_t EthernetServer::write(uint8_t b) { - return write(&b, 1); + return write(&b, 1); } size_t EthernetServer::write(const uint8_t *buffer, size_t size) { - uint8_t chip, maxindex=MAX_SOCK_NUM; + uint8_t chip, maxindex = MAX_SOCK_NUM; + + chip = W5100.getChip(); - chip = W5100.getChip(); - if (!chip) return 0; + if (!chip) + return 0; //KH, set W5100 to max 2 sockets to increase buffer size - if (chip == 51) - { + if (chip == 51) + { #ifdef ETHERNET_LARGE_BUFFERS - maxindex = 2; // W5100 chip never supports more than 4 sockets -#else - maxindex = 4; // W5100 chip never supports more than 4 sockets. Original -#endif - } - - available(); - - for (uint8_t i=0; i < maxindex; i++) - { - if (server_port[i] == _port) - { - if (Ethernet.socketStatus(i) == SnSR::ESTABLISHED) - { - Ethernet.socketSend(i, buffer, size); - } - } - } - return size; + maxindex = 2; // W5100 chip never supports more than 4 sockets +#else + maxindex = 4; // W5100 chip never supports more than 4 sockets. Original +#endif + } + + available(); + + for (uint8_t i = 0; i < maxindex; i++) + { + if (server_port[i] == _port) + { + if (Ethernet.socketStatus(i) == SnSR::ESTABLISHED) + { + Ethernet.socketSend(i, buffer, size); + } + } + } + + return size; } diff --git a/LibraryPatches/Ethernet/src/utility/w5100.cpp b/LibraryPatches/Ethernet/src/utility/w5100.cpp index 5cf9cf7..88e6997 100644 --- a/LibraryPatches/Ethernet/src/utility/w5100.cpp +++ b/LibraryPatches/Ethernet/src/utility/w5100.cpp @@ -9,17 +9,17 @@ Version: 1.0.9 Copyright 2018 Paul Stoffregen - + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -34,13 +34,13 @@ 1.0.2 K Hoang 20/02/2020 Add support to UIPEthernet library for ENC28J60 1.0.3 K Hoang 23/02/2020 Add support to SAM DUE / SAMD21 boards 1.0.4 K Hoang 16/04/2020 Add support to SAMD51 boards - 1.0.5 K Hoang 24/04/2020 Add support to nRF52 boards, such as AdaFruit Feather nRF52832, nRF52840 Express, BlueFruit Sense, - Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B30_ublox, etc. + 1.0.5 K Hoang 24/04/2020 Add support to nRF52 boards, such as AdaFruit Feather nRF52832, nRF52840 Express, BlueFruit Sense, + Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B30_ublox, etc. More Custom Ethernet libraries supported such as Ethernet2, Ethernet3, EthernetLarge - 1.0.6 K Hoang 27/04/2020 Add support to ESP32/ESP8266 boards - 1.0.7 K Hoang 30/04/2020 Add ENC28J60 support to ESP32/ESP8266 boards + 1.0.6 K Hoang 27/04/2020 Add support to ESP32/ESP8266 boards + 1.0.7 K Hoang 30/04/2020 Add ENC28J60 support to ESP32/ESP8266 boards 1.0.8 K Hoang 12/05/2020 Fix W5x00 support for ESP8266 boards. - 1.0.9 K Hoang 15/05/2020 Add EthernetWrapper.h for easier W5x00 support as well as more Ethernet libs in the future. + 1.0.9 K Hoang 15/05/2020 Add EthernetWrapper.h for easier W5x00 support as well as more Ethernet libs in the future. *****************************************************************************************************************************/ #include @@ -57,71 +57,71 @@ // default SS pin for ethernet, use it. #if defined(PIN_SPI_SS_ETHERNET_LIB) -#define SS_PIN_DEFAULT PIN_SPI_SS_ETHERNET_LIB -//KH -#warning w5100.cpp Use PIN_SPI_SS_ETHERNET_LIB defined, change SS_PIN_DEFAULT to PIN_SPI_SS_ETHERNET_LIB + #define SS_PIN_DEFAULT PIN_SPI_SS_ETHERNET_LIB + //KH + #warning w5100.cpp Use PIN_SPI_SS_ETHERNET_LIB defined, change SS_PIN_DEFAULT to PIN_SPI_SS_ETHERNET_LIB -// MKR boards default to pin 5 for MKR ETH -// Pins 8-10 are MOSI/SCK/MISO on MRK, so don't use pin 10 + // MKR boards default to pin 5 for MKR ETH + // Pins 8-10 are MOSI/SCK/MISO on MRK, so don't use pin 10 #elif defined(USE_ARDUINO_MKR_PIN_LAYOUT) || defined(ARDUINO_SAMD_MKRZERO) || defined(ARDUINO_SAMD_MKR1000) || defined(ARDUINO_SAMD_MKRFox1200) || defined(ARDUINO_SAMD_MKRGSM1400) || defined(ARDUINO_SAMD_MKRWAN1300) -#define SS_PIN_DEFAULT 5 -//KH -#warning w5100.cpp Use MKR, change SS_PIN_DEFAULT to 5 + #define SS_PIN_DEFAULT 5 + //KH + #warning w5100.cpp Use MKR, change SS_PIN_DEFAULT to 5 -// For boards using AVR, assume shields with SS on pin 10 -// will be used. This allows for Arduino Mega (where -// SS is pin 53) and Arduino Leonardo (where SS is pin 17) -// to work by default with Arduino Ethernet Shield R2 & R3. + // For boards using AVR, assume shields with SS on pin 10 + // will be used. This allows for Arduino Mega (where + // SS is pin 53) and Arduino Leonardo (where SS is pin 17) + // to work by default with Arduino Ethernet Shield R2 & R3. #elif defined(__AVR__) -#define SS_PIN_DEFAULT 10 -//KH -#warning w5100.cpp Use __AVR__, change SS_PIN_DEFAULT to 10 + #define SS_PIN_DEFAULT 10 + //KH + #warning w5100.cpp Use __AVR__, change SS_PIN_DEFAULT to 10 -// If variant.h or other headers define these names -// use them if none of the other cases match + // If variant.h or other headers define these names + // use them if none of the other cases match #elif defined(PIN_SPI_SS) -#if defined(__SAMD21G18A__) -//10 - 2 (6 conflict) all not OK for Nano 33 IoT !!! SPI corrupted??? -#warning w5100.cpp Use __SAMD21G18A__, change SS_PIN_DEFAULT to 10 -#define SS_PIN_DEFAULT 10 -#else -#define SS_PIN_DEFAULT PIN_SPI_SS + #if defined(__SAMD21G18A__) + //10 - 2 (6 conflict) all not OK for Nano 33 IoT !!! SPI corrupted??? + #warning w5100.cpp Use __SAMD21G18A__, change SS_PIN_DEFAULT to 10 + #define SS_PIN_DEFAULT 10 + #else + #define SS_PIN_DEFAULT PIN_SPI_SS -//KH -#warning w5100.cpp Use PIN_SPI_SS defined, change SS_PIN_DEFAULT to PIN_SPI_SS -#endif + //KH + #warning w5100.cpp Use PIN_SPI_SS defined, change SS_PIN_DEFAULT to PIN_SPI_SS + #endif #elif defined(CORE_SS0_PIN) -#define SS_PIN_DEFAULT CORE_SS0_PIN + #define SS_PIN_DEFAULT CORE_SS0_PIN -//KH -#warning w5100.cpp Use CORE_SS0_PIN defined, change SS_PIN_DEFAULT to CORE_SS0_PIN + //KH + #warning w5100.cpp Use CORE_SS0_PIN defined, change SS_PIN_DEFAULT to CORE_SS0_PIN -//KH for ESP32 + //KH for ESP32 #elif defined(ESP32) -//pin SS already defined in ESP32 as pin 5, don't use this as conflict with SPIFFS, EEPROM, etc. -// Use in GPIO22 -#warning w5100.cpp Use ESP32, change SS_PIN_DEFAULT to GPIO22, MOSI(23), MISO(19), SCK(18) -#define SS_PIN_DEFAULT 22 //SS -/////// + //pin SS already defined in ESP32 as pin 5, don't use this as conflict with SPIFFS, EEPROM, etc. + // Use in GPIO22 + #warning w5100.cpp Use ESP32, change SS_PIN_DEFAULT to GPIO22, MOSI(23), MISO(19), SCK(18) + #define SS_PIN_DEFAULT 22 //SS + /////// -//KH for ESP8266 + //KH for ESP8266 #elif defined(ESP8266) -//pin SS already defined in ESP8266 as pin 15. Conflict => Move to pin GPIO4 (D2) -#warning w5100.cpp Use ESP8266, change SS_PIN_DEFAULT to SS(4), MOSI(13), MISO(12), SCK(14) -#define SS_PIN_DEFAULT D2 // GPIO4, SS + //pin SS already defined in ESP8266 as pin 15. Conflict => Move to pin GPIO4 (D2) + #warning w5100.cpp Use ESP8266, change SS_PIN_DEFAULT to SS(4), MOSI(13), MISO(12), SCK(14) + #define SS_PIN_DEFAULT D2 // GPIO4, SS -/////// + /////// -// As a final fallback, use pin 10 + // As a final fallback, use pin 10 #else -#define SS_PIN_DEFAULT 10 + #define SS_PIN_DEFAULT 10 -//KH -#warning w5100.cpp Use fallback, change SS_PIN_DEFAULT to 10 + //KH + #warning w5100.cpp Use fallback, change SS_PIN_DEFAULT to 10 #endif @@ -130,8 +130,8 @@ uint8_t W5100Class::chip = 0; uint8_t W5100Class::CH_BASE_MSB; uint8_t W5100Class::ss_pin = SS_PIN_DEFAULT; #ifdef ETHERNET_LARGE_BUFFERS -uint16_t W5100Class::SSIZE = 2048; -uint16_t W5100Class::SMASK = 0x07FF; + uint16_t W5100Class::SSIZE = 2048; + uint16_t W5100Class::SMASK = 0x07FF; #endif W5100Class W5100; @@ -165,547 +165,580 @@ W5100Class W5100; // KH uint8_t W5100Class::init(uint8_t socketNumbers, uint8_t new_ss_pin) { - uint8_t i; - - if (initialized) return 1; - - // Many Ethernet shields have a CAT811 or similar reset chip - // connected to W5100 or W5200 chips. The W5200 will not work at - // all, and may even drive its MISO pin, until given an active low - // reset pulse! The CAT811 has a 240 ms typical pulse length, and - // a 400 ms worst case maximum pulse length. MAX811 has a worst - // case maximum 560 ms pulse length. This delay is meant to wait - // until the reset pulse is ended. If your hardware has a shorter - // reset time, this can be edited or removed. - delay(560); - - //W5100Class::ss_pin = new_ss_pin; - -#if ( W5100_DEBUG > 0 ) - //KH - Serial.print("\nW5100 init, using SS_PIN_DEFAULT = "); - Serial.print(SS_PIN_DEFAULT); - Serial.print(", new ss_pin = "); - Serial.print(new_ss_pin); - Serial.print(", W5100Class::ss_pin = "); - Serial.println(W5100Class::ss_pin); + uint8_t i; + + if (initialized) + return 1; + + // Many Ethernet shields have a CAT811 or similar reset chip + // connected to W5100 or W5200 chips. The W5200 will not work at + // all, and may even drive its MISO pin, until given an active low + // reset pulse! The CAT811 has a 240 ms typical pulse length, and + // a 400 ms worst case maximum pulse length. MAX811 has a worst + // case maximum 560 ms pulse length. This delay is meant to wait + // until the reset pulse is ended. If your hardware has a shorter + // reset time, this can be edited or removed. + delay(560); + + //W5100Class::ss_pin = new_ss_pin; + +#if ( W5100_DEBUG > 0 ) + //KH + Serial.print("\nW5100 init, using SS_PIN_DEFAULT = "); + Serial.print(SS_PIN_DEFAULT); + Serial.print(", new ss_pin = "); + Serial.print(new_ss_pin); + Serial.print(", W5100Class::ss_pin = "); + Serial.println(W5100Class::ss_pin); #endif - - SPI.begin(); - - initSS(); - resetSS(); - - // From #define SPI_ETHERNET_SETTINGS SPISettings(14000000, MSBFIRST, SPI_MODE0) - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - - // Attempt W5200 detection first, because W5200 does not properly - // reset its SPI state when CS goes high (inactive). Communication - // from detecting the other chips can leave the W5200 in a state - // where it won't recover, unless given a reset pulse. - if (isW5200()) - { - CH_BASE_MSB = 0x40; + + SPI.begin(); + + initSS(); + resetSS(); + + // From #define SPI_ETHERNET_SETTINGS SPISettings(14000000, MSBFIRST, SPI_MODE0) + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + + // Attempt W5200 detection first, because W5200 does not properly + // reset its SPI state when CS goes high (inactive). Communication + // from detecting the other chips can leave the W5200 in a state + // where it won't recover, unless given a reset pulse. + if (isW5200()) + { + CH_BASE_MSB = 0x40; #ifdef ETHERNET_LARGE_BUFFERS #if MAX_SOCK_NUM <= 1 - SSIZE = 16384; + SSIZE = 16384; #elif MAX_SOCK_NUM <= 2 - SSIZE = 8192; + SSIZE = 8192; #elif MAX_SOCK_NUM <= 4 - SSIZE = 4096; + SSIZE = 4096; #else - SSIZE = 2048; + SSIZE = 2048; #endif - SMASK = SSIZE - 1; + SMASK = SSIZE - 1; #endif - for (i=0; i> 10); - writeSnTX_SIZE(i, SSIZE >> 10); - } - for (; i<8; i++) - { - writeSnRX_SIZE(i, 0); - writeSnTX_SIZE(i, 0); - } - -#if ( W5100_DEBUG > 0 ) - Serial.print("W5100::init: W5200, SSIZE ="); + + for (i = 0; i < MAX_SOCK_NUM; i++) + { + writeSnRX_SIZE(i, SSIZE >> 10); + writeSnTX_SIZE(i, SSIZE >> 10); + } + + for (; i < 8; i++) + { + writeSnRX_SIZE(i, 0); + writeSnTX_SIZE(i, 0); + } + +#if ( W5100_DEBUG > 0 ) + Serial.print("W5100::init: W5200, SSIZE ="); Serial.println(SSIZE); #endif - - // Try W5500 next. Wiznet finally seems to have implemented - // SPI well with this chip. It appears to be very resilient, - // so try it after the fragile W5200 - } else if (isW5500()) - { - CH_BASE_MSB = 0x10; + + // Try W5500 next. Wiznet finally seems to have implemented + // SPI well with this chip. It appears to be very resilient, + // so try it after the fragile W5200 + } + else if (isW5500()) + { + CH_BASE_MSB = 0x10; #ifdef ETHERNET_LARGE_BUFFERS #if MAX_SOCK_NUM <= 1 - SSIZE = 16384; + SSIZE = 16384; #elif MAX_SOCK_NUM <= 2 - SSIZE = 8192; + SSIZE = 8192; #elif MAX_SOCK_NUM <= 4 - SSIZE = 4096; + SSIZE = 4096; #else - SSIZE = 2048; + SSIZE = 2048; #endif - SMASK = SSIZE - 1; - for (i=0; i> 10); - writeSnTX_SIZE(i, SSIZE >> 10); - } - for (; i<8; i++) - { - writeSnRX_SIZE(i, 0); - writeSnTX_SIZE(i, 0); - } + SMASK = SSIZE - 1; + + for (i = 0; i < MAX_SOCK_NUM; i++) + { + writeSnRX_SIZE(i, SSIZE >> 10); + writeSnTX_SIZE(i, SSIZE >> 10); + } + + for (; i < 8; i++) + { + writeSnRX_SIZE(i, 0); + writeSnTX_SIZE(i, 0); + } + #endif -#if ( W5100_DEBUG > 0 ) +#if ( W5100_DEBUG > 0 ) Serial.print("W5100::init: W5500, SSIZE ="); Serial.println(SSIZE); #endif - - // Try W5100 last. This simple chip uses fixed 4 byte frames - // for every 8 bit access. Terribly inefficient, but so simple - // it recovers from "hearing" unsuccessful W5100 or W5200 - // communication. W5100 is also the only chip without a VERSIONR - // register for identification, so we check this last. - } else if (isW5100()) - { - CH_BASE_MSB = 0x04; + + // Try W5100 last. This simple chip uses fixed 4 byte frames + // for every 8 bit access. Terribly inefficient, but so simple + // it recovers from "hearing" unsuccessful W5100 or W5200 + // communication. W5100 is also the only chip without a VERSIONR + // register for identification, so we check this last. + } + else if (isW5100()) + { + CH_BASE_MSB = 0x04; #ifdef ETHERNET_LARGE_BUFFERS - #if MAX_SOCK_NUM <= 1 - SSIZE = 8192; - writeTMSR(0x03); - writeRMSR(0x03); - #else - SSIZE = 4096; - writeTMSR(0x0A); - writeRMSR(0x0A); - #endif +#if MAX_SOCK_NUM <= 1 + SSIZE = 8192; + writeTMSR(0x03); + writeRMSR(0x03); +#else + SSIZE = 4096; + writeTMSR(0x0A); + writeRMSR(0x0A); +#endif - SMASK = SSIZE - 1; + SMASK = SSIZE - 1; #else - - writeTMSR(0x55); - writeRMSR(0x55); + + writeTMSR(0x55); + writeRMSR(0x55); #endif -#if ( W5100_DEBUG > 0 ) - Serial.print("W5100::init: W5100, SSIZE ="); - Serial.println(SSIZE); +#if ( W5100_DEBUG > 0 ) + Serial.print("W5100::init: W5100, SSIZE ="); + Serial.println(SSIZE); #endif - - // No hardware seems to be present. Or it could be a W5200 - // that's heard other SPI communication if its chip select - // pin wasn't high when a SD card or other SPI chip was used. - } - else - { -#if ( W5100_DEBUG > 0 ) - Serial.println("no chip :-("); + + // No hardware seems to be present. Or it could be a W5200 + // that's heard other SPI communication if its chip select + // pin wasn't high when a SD card or other SPI chip was used. + } + else + { +#if ( W5100_DEBUG > 0 ) + Serial.println("no chip :-("); #endif - - chip = 0; - SPI.endTransaction(); - return 0; // no known chip is responding :-( - } - - SPI.endTransaction(); - initialized = true; - return 1; // successful init + + chip = 0; + SPI.endTransaction(); + return 0; // no known chip is responding :-( + } + + SPI.endTransaction(); + initialized = true; + return 1; // successful init } // Soft reset the Wiznet chip, by writing to its MR register reset bit uint8_t W5100Class::softReset(void) { - uint16_t count=0; + uint16_t count = 0; -#if ( W5100_DEBUG > 1 ) - Serial.println("Wiznet soft reset"); +#if ( W5100_DEBUG > 1 ) + Serial.println("Wiznet soft reset"); #endif - - // write to reset bit - writeMR(0x80); - // then wait for soft reset to complete - do - { - uint8_t mr = readMR(); - -#if ( W5100_DEBUG > 2 ) - Serial.print("mr="); - Serial.println(mr, HEX); + + // write to reset bit + writeMR(0x80); + + // then wait for soft reset to complete + do + { + uint8_t mr = readMR(); + +#if ( W5100_DEBUG > 2 ) + Serial.print("mr="); + Serial.println(mr, HEX); #endif - - if (mr == 0) - return 1; - - delay(1); - } while (++count < 20); - return 0; + + if (mr == 0) + return 1; + + delay(1); + } while (++count < 20); + + return 0; } uint8_t W5100Class::isW5100(void) { - chip = 51; - -#if ( W5100_DEBUG > 1 ) - Serial.println("W5100.cpp: detect W5100 chip"); + chip = 51; + +#if ( W5100_DEBUG > 1 ) + Serial.println("W5100.cpp: detect W5100 chip"); #endif - - if (!softReset()) - return 0; - - writeMR(0x10); - if (readMR() != 0x10) - return 0; - - writeMR(0x12); - if (readMR() != 0x12) - return 0; - - writeMR(0x00); - if (readMR() != 0x00) - return 0; - -#if ( W5100_DEBUG > 1 ) - Serial.println("chip is W5100"); + + if (!softReset()) + return 0; + + writeMR(0x10); + + if (readMR() != 0x10) + return 0; + + writeMR(0x12); + + if (readMR() != 0x12) + return 0; + + writeMR(0x00); + + if (readMR() != 0x00) + return 0; + +#if ( W5100_DEBUG > 1 ) + Serial.println("chip is W5100"); #endif - - return 1; + + return 1; } uint8_t W5100Class::isW5200(void) { - chip = 52; - -#if ( W5100_DEBUG > 1 ) - Serial.println("W5100.cpp: detect W5200 chip"); + chip = 52; + +#if ( W5100_DEBUG > 1 ) + Serial.println("W5100.cpp: detect W5200 chip"); #endif - - if (!softReset()) - return 0; - - writeMR(0x08); - if (readMR() != 0x08) - return 0; - - writeMR(0x10); - if (readMR() != 0x10) - return 0; - - writeMR(0x00); - if (readMR() != 0x00) - return 0; - - int ver = readVERSIONR_W5200(); - -#if ( W5100_DEBUG > 1 ) - Serial.print("version="); - Serial.println(ver); + + if (!softReset()) + return 0; + + writeMR(0x08); + + if (readMR() != 0x08) + return 0; + + writeMR(0x10); + + if (readMR() != 0x10) + return 0; + + writeMR(0x00); + + if (readMR() != 0x00) + return 0; + + int ver = readVERSIONR_W5200(); + +#if ( W5100_DEBUG > 1 ) + Serial.print("version="); + Serial.println(ver); #endif - - if (ver != 3) - return 0; - -#if ( W5100_DEBUG > 1 ) - Serial.println("chip is W5200"); + + if (ver != 3) + return 0; + +#if ( W5100_DEBUG > 1 ) + Serial.println("chip is W5200"); #endif - - return 1; + + return 1; } uint8_t W5100Class::isW5500(void) { - chip = 55; - -#if ( W5100_DEBUG > 1 ) - Serial.println("W5100.cpp: detect W5500 chip"); + chip = 55; + +#if ( W5100_DEBUG > 1 ) + Serial.println("W5100.cpp: detect W5500 chip"); #endif - - if (!softReset()) - return 0; - - writeMR(0x08); - if (readMR() != 0x08) - return 0; - - writeMR(0x10); - if (readMR() != 0x10) - return 0; - - writeMR(0x00); - if (readMR() != 0x00) - return 0; - - int ver = readVERSIONR_W5500(); - -#if ( W5100_DEBUG > 1 ) - Serial.print("version="); - Serial.println(ver); + + if (!softReset()) + return 0; + + writeMR(0x08); + + if (readMR() != 0x08) + return 0; + + writeMR(0x10); + + if (readMR() != 0x10) + return 0; + + writeMR(0x00); + + if (readMR() != 0x00) + return 0; + + int ver = readVERSIONR_W5500(); + +#if ( W5100_DEBUG > 1 ) + Serial.print("version="); + Serial.println(ver); #endif - - if (ver != 4) - return 0; - -#if ( W5100_DEBUG > 1 ) - Serial.println("chip is W5500"); + + if (ver != 4) + return 0; + +#if ( W5100_DEBUG > 1 ) + Serial.println("chip is W5500"); #endif - return 1; + return 1; } W5100Linkstatus W5100Class::getLinkStatus() { - uint8_t phystatus; - - // KH - if (!initialized) return UNKNOWN; - - switch (chip) - { - case 52: - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - phystatus = readPSTATUS_W5200(); - SPI.endTransaction(); - if (phystatus & 0x20) - return LINK_ON; - - return LINK_OFF; - - case 55: - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - phystatus = readPHYCFGR_W5500(); - SPI.endTransaction(); - if (phystatus & 0x01) - return LINK_ON; - - return LINK_OFF; - - default: - return UNKNOWN; - } + uint8_t phystatus; + + // KH + if (!initialized) + return UNKNOWN; + + switch (chip) + { + case 52: + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + phystatus = readPSTATUS_W5200(); + SPI.endTransaction(); + + if (phystatus & 0x20) + return LINK_ON; + + return LINK_OFF; + + case 55: + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + phystatus = readPHYCFGR_W5500(); + SPI.endTransaction(); + + if (phystatus & 0x01) + return LINK_ON; + + return LINK_OFF; + + default: + return UNKNOWN; + } } uint16_t W5100Class::write(uint16_t addr, const uint8_t *buf, uint16_t len) { - uint8_t cmd[8]; - - if (chip == 51) - { - for (uint16_t i=0; i> 8); - SPI.transfer(addr & 0xFF); - addr++; - SPI.transfer(buf[i]); - resetSS(); - } - } - else if (chip == 52) - { - setSS(); - cmd[0] = addr >> 8; - cmd[1] = addr & 0xFF; - cmd[2] = ((len >> 8) & 0x7F) | 0x80; - cmd[3] = len & 0xFF; - SPI.transfer(cmd, 4); - + uint8_t cmd[8]; + + if (chip == 51) + { + for (uint16_t i = 0; i < len; i++) + { + setSS(); + SPI.transfer(0xF0); + SPI.transfer(addr >> 8); + SPI.transfer(addr & 0xFF); + addr++; + SPI.transfer(buf[i]); + resetSS(); + } + } + else if (chip == 52) + { + setSS(); + cmd[0] = addr >> 8; + cmd[1] = addr & 0xFF; + cmd[2] = ((len >> 8) & 0x7F) | 0x80; + cmd[3] = len & 0xFF; + SPI.transfer(cmd, 4); + #ifdef SPI_HAS_TRANSFER_BUF - SPI.transfer(buf, NULL, len); + SPI.transfer(buf, NULL, len); +#else + + // TODO: copy 8 bytes at a time to cmd[] and block transfer + for (uint16_t i = 0; i < len; i++) + { + SPI.transfer(buf[i]); + } + +#endif + resetSS(); + } + else + { + // chip == 55 + setSS(); + + if (addr < 0x100) + { + // common registers 00nn + cmd[0] = 0; + cmd[1] = addr & 0xFF; + cmd[2] = 0x04; + } + else if (addr < 0x8000) + { + // socket registers 10nn, 11nn, 12nn, 13nn, etc + cmd[0] = 0; + cmd[1] = addr & 0xFF; + cmd[2] = ((addr >> 3) & 0xE0) | 0x0C; + } + else if (addr < 0xC000) + { + // transmit buffers 8000-87FF, 8800-8FFF, 9000-97FF, etc + // 10## #nnn nnnn nnnn + cmd[0] = addr >> 8; + cmd[1] = addr & 0xFF; +#if defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 1 + cmd[2] = 0x14; // 16K buffers +#elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 2 + cmd[2] = ((addr >> 8) & 0x20) | 0x14; // 8K buffers +#elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 4 + cmd[2] = ((addr >> 7) & 0x60) | 0x14; // 4K buffers #else - // TODO: copy 8 bytes at a time to cmd[] and block transfer - for (uint16_t i=0; i < len; i++) - { - SPI.transfer(buf[i]); - } + cmd[2] = ((addr >> 6) & 0xE0) | 0x14; // 2K buffers #endif - resetSS(); - } - else - { - // chip == 55 - setSS(); - if (addr < 0x100) - { - // common registers 00nn - cmd[0] = 0; - cmd[1] = addr & 0xFF; - cmd[2] = 0x04; - } - else if (addr < 0x8000) - { - // socket registers 10nn, 11nn, 12nn, 13nn, etc - cmd[0] = 0; - cmd[1] = addr & 0xFF; - cmd[2] = ((addr >> 3) & 0xE0) | 0x0C; - } - else if (addr < 0xC000) - { - // transmit buffers 8000-87FF, 8800-8FFF, 9000-97FF, etc - // 10## #nnn nnnn nnnn - cmd[0] = addr >> 8; - cmd[1] = addr & 0xFF; - #if defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 1 - cmd[2] = 0x14; // 16K buffers - #elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 2 - cmd[2] = ((addr >> 8) & 0x20) | 0x14; // 8K buffers - #elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 4 - cmd[2] = ((addr >> 7) & 0x60) | 0x14; // 4K buffers - #else - cmd[2] = ((addr >> 6) & 0xE0) | 0x14; // 2K buffers - #endif - } - else - { - // receive buffers - cmd[0] = addr >> 8; - cmd[1] = addr & 0xFF; - #if defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 1 - cmd[2] = 0x1C; // 16K buffers - #elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 2 - cmd[2] = ((addr >> 8) & 0x20) | 0x1C; // 8K buffers - #elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 4 - cmd[2] = ((addr >> 7) & 0x60) | 0x1C; // 4K buffers - #else - cmd[2] = ((addr >> 6) & 0xE0) | 0x1C; // 2K buffers - #endif - } - - if (len <= 5) - { - for (uint8_t i=0; i < len; i++) - { - cmd[i + 3] = buf[i]; - } - - SPI.transfer(cmd, len + 3); - } - else - { - SPI.transfer(cmd, 3); + } + else + { + // receive buffers + cmd[0] = addr >> 8; + cmd[1] = addr & 0xFF; +#if defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 1 + cmd[2] = 0x1C; // 16K buffers +#elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 2 + cmd[2] = ((addr >> 8) & 0x20) | 0x1C; // 8K buffers +#elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 4 + cmd[2] = ((addr >> 7) & 0x60) | 0x1C; // 4K buffers +#else + cmd[2] = ((addr >> 6) & 0xE0) | 0x1C; // 2K buffers +#endif + } + + if (len <= 5) + { + for (uint8_t i = 0; i < len; i++) + { + cmd[i + 3] = buf[i]; + } + + SPI.transfer(cmd, len + 3); + } + else + { + SPI.transfer(cmd, 3); #ifdef SPI_HAS_TRANSFER_BUF - SPI.transfer(buf, NULL, len); + SPI.transfer(buf, NULL, len); #else - // TODO: copy 8 bytes at a time to cmd[] and block transfer - for (uint16_t i=0; i < len; i++) - { - SPI.transfer(buf[i]); - } + + // TODO: copy 8 bytes at a time to cmd[] and block transfer + for (uint16_t i = 0; i < len; i++) + { + SPI.transfer(buf[i]); + } + #endif - } - resetSS(); - } - return len; + } + + resetSS(); + } + + return len; } uint16_t W5100Class::read(uint16_t addr, uint8_t *buf, uint16_t len) { - uint8_t cmd[4]; - - if (chip == 51) - { - for (uint16_t i=0; i < len; i++) - { - setSS(); - #if 1 - SPI.transfer(0x0F); - SPI.transfer(addr >> 8); - SPI.transfer(addr & 0xFF); - addr++; - buf[i] = SPI.transfer(0); - #else - cmd[0] = 0x0F; - cmd[1] = addr >> 8; - cmd[2] = addr & 0xFF; - cmd[3] = 0; - SPI.transfer(cmd, 4); // TODO: why doesn't this work? - buf[i] = cmd[3]; - addr++; - #endif - resetSS(); - } - } - else if (chip == 52) - { - setSS(); - cmd[0] = addr >> 8; - cmd[1] = addr & 0xFF; - cmd[2] = (len >> 8) & 0x7F; - cmd[3] = len & 0xFF; - SPI.transfer(cmd, 4); - memset(buf, 0, len); - SPI.transfer(buf, len); - resetSS(); - } - else - { - // chip == 55 - setSS(); - - if (addr < 0x100) - { - // common registers 00nn - cmd[0] = 0; - cmd[1] = addr & 0xFF; - cmd[2] = 0x00; - } - else if (addr < 0x8000) - { - // socket registers 10nn, 11nn, 12nn, 13nn, etc - cmd[0] = 0; - cmd[1] = addr & 0xFF; - cmd[2] = ((addr >> 3) & 0xE0) | 0x08; - } - else if (addr < 0xC000) - { - // transmit buffers 8000-87FF, 8800-8FFF, 9000-97FF, etc - // 10## #nnn nnnn nnnn - cmd[0] = addr >> 8; - cmd[1] = addr & 0xFF; - #if defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 1 - cmd[2] = 0x10; // 16K buffers - #elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 2 - cmd[2] = ((addr >> 8) & 0x20) | 0x10; // 8K buffers - #elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 4 - cmd[2] = ((addr >> 7) & 0x60) | 0x10; // 4K buffers - #else - cmd[2] = ((addr >> 6) & 0xE0) | 0x10; // 2K buffers - #endif - } else - { - // receive buffers - cmd[0] = addr >> 8; - cmd[1] = addr & 0xFF; - #if defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 1 - cmd[2] = 0x18; // 16K buffers - #elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 2 - cmd[2] = ((addr >> 8) & 0x20) | 0x18; // 8K buffers - #elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 4 - cmd[2] = ((addr >> 7) & 0x60) | 0x18; // 4K buffers - #else - cmd[2] = ((addr >> 6) & 0xE0) | 0x18; // 2K buffers - #endif - } - SPI.transfer(cmd, 3); - memset(buf, 0, len); - SPI.transfer(buf, len); - resetSS(); - } - return len; + uint8_t cmd[4]; + + if (chip == 51) + { + for (uint16_t i = 0; i < len; i++) + { + setSS(); +#if 1 + SPI.transfer(0x0F); + SPI.transfer(addr >> 8); + SPI.transfer(addr & 0xFF); + addr++; + buf[i] = SPI.transfer(0); +#else + cmd[0] = 0x0F; + cmd[1] = addr >> 8; + cmd[2] = addr & 0xFF; + cmd[3] = 0; + SPI.transfer(cmd, 4); // TODO: why doesn't this work? + buf[i] = cmd[3]; + addr++; +#endif + resetSS(); + } + } + else if (chip == 52) + { + setSS(); + cmd[0] = addr >> 8; + cmd[1] = addr & 0xFF; + cmd[2] = (len >> 8) & 0x7F; + cmd[3] = len & 0xFF; + SPI.transfer(cmd, 4); + memset(buf, 0, len); + SPI.transfer(buf, len); + resetSS(); + } + else + { + // chip == 55 + setSS(); + + if (addr < 0x100) + { + // common registers 00nn + cmd[0] = 0; + cmd[1] = addr & 0xFF; + cmd[2] = 0x00; + } + else if (addr < 0x8000) + { + // socket registers 10nn, 11nn, 12nn, 13nn, etc + cmd[0] = 0; + cmd[1] = addr & 0xFF; + cmd[2] = ((addr >> 3) & 0xE0) | 0x08; + } + else if (addr < 0xC000) + { + // transmit buffers 8000-87FF, 8800-8FFF, 9000-97FF, etc + // 10## #nnn nnnn nnnn + cmd[0] = addr >> 8; + cmd[1] = addr & 0xFF; +#if defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 1 + cmd[2] = 0x10; // 16K buffers +#elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 2 + cmd[2] = ((addr >> 8) & 0x20) | 0x10; // 8K buffers +#elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 4 + cmd[2] = ((addr >> 7) & 0x60) | 0x10; // 4K buffers +#else + cmd[2] = ((addr >> 6) & 0xE0) | 0x10; // 2K buffers +#endif + } + else + { + // receive buffers + cmd[0] = addr >> 8; + cmd[1] = addr & 0xFF; +#if defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 1 + cmd[2] = 0x18; // 16K buffers +#elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 2 + cmd[2] = ((addr >> 8) & 0x20) | 0x18; // 8K buffers +#elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 4 + cmd[2] = ((addr >> 7) & 0x60) | 0x18; // 4K buffers +#else + cmd[2] = ((addr >> 6) & 0xE0) | 0x18; // 2K buffers +#endif + } + + SPI.transfer(cmd, 3); + memset(buf, 0, len); + SPI.transfer(buf, len); + resetSS(); + } + + return len; } void W5100Class::execCmdSn(SOCKET s, SockCMD _cmd) { - // Send command to socket - writeSnCR(s, _cmd); - // Wait for command to complete - while (readSnCR(s)) ; + // Send command to socket + writeSnCR(s, _cmd); + + // Wait for command to complete + while (readSnCR(s)) ; } diff --git a/LibraryPatches/Ethernet/src/utility/w5100.h b/LibraryPatches/Ethernet/src/utility/w5100.h index 838a49f..fdc4a08 100644 --- a/LibraryPatches/Ethernet/src/utility/w5100.h +++ b/LibraryPatches/Ethernet/src/utility/w5100.h @@ -9,17 +9,17 @@ Version: 1.0.9 Copyright 2018 Paul Stoffregen - + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -34,11 +34,11 @@ 1.0.2 K Hoang 20/02/2020 Add support to UIPEthernet library for ENC28J60 1.0.3 K Hoang 23/02/2020 Add support to SAM DUE / SAMD21 boards 1.0.4 K Hoang 16/04/2020 Add support to SAMD51 boards - 1.0.5 K Hoang 24/04/2020 Add support to nRF52 boards, such as AdaFruit Feather nRF52832, nRF52840 Express, BlueFruit Sense, - Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B30_ublox, etc. + 1.0.5 K Hoang 24/04/2020 Add support to nRF52 boards, such as AdaFruit Feather nRF52832, nRF52840 Express, BlueFruit Sense, + Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B30_ublox, etc. More Custom Ethernet libraries supported such as Ethernet2, Ethernet3, EthernetLarge - 1.0.6 K Hoang 27/04/2020 Add support to ESP32/ESP8266 boards - 1.0.7 K Hoang 30/04/2020 Add ENC28J60 support to ESP32/ESP8266 boards + 1.0.6 K Hoang 27/04/2020 Add support to ESP32/ESP8266 boards + 1.0.7 K Hoang 30/04/2020 Add ENC28J60 support to ESP32/ESP8266 boards 1.0.8 K Hoang 12/05/2020 Fix W5x00 support for ESP8266 boards. 1.0.9 K Hoang 15/05/2020 Add EthernetWrapper.h for easier W5x00 support as well as more Ethernet libs in the future. *****************************************************************************************************************************/ @@ -46,74 +46,76 @@ // w5100.h contains private W5x00 hardware "driver" level definitions // which are not meant to be exposed to other libraries or Arduino users -#ifndef W5100_H_INCLUDED -#define W5100_H_INCLUDED +#ifndef W5100_H_INCLUDED +#define W5100_H_INCLUDED #include #include #ifndef USE_W5100 -#define USE_W5100 false + #define USE_W5100 false #else -#define USE_W5100 true + #define USE_W5100 true #endif #if !USE_W5100 -// Safe for W5200 and W5500, but also tested OK on W5100 -// Use 14MHz if you know your W5100 can't run -// Higher SPI clock results in faster transfer to hosts on a LAN -// or with very low packet latency. With ordinary internet latency, -// the TCP window size & packet loss determine your overall speed. -#warning Use 25MHz clock for W5200/W5500. Not for W5100 -#define SPI_ETHERNET_SETTINGS SPISettings(25000000, MSBFIRST, SPI_MODE0) + // Safe for W5200 and W5500, but also tested OK on W5100 + // Use 14MHz if you know your W5100 can't run + // Higher SPI clock results in faster transfer to hosts on a LAN + // or with very low packet latency. With ordinary internet latency, + // the TCP window size & packet loss determine your overall speed. + #warning Use 25MHz clock for W5200/W5500. Not for W5100 + #define SPI_ETHERNET_SETTINGS SPISettings(25000000, MSBFIRST, SPI_MODE0) #else -// Safe for all chips but too slow -#define SPI_ETHERNET_SETTINGS SPISettings(14000000, MSBFIRST, SPI_MODE0) -#warning Use 14MHz clock for W5100/W5200/W5500. Slow. + // Safe for all chips but too slow + #define SPI_ETHERNET_SETTINGS SPISettings(14000000, MSBFIRST, SPI_MODE0) + #warning Use 14MHz clock for W5100/W5200/W5500. Slow. #endif // Require Ethernet.h, because we need MAX_SOCK_NUM #ifndef ethernet_h_ -#error "Ethernet.h must be included before w5100.h" + #error "Ethernet.h must be included before w5100.h" #endif // Arduino 101's SPI can not run faster than 8 MHz. #if defined(ARDUINO_ARCH_ARC32) -#undef SPI_ETHERNET_SETTINGS -#define SPI_ETHERNET_SETTINGS SPISettings(8000000, MSBFIRST, SPI_MODE0) + #undef SPI_ETHERNET_SETTINGS + #define SPI_ETHERNET_SETTINGS SPISettings(8000000, MSBFIRST, SPI_MODE0) #endif // Arduino Zero can't use W5100-based shields faster than 8 MHz // https://github.com/arduino-libraries/Ethernet/issues/37#issuecomment-408036848 // W5500 does seem to work at 12 MHz. Delete this if only using W5500 #if defined(__SAMD21G18A__) -#undef SPI_ETHERNET_SETTINGS -//#warning Use SAMD21 architecture SPISettings(8000000, MSBFIRST, SPI_MODE3) => IP OK -#warning Use SAMD21 architecture SPISettings(30000000, MSBFIRST, SPI_MODE3) => IP OK -// Still not working !!! Original SPI_MODE0 not OK at all -//#define SPI_ETHERNET_SETTINGS SPISettings(8000000, MSBFIRST, SPI_MODE3) -#define SPI_ETHERNET_SETTINGS SPISettings(30000000, MSBFIRST, SPI_MODE3) + #undef SPI_ETHERNET_SETTINGS + //#warning Use SAMD21 architecture SPISettings(8000000, MSBFIRST, SPI_MODE3) => IP OK + #warning Use SAMD21 architecture SPISettings(30000000, MSBFIRST, SPI_MODE3) => IP OK + // Still not working !!! Original SPI_MODE0 not OK at all + //#define SPI_ETHERNET_SETTINGS SPISettings(8000000, MSBFIRST, SPI_MODE3) + #define SPI_ETHERNET_SETTINGS SPISettings(30000000, MSBFIRST, SPI_MODE3) #endif typedef uint8_t SOCKET; -class SnMR { -public: - static const uint8_t CLOSE = 0x00; - static const uint8_t TCP = 0x21; - static const uint8_t UDP = 0x02; - static const uint8_t IPRAW = 0x03; - static const uint8_t MACRAW = 0x04; - static const uint8_t PPPOE = 0x05; - static const uint8_t ND = 0x20; - static const uint8_t MULTI = 0x80; +class SnMR +{ + public: + static const uint8_t CLOSE = 0x00; + static const uint8_t TCP = 0x21; + static const uint8_t UDP = 0x02; + static const uint8_t IPRAW = 0x03; + static const uint8_t MACRAW = 0x04; + static const uint8_t PPPOE = 0x05; + static const uint8_t ND = 0x20; + static const uint8_t MULTI = 0x80; }; -enum SockCMD { +enum SockCMD +{ Sock_OPEN = 0x01, Sock_LISTEN = 0x02, Sock_CONNECT = 0x04, @@ -125,97 +127,132 @@ enum SockCMD { Sock_RECV = 0x40 }; -class SnIR { -public: - static const uint8_t SEND_OK = 0x10; - static const uint8_t TIMEOUT = 0x08; - static const uint8_t RECV = 0x04; - static const uint8_t DISCON = 0x02; - static const uint8_t CON = 0x01; +class SnIR +{ + public: + static const uint8_t SEND_OK = 0x10; + static const uint8_t TIMEOUT = 0x08; + static const uint8_t RECV = 0x04; + static const uint8_t DISCON = 0x02; + static const uint8_t CON = 0x01; }; -class SnSR { -public: - static const uint8_t CLOSED = 0x00; - static const uint8_t INIT = 0x13; - static const uint8_t LISTEN = 0x14; - static const uint8_t SYNSENT = 0x15; - static const uint8_t SYNRECV = 0x16; - static const uint8_t ESTABLISHED = 0x17; - static const uint8_t FIN_WAIT = 0x18; - static const uint8_t CLOSING = 0x1A; - static const uint8_t TIME_WAIT = 0x1B; - static const uint8_t CLOSE_WAIT = 0x1C; - static const uint8_t LAST_ACK = 0x1D; - static const uint8_t UDP = 0x22; - static const uint8_t IPRAW = 0x32; - static const uint8_t MACRAW = 0x42; - static const uint8_t PPPOE = 0x5F; +class SnSR +{ + public: + static const uint8_t CLOSED = 0x00; + static const uint8_t INIT = 0x13; + static const uint8_t LISTEN = 0x14; + static const uint8_t SYNSENT = 0x15; + static const uint8_t SYNRECV = 0x16; + static const uint8_t ESTABLISHED = 0x17; + static const uint8_t FIN_WAIT = 0x18; + static const uint8_t CLOSING = 0x1A; + static const uint8_t TIME_WAIT = 0x1B; + static const uint8_t CLOSE_WAIT = 0x1C; + static const uint8_t LAST_ACK = 0x1D; + static const uint8_t UDP = 0x22; + static const uint8_t IPRAW = 0x32; + static const uint8_t MACRAW = 0x42; + static const uint8_t PPPOE = 0x5F; }; -class IPPROTO { -public: - static const uint8_t IP = 0; - static const uint8_t ICMP = 1; - static const uint8_t IGMP = 2; - static const uint8_t GGP = 3; - static const uint8_t TCP = 6; - static const uint8_t PUP = 12; - static const uint8_t UDP = 17; - static const uint8_t IDP = 22; - static const uint8_t ND = 77; - static const uint8_t RAW = 255; +class IPPROTO +{ + public: + static const uint8_t IP = 0; + static const uint8_t ICMP = 1; + static const uint8_t IGMP = 2; + static const uint8_t GGP = 3; + static const uint8_t TCP = 6; + static const uint8_t PUP = 12; + static const uint8_t UDP = 17; + static const uint8_t IDP = 22; + static const uint8_t ND = 77; + static const uint8_t RAW = 255; }; -enum W5100Linkstatus { +enum W5100Linkstatus +{ UNKNOWN, LINK_ON, LINK_OFF }; -class W5100Class { +class W5100Class +{ -public: - // KH - uint8_t init(uint8_t socketNumbers = MAX_SOCK_NUM, uint8_t new_ss_pin = 10); + public: + // KH + uint8_t init(uint8_t socketNumbers = MAX_SOCK_NUM, uint8_t new_ss_pin = 10); - inline void setGatewayIp(const uint8_t * addr) { writeGAR(addr); } - inline void getGatewayIp(uint8_t * addr) { readGAR(addr); } + inline void setGatewayIp(const uint8_t * addr) + { + writeGAR(addr); + } + inline void getGatewayIp(uint8_t * addr) + { + readGAR(addr); + } - inline void setSubnetMask(const uint8_t * addr) { writeSUBR(addr); } - inline void getSubnetMask(uint8_t * addr) { readSUBR(addr); } + inline void setSubnetMask(const uint8_t * addr) + { + writeSUBR(addr); + } + inline void getSubnetMask(uint8_t * addr) + { + readSUBR(addr); + } - inline void setMACAddress(const uint8_t * addr) { writeSHAR(addr); } - inline void getMACAddress(uint8_t * addr) { readSHAR(addr); } + inline void setMACAddress(const uint8_t * addr) + { + writeSHAR(addr); + } + inline void getMACAddress(uint8_t * addr) + { + readSHAR(addr); + } - inline void setIPAddress(const uint8_t * addr) { writeSIPR(addr); } - inline void getIPAddress(uint8_t * addr) { readSIPR(addr); } + inline void setIPAddress(const uint8_t * addr) + { + writeSIPR(addr); + } + inline void getIPAddress(uint8_t * addr) + { + readSIPR(addr); + } - inline void setRetransmissionTime(uint16_t timeout) { writeRTR(timeout); } - inline void setRetransmissionCount(uint8_t retry) { writeRCR(retry); } + inline void setRetransmissionTime(uint16_t timeout) + { + writeRTR(timeout); + } + inline void setRetransmissionCount(uint8_t retry) + { + writeRCR(retry); + } - static void execCmdSn(SOCKET s, SockCMD _cmd); + static void execCmdSn(SOCKET s, SockCMD _cmd); - // W5100 Registers - // --------------- -//private: -public: - static uint16_t write(uint16_t addr, const uint8_t *buf, uint16_t len); - - static uint8_t write(uint16_t addr, uint8_t data) - { - return write(addr, &data, 1); - } - - static uint16_t read(uint16_t addr, uint8_t *buf, uint16_t len); - - static uint8_t read(uint16_t addr) - { - uint8_t data; - read(addr, &data, 1); - return data; - } + // W5100 Registers + // --------------- + //private: + public: + static uint16_t write(uint16_t addr, const uint8_t *buf, uint16_t len); + + static uint8_t write(uint16_t addr, uint8_t data) + { + return write(addr, &data, 1); + } + + static uint16_t read(uint16_t addr, uint8_t *buf, uint16_t len); + + static uint8_t read(uint16_t addr) + { + uint8_t data; + read(addr, &data, 1); + return data; + } #define __GP_REGISTER8(name, address) \ static inline void write##name(uint8_t _data) { \ @@ -243,64 +280,65 @@ class W5100Class { static uint16_t read##name(uint8_t *_buff) { \ return read(address, _buff, size); \ } - - W5100Linkstatus getLinkStatus(); - -public: - __GP_REGISTER8 (MR, 0x0000); // Mode - __GP_REGISTER_N(GAR, 0x0001, 4); // Gateway IP address - __GP_REGISTER_N(SUBR, 0x0005, 4); // Subnet mask address - __GP_REGISTER_N(SHAR, 0x0009, 6); // Source MAC address - __GP_REGISTER_N(SIPR, 0x000F, 4); // Source IP address - __GP_REGISTER8 (IR, 0x0015); // Interrupt - __GP_REGISTER8 (IMR, 0x0016); // Interrupt Mask - __GP_REGISTER16(RTR, 0x0017); // Timeout address - __GP_REGISTER8 (RCR, 0x0019); // Retry count - __GP_REGISTER8 (RMSR, 0x001A); // Receive memory size (W5100 only) - __GP_REGISTER8 (TMSR, 0x001B); // Transmit memory size (W5100 only) - __GP_REGISTER8 (PATR, 0x001C); // Authentication type address in PPPoE mode - __GP_REGISTER8 (PTIMER, 0x0028); // PPP LCP Request Timer - __GP_REGISTER8 (PMAGIC, 0x0029); // PPP LCP Magic Number - __GP_REGISTER_N(UIPR, 0x002A, 4); // Unreachable IP address in UDP mode (W5100 only) - __GP_REGISTER16(UPORT, 0x002E); // Unreachable Port address in UDP mode (W5100 only) - __GP_REGISTER8 (VERSIONR_W5200,0x001F); // Chip Version Register (W5200 only) - __GP_REGISTER8 (VERSIONR_W5500,0x0039); // Chip Version Register (W5500 only) - __GP_REGISTER8 (PSTATUS_W5200, 0x0035); // PHY Status - __GP_REGISTER8 (PHYCFGR_W5500, 0x002E); // PHY Configuration register, default: 10111xxx + + W5100Linkstatus getLinkStatus(); + + public: + __GP_REGISTER8 (MR, 0x0000); // Mode + __GP_REGISTER_N(GAR, 0x0001, 4); // Gateway IP address + __GP_REGISTER_N(SUBR, 0x0005, 4); // Subnet mask address + __GP_REGISTER_N(SHAR, 0x0009, 6); // Source MAC address + __GP_REGISTER_N(SIPR, 0x000F, 4); // Source IP address + __GP_REGISTER8 (IR, 0x0015); // Interrupt + __GP_REGISTER8 (IMR, 0x0016); // Interrupt Mask + __GP_REGISTER16(RTR, 0x0017); // Timeout address + __GP_REGISTER8 (RCR, 0x0019); // Retry count + __GP_REGISTER8 (RMSR, 0x001A); // Receive memory size (W5100 only) + __GP_REGISTER8 (TMSR, 0x001B); // Transmit memory size (W5100 only) + __GP_REGISTER8 (PATR, 0x001C); // Authentication type address in PPPoE mode + __GP_REGISTER8 (PTIMER, 0x0028); // PPP LCP Request Timer + __GP_REGISTER8 (PMAGIC, 0x0029); // PPP LCP Magic Number + __GP_REGISTER_N(UIPR, 0x002A, 4); // Unreachable IP address in UDP mode (W5100 only) + __GP_REGISTER16(UPORT, 0x002E); // Unreachable Port address in UDP mode (W5100 only) + __GP_REGISTER8 (VERSIONR_W5200, 0x001F); // Chip Version Register (W5200 only) + __GP_REGISTER8 (VERSIONR_W5500, 0x0039); // Chip Version Register (W5500 only) + __GP_REGISTER8 (PSTATUS_W5200, 0x0035); // PHY Status + __GP_REGISTER8 (PHYCFGR_W5500, 0x002E); // PHY Configuration register, default: 10111xxx #undef __GP_REGISTER8 #undef __GP_REGISTER16 #undef __GP_REGISTER_N - // W5100 Socket registers - // ---------------------- -private: - static uint16_t CH_BASE(void) { - //if (chip == 55) return 0x1000; - //if (chip == 52) return 0x4000; - //return 0x0400; - return CH_BASE_MSB << 8; - } - static uint8_t CH_BASE_MSB; // 1 redundant byte, saves ~80 bytes code on AVR - static const uint16_t CH_SIZE = 0x0100; + // W5100 Socket registers + // ---------------------- + private: + static uint16_t CH_BASE(void) + { + //if (chip == 55) return 0x1000; + //if (chip == 52) return 0x4000; + //return 0x0400; + return CH_BASE_MSB << 8; + } + static uint8_t CH_BASE_MSB; // 1 redundant byte, saves ~80 bytes code on AVR + static const uint16_t CH_SIZE = 0x0100; - static inline uint8_t readSn(SOCKET s, uint16_t addr) - { - return read(CH_BASE() + s * CH_SIZE + addr); - } - static inline uint8_t writeSn(SOCKET s, uint16_t addr, uint8_t data) - { - return write(CH_BASE() + s * CH_SIZE + addr, data); - } - static inline uint16_t readSn(SOCKET s, uint16_t addr, uint8_t *buf, uint16_t len) - { - return read(CH_BASE() + s * CH_SIZE + addr, buf, len); - } - static inline uint16_t writeSn(SOCKET s, uint16_t addr, uint8_t *buf, uint16_t len) - { - return write(CH_BASE() + s * CH_SIZE + addr, buf, len); - } + static inline uint8_t readSn(SOCKET s, uint16_t addr) + { + return read(CH_BASE() + s * CH_SIZE + addr); + } + static inline uint8_t writeSn(SOCKET s, uint16_t addr, uint8_t data) + { + return write(CH_BASE() + s * CH_SIZE + addr, data); + } + static inline uint16_t readSn(SOCKET s, uint16_t addr, uint8_t *buf, uint16_t len) + { + return read(CH_BASE() + s * CH_SIZE + addr, buf, len); + } + static inline uint16_t writeSn(SOCKET s, uint16_t addr, uint8_t *buf, uint16_t len) + { + return write(CH_BASE() + s * CH_SIZE + addr, buf, len); + } #define __SOCKET_REGISTER8(name, address) \ static inline void write##name(SOCKET _s, uint8_t _data) { \ @@ -329,287 +367,294 @@ class W5100Class { return readSn(_s, address, _buff, size); \ } -public: - __SOCKET_REGISTER8(SnMR, 0x0000) // Mode - __SOCKET_REGISTER8(SnCR, 0x0001) // Command - __SOCKET_REGISTER8(SnIR, 0x0002) // Interrupt - __SOCKET_REGISTER8(SnSR, 0x0003) // Status - __SOCKET_REGISTER16(SnPORT, 0x0004) // Source Port - __SOCKET_REGISTER_N(SnDHAR, 0x0006, 6) // Destination Hardw Addr - __SOCKET_REGISTER_N(SnDIPR, 0x000C, 4) // Destination IP Addr - __SOCKET_REGISTER16(SnDPORT, 0x0010) // Destination Port - __SOCKET_REGISTER16(SnMSSR, 0x0012) // Max Segment Size - __SOCKET_REGISTER8(SnPROTO, 0x0014) // Protocol in IP RAW Mode - __SOCKET_REGISTER8(SnTOS, 0x0015) // IP TOS - __SOCKET_REGISTER8(SnTTL, 0x0016) // IP TTL - __SOCKET_REGISTER8(SnRX_SIZE, 0x001E) // RX Memory Size (W5200 only) - __SOCKET_REGISTER8(SnTX_SIZE, 0x001F) // RX Memory Size (W5200 only) - __SOCKET_REGISTER16(SnTX_FSR, 0x0020) // TX Free Size - __SOCKET_REGISTER16(SnTX_RD, 0x0022) // TX Read Pointer - __SOCKET_REGISTER16(SnTX_WR, 0x0024) // TX Write Pointer - __SOCKET_REGISTER16(SnRX_RSR, 0x0026) // RX Free Size - __SOCKET_REGISTER16(SnRX_RD, 0x0028) // RX Read Pointer - __SOCKET_REGISTER16(SnRX_WR, 0x002A) // RX Write Pointer (supported?) + public: + __SOCKET_REGISTER8(SnMR, 0x0000) // Mode + __SOCKET_REGISTER8(SnCR, 0x0001) // Command + __SOCKET_REGISTER8(SnIR, 0x0002) // Interrupt + __SOCKET_REGISTER8(SnSR, 0x0003) // Status + __SOCKET_REGISTER16(SnPORT, 0x0004) // Source Port + __SOCKET_REGISTER_N(SnDHAR, 0x0006, 6) // Destination Hardw Addr + __SOCKET_REGISTER_N(SnDIPR, 0x000C, 4) // Destination IP Addr + __SOCKET_REGISTER16(SnDPORT, 0x0010) // Destination Port + __SOCKET_REGISTER16(SnMSSR, 0x0012) // Max Segment Size + __SOCKET_REGISTER8(SnPROTO, 0x0014) // Protocol in IP RAW Mode + __SOCKET_REGISTER8(SnTOS, 0x0015) // IP TOS + __SOCKET_REGISTER8(SnTTL, 0x0016) // IP TTL + __SOCKET_REGISTER8(SnRX_SIZE, 0x001E) // RX Memory Size (W5200 only) + __SOCKET_REGISTER8(SnTX_SIZE, 0x001F) // RX Memory Size (W5200 only) + __SOCKET_REGISTER16(SnTX_FSR, 0x0020) // TX Free Size + __SOCKET_REGISTER16(SnTX_RD, 0x0022) // TX Read Pointer + __SOCKET_REGISTER16(SnTX_WR, 0x0024) // TX Write Pointer + __SOCKET_REGISTER16(SnRX_RSR, 0x0026) // RX Free Size + __SOCKET_REGISTER16(SnRX_RD, 0x0028) // RX Read Pointer + __SOCKET_REGISTER16(SnRX_WR, 0x002A) // RX Write Pointer (supported?) #undef __SOCKET_REGISTER8 #undef __SOCKET_REGISTER16 #undef __SOCKET_REGISTER_N -private: - // KH - bool initialized = false; - static uint8_t chip; - static uint8_t ss_pin; + private: + // KH + bool initialized = false; + static uint8_t chip; + static uint8_t ss_pin; - static uint8_t isW5100(void); - static uint8_t isW5200(void); - static uint8_t isW5500(void); + static uint8_t isW5100(void); + static uint8_t isW5200(void); + static uint8_t isW5500(void); -public: - // KH - static uint8_t softReset(void); - static uint8_t getChip(void) { return chip; } + public: + // KH + static uint8_t softReset(void); + static uint8_t getChip(void) + { + return chip; + } #ifdef ETHERNET_LARGE_BUFFERS - static uint16_t SSIZE; - static uint16_t SMASK; + static uint16_t SSIZE; + static uint16_t SMASK; #else - static const uint16_t SSIZE = 2048; - static const uint16_t SMASK = 0x07FF; + static const uint16_t SSIZE = 2048; + static const uint16_t SMASK = 0x07FF; #endif - static uint16_t SBASE(uint8_t socknum) - { - if (chip == 51) + static uint16_t SBASE(uint8_t socknum) { - return socknum * SSIZE + 0x4000; - } - else + if (chip == 51) + { + return socknum * SSIZE + 0x4000; + } + else + { + return socknum * SSIZE + 0x8000; + } + } + + static uint16_t RBASE(uint8_t socknum) { - return socknum * SSIZE + 0x8000; + if (chip == 51) + { + return socknum * SSIZE + 0x6000; + } + else + { + return socknum * SSIZE + 0xC000; + } } - } - - static uint16_t RBASE(uint8_t socknum) - { - if (chip == 51) { - return socknum * SSIZE + 0x6000; - } - else + + static bool hasOffsetAddressMapping(void) { - return socknum * SSIZE + 0xC000; + if (chip == 55) + return true; + + return false; } - } - static bool hasOffsetAddressMapping(void) - { - if (chip == 55) - return true; - - return false; - } - - static void setSS(uint8_t pin) { ss_pin = pin; } + static void setSS(uint8_t pin) + { + ss_pin = pin; + } -private: + private: #if defined(__AVR__) #warning Use AVR architecture - static volatile uint8_t *ss_pin_reg; - static uint8_t ss_pin_mask; - - inline static void initSS() - { - ss_pin_reg = portOutputRegister(digitalPinToPort(ss_pin)); - ss_pin_mask = digitalPinToBitMask(ss_pin); - pinMode(ss_pin, OUTPUT); - } - - inline static void setSS() - { - *(ss_pin_reg) &= ~ss_pin_mask; - } - - inline static void resetSS() - { - *(ss_pin_reg) |= ss_pin_mask; - } + static volatile uint8_t *ss_pin_reg; + static uint8_t ss_pin_mask; + + inline static void initSS() + { + ss_pin_reg = portOutputRegister(digitalPinToPort(ss_pin)); + ss_pin_mask = digitalPinToBitMask(ss_pin); + pinMode(ss_pin, OUTPUT); + } + + inline static void setSS() + { + *(ss_pin_reg) &= ~ss_pin_mask; + } + + inline static void resetSS() + { + *(ss_pin_reg) |= ss_pin_mask; + } #elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK66FX1M0__) || defined(__MK64FX512__) #warning Use MK architecture - static volatile uint8_t *ss_pin_reg; - - inline static void initSS() - { - ss_pin_reg = portOutputRegister(ss_pin); - pinMode(ss_pin, OUTPUT); - } - - inline static void setSS() - { - *(ss_pin_reg+256) = 1; - } - - inline static void resetSS() - { - *(ss_pin_reg+128) = 1; - } + static volatile uint8_t *ss_pin_reg; + + inline static void initSS() + { + ss_pin_reg = portOutputRegister(ss_pin); + pinMode(ss_pin, OUTPUT); + } + + inline static void setSS() + { + *(ss_pin_reg + 256) = 1; + } + + inline static void resetSS() + { + *(ss_pin_reg + 128) = 1; + } #elif defined(__IMXRT1062__) #warning Use Teensy architecture - static volatile uint32_t *ss_pin_reg; - static uint32_t ss_pin_mask; - - inline static void initSS() - { - ss_pin_reg = portOutputRegister(digitalPinToPort(ss_pin)); - ss_pin_mask = digitalPinToBitMask(ss_pin); - pinMode(ss_pin, OUTPUT); - } - - inline static void setSS() - { - *(ss_pin_reg+34) = ss_pin_mask; - } - - inline static void resetSS() - { - *(ss_pin_reg+33) = ss_pin_mask; - - // Check https://forum.pjrc.com/threads/66758-Teensy-4-0-and-Ethernet-(WIZ5100-and-WIZ812) - if (chip == 51) - delayNanoseconds(10); // <-- fixes W5100 on Teensy 4 - } + static volatile uint32_t *ss_pin_reg; + static uint32_t ss_pin_mask; + + inline static void initSS() + { + ss_pin_reg = portOutputRegister(digitalPinToPort(ss_pin)); + ss_pin_mask = digitalPinToBitMask(ss_pin); + pinMode(ss_pin, OUTPUT); + } + + inline static void setSS() + { + *(ss_pin_reg + 34) = ss_pin_mask; + } + + inline static void resetSS() + { + *(ss_pin_reg + 33) = ss_pin_mask; + + // Check https://forum.pjrc.com/threads/66758-Teensy-4-0-and-Ethernet-(WIZ5100-and-WIZ812) + if (chip == 51) + delayNanoseconds(10); // <-- fixes W5100 on Teensy 4 + } #elif defined(__MKL26Z64__) - static volatile uint8_t *ss_pin_reg; - static uint8_t ss_pin_mask; - inline static void initSS() - { - ss_pin_reg = portOutputRegister(digitalPinToPort(ss_pin)); - ss_pin_mask = digitalPinToBitMask(ss_pin); - pinMode(ss_pin, OUTPUT); - } - - inline static void setSS() - { - *(ss_pin_reg+8) = ss_pin_mask; - } - - inline static void resetSS() - { - *(ss_pin_reg+4) = ss_pin_mask; - } + static volatile uint8_t *ss_pin_reg; + static uint8_t ss_pin_mask; + inline static void initSS() + { + ss_pin_reg = portOutputRegister(digitalPinToPort(ss_pin)); + ss_pin_mask = digitalPinToBitMask(ss_pin); + pinMode(ss_pin, OUTPUT); + } + + inline static void setSS() + { + *(ss_pin_reg + 8) = ss_pin_mask; + } + + inline static void resetSS() + { + *(ss_pin_reg + 4) = ss_pin_mask; + } #elif defined(__SAM3X8E__) || defined(__SAM3A8C__) || defined(__SAM3A4C__) #warning Use SAM3 architecture - static volatile uint32_t *ss_pin_reg; - static uint32_t ss_pin_mask; - - inline static void initSS() - { - ss_pin_reg = &(digitalPinToPort(ss_pin)->PIO_PER); - ss_pin_mask = digitalPinToBitMask(ss_pin); - pinMode(ss_pin, OUTPUT); - } - - inline static void setSS() - { - *(ss_pin_reg+13) = ss_pin_mask; - } - - inline static void resetSS() - { - *(ss_pin_reg+12) = ss_pin_mask; - } + static volatile uint32_t *ss_pin_reg; + static uint32_t ss_pin_mask; + + inline static void initSS() + { + ss_pin_reg = &(digitalPinToPort(ss_pin)->PIO_PER); + ss_pin_mask = digitalPinToBitMask(ss_pin); + pinMode(ss_pin, OUTPUT); + } + + inline static void setSS() + { + *(ss_pin_reg + 13) = ss_pin_mask; + } + + inline static void resetSS() + { + *(ss_pin_reg + 12) = ss_pin_mask; + } #elif defined(__PIC32MX__) - static volatile uint32_t *ss_pin_reg; - static uint32_t ss_pin_mask; - - inline static void initSS() - { - ss_pin_reg = portModeRegister(digitalPinToPort(ss_pin)); - ss_pin_mask = digitalPinToBitMask(ss_pin); - pinMode(ss_pin, OUTPUT); - } - - inline static void setSS() - { - *(ss_pin_reg+8+1) = ss_pin_mask; - } - - inline static void resetSS() - { - *(ss_pin_reg+8+2) = ss_pin_mask; - } + static volatile uint32_t *ss_pin_reg; + static uint32_t ss_pin_mask; + + inline static void initSS() + { + ss_pin_reg = portModeRegister(digitalPinToPort(ss_pin)); + ss_pin_mask = digitalPinToBitMask(ss_pin); + pinMode(ss_pin, OUTPUT); + } + + inline static void setSS() + { + *(ss_pin_reg + 8 + 1) = ss_pin_mask; + } + + inline static void resetSS() + { + *(ss_pin_reg + 8 + 2) = ss_pin_mask; + } #elif defined(ARDUINO_ARCH_ESP8266) #warning Use ARDUINO_ARCH_ESP8266 architecture - static volatile uint32_t *ss_pin_reg; - static uint32_t ss_pin_mask; - - inline static void initSS() - { - ss_pin_reg = (volatile uint32_t*)GPO; - ss_pin_mask = 1 << ss_pin; - pinMode(ss_pin, OUTPUT); - } - - inline static void setSS() - { - GPOC = ss_pin_mask; - } - - inline static void resetSS() - { - GPOS = ss_pin_mask; - } + static volatile uint32_t *ss_pin_reg; + static uint32_t ss_pin_mask; + + inline static void initSS() + { + ss_pin_reg = (volatile uint32_t*)GPO; + ss_pin_mask = 1 << ss_pin; + pinMode(ss_pin, OUTPUT); + } + + inline static void setSS() + { + GPOC = ss_pin_mask; + } + + inline static void resetSS() + { + GPOS = ss_pin_mask; + } #elif defined(__SAMD21G18A__) #warning Use SAMD21 architecture - static volatile uint32_t *ss_pin_reg; - static uint32_t ss_pin_mask; - - inline static void initSS() - { - ss_pin_reg = portModeRegister(digitalPinToPort(ss_pin)); - ss_pin_mask = digitalPinToBitMask(ss_pin); - pinMode(ss_pin, OUTPUT); - } - - inline static void setSS() - { - *(ss_pin_reg+5) = ss_pin_mask; - } - - inline static void resetSS() - { - *(ss_pin_reg+6) = ss_pin_mask; - } + static volatile uint32_t *ss_pin_reg; + static uint32_t ss_pin_mask; + + inline static void initSS() + { + ss_pin_reg = portModeRegister(digitalPinToPort(ss_pin)); + ss_pin_mask = digitalPinToBitMask(ss_pin); + pinMode(ss_pin, OUTPUT); + } + + inline static void setSS() + { + *(ss_pin_reg + 5) = ss_pin_mask; + } + + inline static void resetSS() + { + *(ss_pin_reg + 6) = ss_pin_mask; + } #else #warning Use Default architecture - inline static void initSS() - { - pinMode(ss_pin, OUTPUT); - } - - inline static void setSS() - { - digitalWrite(ss_pin, LOW); - } - - inline static void resetSS() - { - digitalWrite(ss_pin, HIGH); - } + inline static void initSS() + { + pinMode(ss_pin, OUTPUT); + } + + inline static void setSS() + { + digitalWrite(ss_pin, LOW); + } + + inline static void resetSS() + { + digitalWrite(ss_pin, HIGH); + } #endif }; @@ -621,11 +666,11 @@ extern W5100Class W5100; #define UTIL_H #ifndef htons -#define htons(x) ( (((x)<<8)&0xFF00) | (((x)>>8)&0xFF) ) + #define htons(x) ( (((x)<<8)&0xFF00) | (((x)>>8)&0xFF) ) #endif #ifndef ntohs -#define ntohs(x) htons(x) + #define ntohs(x) htons(x) #endif #ifndef htonl @@ -634,9 +679,9 @@ extern W5100Class W5100; ((x)>> 8 & 0x0000FF00UL) | \ ((x)>>24 & 0x000000FFUL) ) #endif - -#ifndef ntohl -#define ntohl(x) htonl(x) + +#ifndef ntohl + #define ntohl(x) htonl(x) #endif #endif //W5100_H_INCLUDED diff --git a/LibraryPatches/Ethernet2/src/Ethernet2.cpp b/LibraryPatches/Ethernet2/src/Ethernet2.cpp index f90be20..70423b2 100644 --- a/LibraryPatches/Ethernet2/src/Ethernet2.cpp +++ b/LibraryPatches/Ethernet2/src/Ethernet2.cpp @@ -1,13 +1,13 @@ /* - modified 12 Aug 2013 - by Soohwan Kim (suhwan@wiznet.co.kr) + modified 12 Aug 2013 + by Soohwan Kim (suhwan@wiznet.co.kr) -- 10 Apr. 2015 - Added support for Arduino Ethernet Shield 2 - by Arduino.org team + - 10 Apr. 2015 + Added support for Arduino Ethernet Shield 2 + by Arduino.org team + +*/ - */ - #include "Ethernet2.h" #include "Dhcp.h" @@ -24,24 +24,26 @@ int EthernetClass::begin(void) // Now store to private var _mac_address //byte mac_address[6] ={0,}; ////// - - if (_dhcp != NULL) { + + if (_dhcp != NULL) + { delete _dhcp; } + _dhcp = new DhcpClass(); // Initialise the basic info w5500.init(w5500_cspin); - w5500.setIPAddress(IPAddress(0,0,0,0).raw_address()); - + w5500.setIPAddress(IPAddress(0, 0, 0, 0).raw_address()); + // KH mod w5500.getMACAddress(_mac_address); - + // Now try to get our config info from a DHCP server int ret = _dhcp->beginWithDHCP(_mac_address); ////// - - if(ret == 1) + + if (ret == 1) { // We've successfully found a DHCP server and got our configuration info, so set things // accordingly @@ -97,18 +99,21 @@ int EthernetClass::begin(uint8_t *mac_address) memcpy(_mac_address, mac_address, sizeof(_mac_address)); ////// - if (_dhcp != NULL) { - delete _dhcp; - } + if (_dhcp != NULL) + { + delete _dhcp; + } + _dhcp = new DhcpClass(); // Initialise the basic info w5500.init(w5500_cspin); w5500.setMACAddress(mac_address); - w5500.setIPAddress(IPAddress(0,0,0,0).raw_address()); + w5500.setIPAddress(IPAddress(0, 0, 0, 0).raw_address()); // Now try to get our config info from a DHCP server int ret = _dhcp->beginWithDHCP(mac_address); - if(ret == 1) + + if (ret == 1) { // We've successfully found a DHCP server and got our configuration info, so set things // accordingly @@ -130,7 +135,7 @@ void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip) //uint8_t _mac_address[6] ={0,}; memcpy(_mac_address, mac_address, sizeof(_mac_address)); ////// - + // Assume the DNS server will be the machine on the same network as the local IP // but with last octet being '1' IPAddress dns_server = local_ip; @@ -145,7 +150,7 @@ void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dn //uint8_t _mac_address[6] ={0,}; memcpy(_mac_address, mac_address, sizeof(_mac_address)); ////// - + // Assume the gateway will be the machine on the same network as the local IP // but with last octet being '1' IPAddress gateway = local_ip; @@ -160,19 +165,20 @@ void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dn //uint8_t _mac_address[6] ={0,}; memcpy(_mac_address, mac_address, sizeof(_mac_address)); ////// - + IPAddress subnet(255, 255, 255, 0); begin(mac_address, local_ip, dns_server, gateway, subnet); } -void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet) +void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway, + IPAddress subnet) { // KH mod to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ // Now store to private var //uint8_t _mac_address[6] ={0,}; memcpy(_mac_address, mac_address, sizeof(_mac_address)); ////// - + w5500.init(w5500_cspin); w5500.setMACAddress(mac_address); w5500.setIPAddress(local_ip.raw_address()); @@ -183,15 +189,21 @@ void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dn #endif -int EthernetClass::maintain(){ +int EthernetClass::maintain() +{ int rc = DHCP_CHECK_NONE; - if(_dhcp != NULL){ + + if (_dhcp != NULL) + { //we have a pointer to dhcp, use it rc = _dhcp->checkLease(); - switch ( rc ){ + + switch ( rc ) + { case DHCP_CHECK_NONE: //nothing done break; + case DHCP_CHECK_RENEW_OK: case DHCP_CHECK_REBIND_OK: //we might have got a new IP. @@ -202,25 +214,27 @@ int EthernetClass::maintain(){ _dnsDomainName = _dhcp->getDnsDomainName(); _hostName = _dhcp->getHostName(); break; + default: //this is actually a error, it will retry though break; } } + return rc; } // KH add to report link status -uint8_t EthernetClass::link() +uint8_t EthernetClass::link() { return bitRead(w5500.getPHYCFGR(), 0); } -const char* EthernetClass::linkReport() +const char* EthernetClass::linkReport() { - if (bitRead(w5500.getPHYCFGR(), 0) == 1) + if (bitRead(w5500.getPHYCFGR(), 0) == 1) return "LINK"; - else + else return "NO LINK"; } ////// @@ -251,12 +265,14 @@ IPAddress EthernetClass::dnsServerIP() return _dnsServerAddress; } -char* EthernetClass::dnsDomainName(){ - return _dnsDomainName; +char* EthernetClass::dnsDomainName() +{ + return _dnsDomainName; } -char* EthernetClass::hostName(){ - return _hostName; +char* EthernetClass::hostName() +{ + return _hostName; } EthernetClass Ethernet; diff --git a/LibraryPatches/Ethernet2/src/Ethernet2.h b/LibraryPatches/Ethernet2/src/Ethernet2.h index 7a5a25f..ded8309 100644 --- a/LibraryPatches/Ethernet2/src/Ethernet2.h +++ b/LibraryPatches/Ethernet2/src/Ethernet2.h @@ -1,12 +1,12 @@ /* - modified 12 Aug 2013 - by Soohwan Kim (suhwan@wiznet.co.kr) - - - 10 Apr. 2015 - Added support for Arduino Ethernet Shield 2 - by Arduino.org team - - */ + modified 12 Aug 2013 + by Soohwan Kim (suhwan@wiznet.co.kr) + + - 10 Apr. 2015 + Added support for Arduino Ethernet Shield 2 + by Arduino.org team + +*/ #ifndef ethernet_h #define ethernet_h @@ -19,72 +19,80 @@ -class EthernetClass { -private: - IPAddress _dnsServerAddress; - char* _dnsDomainName; - char* _hostName; - DhcpClass* _dhcp; - - // KH add to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ - uint8_t _mac_address[6] ={0,}; - ////// - -public: - uint8_t w5500_cspin; +class EthernetClass +{ + private: + IPAddress _dnsServerAddress; + char* _dnsDomainName; + char* _hostName; + DhcpClass* _dhcp; + + // KH add to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ + uint8_t _mac_address[6] = {0,}; + ////// - static uint8_t _state[MAX_SOCK_NUM]; - static uint16_t _server_port[MAX_SOCK_NUM]; + public: + uint8_t w5500_cspin; - EthernetClass() { _dhcp = NULL; w5500_cspin = 10; } - void init(uint8_t _cspin = 10) { w5500_cspin = _cspin; } + static uint8_t _state[MAX_SOCK_NUM]; + static uint16_t _server_port[MAX_SOCK_NUM]; + + EthernetClass() + { + _dhcp = NULL; + w5500_cspin = 10; + } + void init(uint8_t _cspin = 10) + { + w5500_cspin = _cspin; + } #if defined(WIZ550io_WITH_MACADDRESS) - // Initialize function when use the ioShield serise (included WIZ550io) - // WIZ550io has a MAC address which is written after reset. - // Default IP, Gateway and subnet address are also writen. - // so, It needs some initial time. please refer WIZ550io Datasheet in details. - int begin(void); - void begin(IPAddress local_ip); - void begin(IPAddress local_ip, IPAddress dns_server); - void begin(IPAddress local_ip, IPAddress dns_server, IPAddress gateway); - void begin(IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet); + // Initialize function when use the ioShield serise (included WIZ550io) + // WIZ550io has a MAC address which is written after reset. + // Default IP, Gateway and subnet address are also writen. + // so, It needs some initial time. please refer WIZ550io Datasheet in details. + int begin(void); + void begin(IPAddress local_ip); + void begin(IPAddress local_ip, IPAddress dns_server); + void begin(IPAddress local_ip, IPAddress dns_server, IPAddress gateway); + void begin(IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet); #else - // Initialize the Ethernet shield to use the provided MAC address and gain the rest of the - // configuration through DHCP. - // Returns 0 if the DHCP configuration failed, and 1 if it succeeded - int begin(uint8_t *mac_address); - void begin(uint8_t *mac_address, IPAddress local_ip); - void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server); - void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway); - void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet); + // Initialize the Ethernet shield to use the provided MAC address and gain the rest of the + // configuration through DHCP. + // Returns 0 if the DHCP configuration failed, and 1 if it succeeded + int begin(uint8_t *mac_address); + void begin(uint8_t *mac_address, IPAddress local_ip); + void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server); + void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway); + void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress dns_server, IPAddress gateway, IPAddress subnet); #endif - - int maintain(); - - // KH add to report link status - uint8_t link(); // returns the linkstate, 1 = linked, 0 = no link - const char* linkReport(); // returns the linkstate as a string - ////// - - // KH add to have similar function to Ethernet lib - // Certainly we can use void macAddress(uint8_t mac[]) to read from W5x00. - void MACAddress(uint8_t *mac_address) - { - memcpy(mac_address, _mac_address, sizeof(_mac_address)); - } - ////// - - IPAddress localIP(); - IPAddress subnetMask(); - IPAddress gatewayIP(); - IPAddress dnsServerIP(); - char* dnsDomainName(); - char* hostName(); - - friend class EthernetClient; - friend class EthernetServer; + + int maintain(); + + // KH add to report link status + uint8_t link(); // returns the linkstate, 1 = linked, 0 = no link + const char* linkReport(); // returns the linkstate as a string + ////// + + // KH add to have similar function to Ethernet lib + // Certainly we can use void macAddress(uint8_t mac[]) to read from W5x00. + void MACAddress(uint8_t *mac_address) + { + memcpy(mac_address, _mac_address, sizeof(_mac_address)); + } + ////// + + IPAddress localIP(); + IPAddress subnetMask(); + IPAddress gatewayIP(); + IPAddress dnsServerIP(); + char* dnsDomainName(); + char* hostName(); + + friend class EthernetClient; + friend class EthernetServer; }; extern EthernetClass Ethernet; diff --git a/LibraryPatches/Ethernet2/src/EthernetUdp2.cpp b/LibraryPatches/Ethernet2/src/EthernetUdp2.cpp index d8671cd..3fc6044 100644 --- a/LibraryPatches/Ethernet2/src/EthernetUdp2.cpp +++ b/LibraryPatches/Ethernet2/src/EthernetUdp2.cpp @@ -1,34 +1,34 @@ /* - * Udp.cpp: Library to send/receive UDP packets with the Arduino ethernet shield. - * This version only offers minimal wrapping of socket.c/socket.h - * Drop Udp.h/.cpp into the Ethernet library directory at hardware/libraries/Ethernet/ - * - * MIT License: - * Copyright (c) 2008 Bjoern Hartmann - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * bjoern@cs.stanford.edu 12/30/2008 - * - * - 10 Apr. 2015 - * Added support for Arduino Ethernet Shield 2 - * by Arduino.org team - */ + Udp.cpp: Library to send/receive UDP packets with the Arduino ethernet shield. + This version only offers minimal wrapping of socket.c/socket.h + Drop Udp.h/.cpp into the Ethernet library directory at hardware/libraries/Ethernet/ + + MIT License: + Copyright (c) 2008 Bjoern Hartmann + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + bjoern@cs.stanford.edu 12/30/2008 + + - 10 Apr. 2015 + Added support for Arduino Ethernet Shield 2 + by Arduino.org team +*/ #include "utility/w5500.h" #include "utility/socket.h" @@ -42,13 +42,17 @@ EthernetUDP::EthernetUDP() : _sock(MAX_SOCK_NUM) {} /* Start EthernetUDP socket, listening at local port PORT */ -uint8_t EthernetUDP::begin(uint16_t port) { +uint8_t EthernetUDP::begin(uint16_t port) +{ if (_sock != MAX_SOCK_NUM) return 0; - for (int i = 0; i < MAX_SOCK_NUM; i++) { + for (int i = 0; i < MAX_SOCK_NUM; i++) + { uint8_t s = w5500.readSnSR(i); - if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT) { + + if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT) + { _sock = i; break; } @@ -70,40 +74,44 @@ uint8_t EthernetUDP::beginMulticast(IPAddress ip, uint16_t port) { if (_sock != MAX_SOCK_NUM) return 0; - - for (int i = 0; i < MAX_SOCK_NUM; i++) { + + for (int i = 0; i < MAX_SOCK_NUM; i++) + { uint8_t s = w5500.readSnSR(i); - if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT) { + + if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT) + { _sock = i; break; } } - + if (_sock == MAX_SOCK_NUM) return 0; - + // Calculate MAC address from Multicast IP Address byte mac[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0x00 }; - + mac[3] = ip[1] & 0x7F; mac[4] = ip[2]; mac[5] = ip[3]; - + w5500.writeSnDIPR(_sock, rawIPAddress(ip)); //239.255.0.1 w5500.writeSnDPORT(_sock, port); - w5500.writeSnDHAR(_sock,mac); - + w5500.writeSnDHAR(_sock, mac); + _remaining = 0; socket(_sock, SnMR::UDP, port, SnMR::MULTI); return 1; } ////// - - + + /* return number of bytes available in the current packet, will return zero if parsePacket hasn't been called yet */ -int EthernetUDP::available() { +int EthernetUDP::available() +{ return _remaining; } @@ -128,9 +136,13 @@ int EthernetUDP::beginPacket(const char *host, uint16_t port) dns.begin(Ethernet.dnsServerIP()); ret = dns.getHostByName(host, remote_addr); - if (ret == 1) { + + if (ret == 1) + { return beginPacket(remote_addr, port); - } else { + } + else + { return ret; } } @@ -138,15 +150,15 @@ int EthernetUDP::beginPacket(const char *host, uint16_t port) int EthernetUDP::beginPacket(IPAddress ip, uint16_t port) { _offset = 0; - -// KH debug + + // KH debug #if (ETHERNET2_DEBUG > 1) - Serial.print("Ethernet2UDP::beginPacket: ip="); - Serial.print(ip); - Serial.print(", port="); - Serial.println(port); + Serial.print("Ethernet2UDP::beginPacket: ip="); + Serial.print(ip); + Serial.print(", port="); + Serial.println(port); #endif - + return startUDP(_sock, rawIPAddress(ip), port); } @@ -170,13 +182,13 @@ size_t EthernetUDP::write(const uint8_t *buffer, size_t size) uint16_t bytes_written = bufferData(_sock, _offset, buffer, size); _offset += bytes_written; - + // KH debug #if (ETHERNET2_DEBUG > 1) Serial.print("Ethernet2UDP: bytes written="); Serial.println(bytes_written); #endif - + return bytes_written; } @@ -189,9 +201,10 @@ int EthernetUDP::parsePacket() { //HACK - hand-parse the UDP packet using TCP recv method uint8_t tmpBuf[8]; - int ret =0; + int ret = 0; //read 8 header bytes and get IP and port from it - ret = recv(_sock,tmpBuf,8); + ret = recv(_sock, tmpBuf, 8); + if (ret > 0) { _remoteIP = tmpBuf; @@ -204,14 +217,15 @@ int EthernetUDP::parsePacket() ret = _remaining; } - // KH debug + // KH debug #if (ETHERNET2_DEBUG > 1) - Serial.print("Ethernet2UDP:parsePacket OK, datasize="); - Serial.println(ret); -#endif - + Serial.print("Ethernet2UDP:parsePacket OK, datasize="); + Serial.println(ret); +#endif + return ret; } + // There aren't any packets available return 0; } @@ -246,7 +260,7 @@ int EthernetUDP::read(unsigned char* buffer, size_t len) } else { - // too much data for the buffer, + // too much data for the buffer, // grab as much as will fit got = recv(_sock, buffer, len); } @@ -267,11 +281,13 @@ int EthernetUDP::read(unsigned char* buffer, size_t len) int EthernetUDP::peek() { uint8_t b; + // Unlike recv, peek doesn't check to see if there's any data available, so we must. // If the user hasn't called parsePacket yet then return nothing otherwise they // may get the UDP header if (!_remaining) return -1; + ::peek(_sock, &b); return b; } diff --git a/LibraryPatches/Ethernet2/src/EthernetUdp2.h b/LibraryPatches/Ethernet2/src/EthernetUdp2.h index fe8d110..a7e7627 100644 --- a/LibraryPatches/Ethernet2/src/EthernetUdp2.h +++ b/LibraryPatches/Ethernet2/src/EthernetUdp2.h @@ -1,44 +1,44 @@ /* - * Udp.cpp: Library to send/receive UDP packets with the Arduino ethernet shield. - * This version only offers minimal wrapping of socket.c/socket.h - * Drop Udp.h/.cpp into the Ethernet library directory at hardware/libraries/Ethernet/ - * - * NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these) - * 1) UDP does not guarantee the order in which assembled UDP packets are received. This - * might not happen often in practice, but in larger network topologies, a UDP - * packet can be received out of sequence. - * 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being - * aware of it. Again, this may not be a concern in practice on small local networks. - * For more information, see http://www.cafeaulait.org/course/week12/35.html - * - * MIT License: - * Copyright (c) 2008 Bjoern Hartmann - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * bjoern@cs.stanford.edu 12/30/2008 - * - * - 10 Apr. 2015 - * Added support for Arduino Ethernet Shield 2 - * by Arduino.org team - * - */ - + Udp.cpp: Library to send/receive UDP packets with the Arduino ethernet shield. + This version only offers minimal wrapping of socket.c/socket.h + Drop Udp.h/.cpp into the Ethernet library directory at hardware/libraries/Ethernet/ + + NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these) + 1) UDP does not guarantee the order in which assembled UDP packets are received. This + might not happen often in practice, but in larger network topologies, a UDP + packet can be received out of sequence. + 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being + aware of it. Again, this may not be a concern in practice on small local networks. + For more information, see http://www.cafeaulait.org/course/week12/35.html + + MIT License: + Copyright (c) 2008 Bjoern Hartmann + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + bjoern@cs.stanford.edu 12/30/2008 + + - 10 Apr. 2015 + Added support for Arduino Ethernet Shield 2 + by Arduino.org team + +*/ + #ifndef ethernetudp_h #define ethernetudp_h @@ -47,64 +47,76 @@ #define UDP_TX_PACKET_MAX_SIZE 24 -class EthernetUDP : public UDP { -private: - uint8_t _sock; // socket ID for Wiz5100 - uint16_t _port; // local port to listen on - IPAddress _remoteIP; // remote IP address for the incoming packet whilst it's being processed - uint16_t _remotePort; // remote port for the incoming packet whilst it's being processed - uint16_t _offset; // offset into the packet being sent - uint16_t _remaining; // remaining bytes of incoming packet yet to be processed - -public: - EthernetUDP(); // Constructor - virtual uint8_t begin(uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use - - //KH, to add Multicast support - virtual uint8_t beginMulticast(IPAddress, uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use - ////// - - virtual void stop(); // Finish with the UDP socket - - // Sending UDP packets - - // Start building up a packet to send to the remote host specific in ip and port - // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port - virtual int beginPacket(IPAddress ip, uint16_t port); - // Start building up a packet to send to the remote host specific in host and port - // Returns 1 if successful, 0 if there was a problem resolving the hostname or port - virtual int beginPacket(const char *host, uint16_t port); - // Finish off this packet and send it - // Returns 1 if the packet was sent successfully, 0 if there was an error - virtual int endPacket(); - // Write a single byte into the packet - virtual size_t write(uint8_t); - // Write size bytes from buffer into the packet - virtual size_t write(const uint8_t *buffer, size_t size); - - using Print::write; - - // Start processing the next available incoming packet - // Returns the size of the packet in bytes, or 0 if no packets are available - virtual int parsePacket(); - // Number of bytes remaining in the current packet - virtual int available(); - // Read a single byte from the current packet - virtual int read(); - // Read up to len bytes from the current packet and place them into buffer - // Returns the number of bytes read, or 0 if none are available - virtual int read(unsigned char* buffer, size_t len); - // Read up to len characters from the current packet and place them into buffer - // Returns the number of characters read, or 0 if none are available - virtual int read(char* buffer, size_t len) { return read((unsigned char*)buffer, len); }; - // Return the next byte from the current packet without moving on to the next byte - virtual int peek(); - virtual void flush(); // Finish reading the current packet - - // Return the IP address of the host who sent the current incoming packet - virtual IPAddress remoteIP() { return _remoteIP; }; - // Return the port of the host who sent the current incoming packet - virtual uint16_t remotePort() { return _remotePort; }; +class EthernetUDP : public UDP +{ + private: + uint8_t _sock; // socket ID for Wiz5100 + uint16_t _port; // local port to listen on + IPAddress _remoteIP; // remote IP address for the incoming packet whilst it's being processed + uint16_t _remotePort; // remote port for the incoming packet whilst it's being processed + uint16_t _offset; // offset into the packet being sent + uint16_t _remaining; // remaining bytes of incoming packet yet to be processed + + public: + EthernetUDP(); // Constructor + virtual uint8_t begin( + uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use + + //KH, to add Multicast support + virtual uint8_t beginMulticast(IPAddress, + uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use + ////// + + virtual void stop(); // Finish with the UDP socket + + // Sending UDP packets + + // Start building up a packet to send to the remote host specific in ip and port + // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port + virtual int beginPacket(IPAddress ip, uint16_t port); + // Start building up a packet to send to the remote host specific in host and port + // Returns 1 if successful, 0 if there was a problem resolving the hostname or port + virtual int beginPacket(const char *host, uint16_t port); + // Finish off this packet and send it + // Returns 1 if the packet was sent successfully, 0 if there was an error + virtual int endPacket(); + // Write a single byte into the packet + virtual size_t write(uint8_t); + // Write size bytes from buffer into the packet + virtual size_t write(const uint8_t *buffer, size_t size); + + using Print::write; + + // Start processing the next available incoming packet + // Returns the size of the packet in bytes, or 0 if no packets are available + virtual int parsePacket(); + // Number of bytes remaining in the current packet + virtual int available(); + // Read a single byte from the current packet + virtual int read(); + // Read up to len bytes from the current packet and place them into buffer + // Returns the number of bytes read, or 0 if none are available + virtual int read(unsigned char* buffer, size_t len); + // Read up to len characters from the current packet and place them into buffer + // Returns the number of characters read, or 0 if none are available + virtual int read(char* buffer, size_t len) + { + return read((unsigned char*)buffer, len); + }; + // Return the next byte from the current packet without moving on to the next byte + virtual int peek(); + virtual void flush(); // Finish reading the current packet + + // Return the IP address of the host who sent the current incoming packet + virtual IPAddress remoteIP() + { + return _remoteIP; + }; + // Return the port of the host who sent the current incoming packet + virtual uint16_t remotePort() + { + return _remotePort; + }; }; #endif diff --git a/LibraryPatches/Ethernet3/src/Ethernet3.cpp b/LibraryPatches/Ethernet3/src/Ethernet3.cpp index ec28896..ce0401f 100644 --- a/LibraryPatches/Ethernet3/src/Ethernet3.cpp +++ b/LibraryPatches/Ethernet3/src/Ethernet3.cpp @@ -1,12 +1,12 @@ /* - modified 12 Aug 2013 - by Soohwan Kim (suhwan@wiznet.co.kr) + modified 12 Aug 2013 + by Soohwan Kim (suhwan@wiznet.co.kr) -- 10 Apr. 2015 - Added support for Arduino Ethernet Shield 2 - by Arduino.org team + - 10 Apr. 2015 + Added support for Arduino Ethernet Shield 2 + by Arduino.org team - */ +*/ #include "Ethernet3.h" #include "Dhcp.h" @@ -15,31 +15,37 @@ uint8_t EthernetClass::_state[MAX_SOCK_NUM] = { 0, }; uint16_t EthernetClass::_server_port[MAX_SOCK_NUM] = { 0, }; -void EthernetClass::setRstPin(uint8_t pinRST) { +void EthernetClass::setRstPin(uint8_t pinRST) +{ _pinRST = pinRST; pinMode(_pinRST, OUTPUT); digitalWrite(_pinRST, HIGH); - } -void EthernetClass::setCsPin(uint8_t pinCS) { +} +void EthernetClass::setCsPin(uint8_t pinCS) +{ _pinCS = pinCS; - } +} -void EthernetClass::init(uint8_t maxSockNum) { +void EthernetClass::init(uint8_t maxSockNum) +{ _maxSockNum = maxSockNum; - } +} -uint8_t EthernetClass::softreset() { +uint8_t EthernetClass::softreset() +{ return w5500.softReset(); - } +} -void EthernetClass::hardreset() { - if(_pinRST != 0) { +void EthernetClass::hardreset() +{ + if (_pinRST != 0) + { digitalWrite(_pinRST, LOW); delay(1); digitalWrite(_pinRST, HIGH); delay(150); - } } +} #if defined(WIZ550io_WITH_MACADDRESS) @@ -49,13 +55,13 @@ int EthernetClass::begin(void) // Now store to private var _mac_address //uint8_t mac_address[6] ={0,}; ////// - + _dhcp = new DhcpClass(); // Initialise the basic info w5500.init(_maxSockNum, _pinCS); - w5500.setIPAddress(IPAddress(0,0,0,0).raw_address()); - + w5500.setIPAddress(IPAddress(0, 0, 0, 0).raw_address()); + // KH mod w5500.getMACAddress(_mac_address); ////// @@ -64,13 +70,13 @@ int EthernetClass::begin(void) { _dhcp->setCustomHostname(_customHostname); } - + // Now try to get our config info from a DHCP server // KH mod int ret = _dhcp->beginWithDHCP(_mac_address); ////// - - if(ret == 1) + + if (ret == 1) { // We've successfully found a DHCP server and got our configuration info, so set things // accordingly @@ -79,6 +85,7 @@ int EthernetClass::begin(void) w5500.setSubnetMask(_dhcp->getSubnetMask().raw_address()); _dnsServerAddress = _dhcp->getDnsServerIp(); } + return ret; } @@ -123,21 +130,22 @@ int EthernetClass::begin(uint8_t *mac_address) //uint8_t _mac_address[6] ={0,}; memcpy(_mac_address, mac_address, sizeof(_mac_address)); ////// - + _dhcp = new DhcpClass(); // Initialise the basic info w5500.init(_maxSockNum, _pinCS); w5500.setMACAddress(mac_address); - w5500.setIPAddress(IPAddress(0,0,0,0).raw_address()); + w5500.setIPAddress(IPAddress(0, 0, 0, 0).raw_address()); if (strlen(_customHostname) != 0) { _dhcp->setCustomHostname(_customHostname); } - + // Now try to get our config info from a DHCP server int ret = _dhcp->beginWithDHCP(mac_address); - if(ret == 1) + + if (ret == 1) { // We've successfully found a DHCP server and got our configuration info, so set things // accordingly @@ -157,7 +165,7 @@ void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip) //uint8_t _mac_address[6] ={0,}; memcpy(_mac_address, mac_address, sizeof(_mac_address)); ////// - + IPAddress subnet(255, 255, 255, 0); begin(mac_address, local_ip, subnet); } @@ -169,7 +177,7 @@ void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip, IPAddress su //uint8_t _mac_address[6] ={0,}; memcpy(_mac_address, mac_address, sizeof(_mac_address)); ////// - + // Assume the gateway will be the machine on the same network as the local IP // but with last octet being '1' IPAddress gateway = local_ip; @@ -184,7 +192,7 @@ void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip, IPAddress su //uint8_t _mac_address[6] ={0,}; memcpy(_mac_address, mac_address, sizeof(_mac_address)); ////// - + // Assume the DNS server will be the machine on the same network as the local IP // but with last octet being '1' IPAddress dns_server = local_ip; @@ -192,14 +200,15 @@ void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip, IPAddress su begin(mac_address, local_ip, subnet, gateway, dns_server); } -void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip, IPAddress subnet, IPAddress gateway, IPAddress dns_server) +void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip, IPAddress subnet, IPAddress gateway, + IPAddress dns_server) { // KH mod to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ // Now store to private var //uint8_t _mac_address[6] ={0,}; memcpy(_mac_address, mac_address, sizeof(_mac_address)); ////// - + w5500.init(_maxSockNum, _pinCS); w5500.setMACAddress(mac_address); w5500.setIPAddress(local_ip.raw_address()); @@ -210,15 +219,21 @@ void EthernetClass::begin(uint8_t *mac_address, IPAddress local_ip, IPAddress su #endif -int EthernetClass::maintain(){ +int EthernetClass::maintain() +{ int rc = DHCP_CHECK_NONE; - if(_dhcp != NULL){ + + if (_dhcp != NULL) + { //we have a pointer to dhcp, use it rc = _dhcp->checkLease(); - switch ( rc ){ + + switch ( rc ) + { case DHCP_CHECK_NONE: //nothing done break; + case DHCP_CHECK_RENEW_OK: case DHCP_CHECK_REBIND_OK: //we might have got a new IP. @@ -227,180 +242,203 @@ int EthernetClass::maintain(){ w5500.setSubnetMask(_dhcp->getSubnetMask().raw_address()); _dnsServerAddress = _dhcp->getDnsServerIp(); break; + default: //this is actually a error, it will retry though break; } } + return rc; } -void EthernetClass::WoL(bool wol) { +void EthernetClass::WoL(bool wol) +{ uint8_t val = w5500.readMR(); bitWrite(val, 5, wol); w5500.writeMR(val); - } +} -bool EthernetClass::WoL() { +bool EthernetClass::WoL() +{ uint8_t val = w5500.readMR(); return bitRead(val, 5); - } +} -void EthernetClass::phyMode(phyMode_t mode) { +void EthernetClass::phyMode(phyMode_t mode) +{ uint8_t val = w5500.getPHYCFGR(); bitWrite(val, 6, 1); - if (mode == HALF_DUPLEX_10) { + + if (mode == HALF_DUPLEX_10) + { bitWrite(val, 3, 0); bitWrite(val, 4, 0); bitWrite(val, 5, 0); w5500.setPHYCFGR(val); - } - else if (mode == FULL_DUPLEX_10) { + } + else if (mode == FULL_DUPLEX_10) + { bitWrite(val, 3, 1); bitWrite(val, 4, 0); bitWrite(val, 5, 0); w5500.setPHYCFGR(val); - } - else if (mode == HALF_DUPLEX_100) { + } + else if (mode == HALF_DUPLEX_100) + { bitWrite(val, 3, 0); bitWrite(val, 4, 1); bitWrite(val, 5, 0); w5500.setPHYCFGR(val); - } - else if (mode == FULL_DUPLEX_100) { + } + else if (mode == FULL_DUPLEX_100) + { bitWrite(val, 3, 1); bitWrite(val, 4, 1); bitWrite(val, 5, 0); w5500.setPHYCFGR(val); - } - else if (mode == FULL_DUPLEX_100_AUTONEG) { + } + else if (mode == FULL_DUPLEX_100_AUTONEG) + { bitWrite(val, 3, 0); bitWrite(val, 4, 0); bitWrite(val, 5, 1); w5500.setPHYCFGR(val); - } - else if (mode == POWER_DOWN) { + } + else if (mode == POWER_DOWN) + { bitWrite(val, 3, 0); bitWrite(val, 4, 1); bitWrite(val, 5, 1); w5500.setPHYCFGR(val); - } - else if (mode == ALL_AUTONEG) { + } + else if (mode == ALL_AUTONEG) + { bitWrite(val, 3, 1); bitWrite(val, 4, 1); bitWrite(val, 5, 1); w5500.setPHYCFGR(val); - } + } + bitWrite(val, 7, 0); w5500.setPHYCFGR(val); bitWrite(val, 7, 1); w5500.setPHYCFGR(val); - } +} -void EthernetClass::setHostname(const char* hostname) { +void EthernetClass::setHostname(const char* hostname) +{ memset(_customHostname, 0, 32); memcpy((void*)_customHostname, (void*)hostname, strlen(hostname) >= 31 ? 31 : strlen(hostname)); - } +} -uint8_t EthernetClass::phyState() { +uint8_t EthernetClass::phyState() +{ return w5500.getPHYCFGR(); - } +} -uint8_t EthernetClass::link() { +uint8_t EthernetClass::link() +{ return bitRead(w5500.getPHYCFGR(), 0); - } +} -const char* EthernetClass::linkReport() +const char* EthernetClass::linkReport() { - if (bitRead(w5500.getPHYCFGR(), 0) == 1) + if (bitRead(w5500.getPHYCFGR(), 0) == 1) return "LINK"; - else + else return "NO LINK"; - } +} -uint8_t EthernetClass::speed() +uint8_t EthernetClass::speed() { - if (bitRead(w5500.getPHYCFGR(), 0) == 1) + if (bitRead(w5500.getPHYCFGR(), 0) == 1) { - if (bitRead(w5500.getPHYCFGR(), 1) == 1) + if (bitRead(w5500.getPHYCFGR(), 1) == 1) return 100; - - if (bitRead(w5500.getPHYCFGR(), 1) == 0) + + if (bitRead(w5500.getPHYCFGR(), 1) == 0) return 10; } return 0; } -const char* EthernetClass::speedReport() +const char* EthernetClass::speedReport() { - if (bitRead(w5500.getPHYCFGR(), 0) == 1) + if (bitRead(w5500.getPHYCFGR(), 0) == 1) { - if (bitRead(w5500.getPHYCFGR(), 1) == 1) + if (bitRead(w5500.getPHYCFGR(), 1) == 1) return "100 MB"; - - if (bitRead(w5500.getPHYCFGR(), 1) == 0) + + if (bitRead(w5500.getPHYCFGR(), 1) == 0) return "10 MB"; } return "NO LINK"; } -uint8_t EthernetClass::duplex() +uint8_t EthernetClass::duplex() { - if(bitRead(w5500.getPHYCFGR(), 0) == 1) + if (bitRead(w5500.getPHYCFGR(), 0) == 1) { - if (bitRead(w5500.getPHYCFGR(), 2) == 1) + if (bitRead(w5500.getPHYCFGR(), 2) == 1) return 2; - - if (bitRead(w5500.getPHYCFGR(), 2) == 0) + + if (bitRead(w5500.getPHYCFGR(), 2) == 0) return 1; } return 0; } -const char* EthernetClass::duplexReport() +const char* EthernetClass::duplexReport() { - if (bitRead(w5500.getPHYCFGR(), 0) == 1) + if (bitRead(w5500.getPHYCFGR(), 0) == 1) { - if(bitRead(w5500.getPHYCFGR(), 2) == 1) + if (bitRead(w5500.getPHYCFGR(), 2) == 1) return "FULL DUPLEX"; - - if (bitRead(w5500.getPHYCFGR(), 2) == 0) + + if (bitRead(w5500.getPHYCFGR(), 2) == 0) return "HALF DUPLEX"; } return "NO LINK"; } -void EthernetClass::setRtTimeOut(uint16_t timeout) { +void EthernetClass::setRtTimeOut(uint16_t timeout) +{ w5500.setRetransmissionTime(timeout); - } +} -uint16_t EthernetClass::getRtTimeOut() { +uint16_t EthernetClass::getRtTimeOut() +{ return w5500.getRetransmissionTime(); - } +} -void EthernetClass::setRtCount(uint8_t count) { +void EthernetClass::setRtCount(uint8_t count) +{ w5500.setRetransmissionCount(count); - } +} -uint8_t EthernetClass::getRtCount() { +uint8_t EthernetClass::getRtCount() +{ return w5500.getRetransmissionCount(); - } +} -void EthernetClass::macAddress(uint8_t mac[]) { +void EthernetClass::macAddress(uint8_t mac[]) +{ w5500.getMACAddress(mac); - } +} -const char* EthernetClass::macAddressReport() { +const char* EthernetClass::macAddressReport() +{ uint8_t mac[6]; static char str[18]; w5500.getMACAddress(mac); sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); return str; - } +} IPAddress EthernetClass::localIP() { diff --git a/LibraryPatches/Ethernet3/src/Ethernet3.h b/LibraryPatches/Ethernet3/src/Ethernet3.h index dab54f4..eb7cabc 100644 --- a/LibraryPatches/Ethernet3/src/Ethernet3.h +++ b/LibraryPatches/Ethernet3/src/Ethernet3.h @@ -1,12 +1,12 @@ /* - modified 12 Aug 2013 - by Soohwan Kim (suhwan@wiznet.co.kr) + modified 12 Aug 2013 + by Soohwan Kim (suhwan@wiznet.co.kr) - - 10 Apr. 2015 - Added support for Arduino Ethernet Shield 2 - by Arduino.org team + - 10 Apr. 2015 + Added support for Arduino Ethernet Shield 2 + by Arduino.org team - */ +*/ #ifndef ethernet3_h #define ethernet3_h @@ -17,7 +17,8 @@ #include "EthernetServer.h" #include "Dhcp.h" -enum phyMode_t { +enum phyMode_t +{ HALF_DUPLEX_10, FULL_DUPLEX_10, HALF_DUPLEX_100, @@ -25,101 +26,107 @@ enum phyMode_t { FULL_DUPLEX_100_AUTONEG, POWER_DOWN, ALL_AUTONEG - }; - -class EthernetClass { -private: - IPAddress _dnsServerAddress; - DhcpClass* _dhcp; - char _customHostname[32]; - - // KH add to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ - uint8_t _mac_address[6] ={0,}; - ////// - -public: - uint8_t _maxSockNum; - uint8_t _pinCS; - uint8_t _pinRST; - - static uint8_t _state[MAX_SOCK_NUM]; - static uint16_t _server_port[MAX_SOCK_NUM]; - - EthernetClass() { _dhcp = NULL; _pinCS = 10; _maxSockNum = 8; } - - void setRstPin(uint8_t pinRST = 9); // for WIZ550io or USR-ES1, must set befor Ethernet.begin - void setCsPin(uint8_t pinCS = 10); // must set befor Ethernet.begin - - // Initialize with less sockets but more RX/TX Buffer - // maxSockNum = 1 Socket 0 -> RX/TX Buffer 16k - // maxSockNum = 2 Socket 0, 1 -> RX/TX Buffer 8k - // maxSockNum = 4 Socket 0...3 -> RX/TX Buffer 4k - // maxSockNum = 8 (Standard) all sockets -> RX/TX Buffer 2k - // be carefull of the MAX_SOCK_NUM, because in the moment it can't dynamicly changed - void init(uint8_t maxSockNum = 8); - - uint8_t softreset(); // can set only after Ethernet.begin - void hardreset(); // You need to set the Rst pin +}; + +class EthernetClass +{ + private: + IPAddress _dnsServerAddress; + DhcpClass* _dhcp; + char _customHostname[32]; + + // KH add to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ + uint8_t _mac_address[6] = {0,}; + ////// + + public: + uint8_t _maxSockNum; + uint8_t _pinCS; + uint8_t _pinRST; + + static uint8_t _state[MAX_SOCK_NUM]; + static uint16_t _server_port[MAX_SOCK_NUM]; + + EthernetClass() + { + _dhcp = NULL; + _pinCS = 10; + _maxSockNum = 8; + } + + void setRstPin(uint8_t pinRST = 9); // for WIZ550io or USR-ES1, must set befor Ethernet.begin + void setCsPin(uint8_t pinCS = 10); // must set befor Ethernet.begin + + // Initialize with less sockets but more RX/TX Buffer + // maxSockNum = 1 Socket 0 -> RX/TX Buffer 16k + // maxSockNum = 2 Socket 0, 1 -> RX/TX Buffer 8k + // maxSockNum = 4 Socket 0...3 -> RX/TX Buffer 4k + // maxSockNum = 8 (Standard) all sockets -> RX/TX Buffer 2k + // be carefull of the MAX_SOCK_NUM, because in the moment it can't dynamicly changed + void init(uint8_t maxSockNum = 8); + + uint8_t softreset(); // can set only after Ethernet.begin + void hardreset(); // You need to set the Rst pin #if defined(WIZ550io_WITH_MACADDRESS) - // Initialize function when use the ioShield serise (included WIZ550io) - // WIZ550io has a MAC address which is written after reset. - // Default IP, Gateway and subnet address are also writen. - // so, It needs some initial time. please refer WIZ550io Datasheet in details. - int begin(void); - void begin(IPAddress local_ip); - void begin(IPAddress local_ip, IPAddress subnet); - void begin(IPAddress local_ip, IPAddress subnet, IPAddress gateway); - void begin(IPAddress local_ip, IPAddress subnet, IPAddress gateway, IPAddress dns_server); + // Initialize function when use the ioShield serise (included WIZ550io) + // WIZ550io has a MAC address which is written after reset. + // Default IP, Gateway and subnet address are also writen. + // so, It needs some initial time. please refer WIZ550io Datasheet in details. + int begin(void); + void begin(IPAddress local_ip); + void begin(IPAddress local_ip, IPAddress subnet); + void begin(IPAddress local_ip, IPAddress subnet, IPAddress gateway); + void begin(IPAddress local_ip, IPAddress subnet, IPAddress gateway, IPAddress dns_server); #else - // Initialize the Ethernet shield to use the provided MAC address and gain the rest of the - // configuration through DHCP. - // Returns 0 if the DHCP configuration failed, and 1 if it succeeded - int begin(uint8_t *mac_address); - void begin(uint8_t *mac_address, IPAddress local_ip); - void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress subnet); - void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress subnet, IPAddress gateway); - void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress subnet, IPAddress gateway, IPAddress dns_server); + // Initialize the Ethernet shield to use the provided MAC address and gain the rest of the + // configuration through DHCP. + // Returns 0 if the DHCP configuration failed, and 1 if it succeeded + int begin(uint8_t *mac_address); + void begin(uint8_t *mac_address, IPAddress local_ip); + void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress subnet); + void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress subnet, IPAddress gateway); + void begin(uint8_t *mac_address, IPAddress local_ip, IPAddress subnet, IPAddress gateway, IPAddress dns_server); #endif - int maintain(); - void WoL(bool wol); // set Wake on LAN - bool WoL(); // get the WoL state - void phyMode(phyMode_t mode); // set PHYCFGR - uint8_t phyState(); // returns the PHYCFGR - uint8_t link(); // returns the linkstate, 1 = linked, 0 = no link - const char* linkReport(); // returns the linkstate as a string - uint8_t speed(); // returns speed in MB/s - const char* speedReport(); // returns speed as a string - uint8_t duplex(); // returns duplex mode 0 = no link, 1 = Half Duplex, 2 = Full Duplex - const char* duplexReport(); // returns duplex mode as a string - - void setRtTimeOut(uint16_t timeout = 2000); // set the retransmission timout *100us - uint16_t getRtTimeOut(); // get the retransmission timout - void setRtCount(uint8_t count = 8); // set the retransmission count - uint8_t getRtCount(); // get the retransmission count - - void macAddress(uint8_t mac[]); // get the MAC Address - const char* macAddressReport(); // returns the the MAC Address as a string - - void setHostname(const char* hostname); - - // KH add to have similar function to Ethernet lib - // Certainly we can use void macAddress(uint8_t mac[]) to read from W5x00. - void MACAddress(uint8_t *mac_address) - { - memcpy(mac_address, _mac_address, sizeof(_mac_address)); - } - ////// - - IPAddress localIP(); - IPAddress subnetMask(); - IPAddress gatewayIP(); - IPAddress dnsServerIP(); - - friend class EthernetClient; - friend class EthernetServer; + int maintain(); + void WoL(bool wol); // set Wake on LAN + bool WoL(); // get the WoL state + void phyMode(phyMode_t mode); // set PHYCFGR + uint8_t phyState(); // returns the PHYCFGR + uint8_t link(); // returns the linkstate, 1 = linked, 0 = no link + const char* linkReport(); // returns the linkstate as a string + uint8_t speed(); // returns speed in MB/s + const char* speedReport(); // returns speed as a string + uint8_t duplex(); // returns duplex mode 0 = no link, 1 = Half Duplex, 2 = Full Duplex + const char* duplexReport(); // returns duplex mode as a string + + void setRtTimeOut(uint16_t timeout = 2000); // set the retransmission timout *100us + uint16_t getRtTimeOut(); // get the retransmission timout + void setRtCount(uint8_t count = 8); // set the retransmission count + uint8_t getRtCount(); // get the retransmission count + + void macAddress(uint8_t mac[]); // get the MAC Address + const char* macAddressReport(); // returns the the MAC Address as a string + + void setHostname(const char* hostname); + + // KH add to have similar function to Ethernet lib + // Certainly we can use void macAddress(uint8_t mac[]) to read from W5x00. + void MACAddress(uint8_t *mac_address) + { + memcpy(mac_address, _mac_address, sizeof(_mac_address)); + } + ////// + + IPAddress localIP(); + IPAddress subnetMask(); + IPAddress gatewayIP(); + IPAddress dnsServerIP(); + + friend class EthernetClient; + friend class EthernetServer; }; extern EthernetClass Ethernet; diff --git a/LibraryPatches/EthernetLarge/src/EthernetLarge.cpp b/LibraryPatches/EthernetLarge/src/EthernetLarge.cpp index 4357b3c..9f9fe0c 100644 --- a/LibraryPatches/EthernetLarge/src/EthernetLarge.cpp +++ b/LibraryPatches/EthernetLarge/src/EthernetLarge.cpp @@ -9,17 +9,17 @@ Version: 1.0.9 Copyright 2018 Paul Stoffregen - + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -34,11 +34,11 @@ 1.0.2 K Hoang 20/02/2020 Add support to UIPEthernet library for ENC28J60 1.0.3 K Hoang 23/02/2020 Add support to SAM DUE / SAMD21 boards 1.0.4 K Hoang 16/04/2020 Add support to SAMD51 boards - 1.0.5 K Hoang 24/04/2020 Add support to nRF52 boards, such as AdaFruit Feather nRF52832, nRF52840 Express, BlueFruit Sense, - Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B30_ublox, etc. + 1.0.5 K Hoang 24/04/2020 Add support to nRF52 boards, such as AdaFruit Feather nRF52832, nRF52840 Express, BlueFruit Sense, + Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B30_ublox, etc. More Custom Ethernet libraries supported such as Ethernet2, Ethernet3, EthernetLarge - 1.0.6 K Hoang 27/04/2020 Add support to ESP32/ESP8266 boards - 1.0.7 K Hoang 30/04/2020 Add ENC28J60 support to ESP32/ESP8266 boards + 1.0.6 K Hoang 27/04/2020 Add support to ESP32/ESP8266 boards + 1.0.7 K Hoang 30/04/2020 Add ENC28J60 support to ESP32/ESP8266 boards 1.0.8 K Hoang 12/05/2020 Fix W5x00 support for ESP8266 boards. 1.0.9 K Hoang 15/05/2020 Add EthernetWrapper.h for easier W5x00 support as well as more Ethernet libs in the future. *****************************************************************************************************************************/ @@ -54,38 +54,38 @@ IPAddress EthernetClass::_dnsServerAddress; DhcpClass* EthernetClass::_dhcp = NULL; // KH -void EthernetClass::setRstPin(uint8_t pinRST) +void EthernetClass::setRstPin(uint8_t pinRST) { _pinRST = pinRST; pinMode(_pinRST, OUTPUT); digitalWrite(_pinRST, HIGH); } -void EthernetClass::setCsPin(uint8_t pinCS) +void EthernetClass::setCsPin(uint8_t pinCS) { _pinCS = pinCS; W5100.setSS(pinCS); - -#if ( ETHERNET_DEBUG > 0 ) + +#if ( ETHERNET_DEBUG > 0 ) Serial.print("Input pinCS = "); - Serial.println(pinCS); + Serial.println(pinCS); Serial.print("_pinCS = "); - Serial.println(_pinCS); -#endif + Serial.println(_pinCS); +#endif } -void EthernetClass::initMaxSockNum(uint8_t maxSockNum) +void EthernetClass::initMaxSockNum(uint8_t maxSockNum) { _maxSockNum = maxSockNum; } -uint8_t EthernetClass::softreset() +uint8_t EthernetClass::softreset() { return W5100.softReset(); } -void EthernetClass::hardreset() +void EthernetClass::hardreset() { - if(_pinRST != 0) + if (_pinRST != 0) { digitalWrite(_pinRST, LOW); delay(1); @@ -96,222 +96,249 @@ void EthernetClass::hardreset() int EthernetClass::begin(uint8_t *mac, unsigned long timeout, unsigned long responseTimeout) { - static DhcpClass s_dhcp; - _dhcp = &s_dhcp; + static DhcpClass s_dhcp; + _dhcp = &s_dhcp; -#if ( ETHERNET_DEBUG > 0 ) +#if ( ETHERNET_DEBUG > 0 ) Serial.print("_pinCS = "); - Serial.print(_pinCS); + Serial.print(_pinCS); #endif - - // Initialise the basic info - if (W5100.init() == 0) - return 0; - - - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - W5100.setMACAddress(mac); - W5100.setIPAddress(IPAddress(0,0,0,0).raw_address()); - SPI.endTransaction(); - - // Now try to get our config info from a DHCP server - int ret = _dhcp->beginWithDHCP(mac, timeout, responseTimeout); - if (ret == 1) { - // We've successfully found a DHCP server and got our configuration - // info, so set things accordingly - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - W5100.setIPAddress(_dhcp->getLocalIp().raw_address()); - W5100.setGatewayIp(_dhcp->getGatewayIp().raw_address()); - W5100.setSubnetMask(_dhcp->getSubnetMask().raw_address()); - SPI.endTransaction(); - _dnsServerAddress = _dhcp->getDnsServerIp(); - socketPortRand(micros()); - } - return ret; + + // Initialise the basic info + if (W5100.init() == 0) + return 0; + + + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.setMACAddress(mac); + W5100.setIPAddress(IPAddress(0, 0, 0, 0).raw_address()); + SPI.endTransaction(); + + // Now try to get our config info from a DHCP server + int ret = _dhcp->beginWithDHCP(mac, timeout, responseTimeout); + + if (ret == 1) + { + // We've successfully found a DHCP server and got our configuration + // info, so set things accordingly + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.setIPAddress(_dhcp->getLocalIp().raw_address()); + W5100.setGatewayIp(_dhcp->getGatewayIp().raw_address()); + W5100.setSubnetMask(_dhcp->getSubnetMask().raw_address()); + SPI.endTransaction(); + _dnsServerAddress = _dhcp->getDnsServerIp(); + socketPortRand(micros()); + } + + return ret; } void EthernetClass::begin(uint8_t *mac, IPAddress ip) { - // Assume the DNS server will be the machine on the same network as the local IP - // but with last octet being '1' - IPAddress dns = ip; - dns[3] = 1; - begin(mac, ip, dns); + // Assume the DNS server will be the machine on the same network as the local IP + // but with last octet being '1' + IPAddress dns = ip; + dns[3] = 1; + begin(mac, ip, dns); } void EthernetClass::begin(uint8_t *mac, IPAddress ip, IPAddress dns) { - // Assume the gateway will be the machine on the same network as the local IP - // but with last octet being '1' - IPAddress gateway = ip; - gateway[3] = 1; - begin(mac, ip, dns, gateway); + // Assume the gateway will be the machine on the same network as the local IP + // but with last octet being '1' + IPAddress gateway = ip; + gateway[3] = 1; + begin(mac, ip, dns, gateway); } void EthernetClass::begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway) { - IPAddress subnet(255, 255, 255, 0); - begin(mac, ip, dns, gateway, subnet); + IPAddress subnet(255, 255, 255, 0); + begin(mac, ip, dns, gateway, subnet); } void EthernetClass::begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) { - // Initialise the basic info - if (W5100.init() == 0) - return; - - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - W5100.setMACAddress(mac); + // Initialise the basic info + if (W5100.init() == 0) + return; + + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.setMACAddress(mac); #if ( defined(ESP8266) || defined(ESP32) ) - W5100.setIPAddress(&ip[0]); - W5100.setGatewayIp(&gateway[0]); - W5100.setSubnetMask(&subnet[0]); + W5100.setIPAddress(&ip[0]); + W5100.setGatewayIp(&gateway[0]); + W5100.setSubnetMask(&subnet[0]); #elif ARDUINO > 106 || TEENSYDUINO > 121 - W5100.setIPAddress(ip._address.bytes); - W5100.setGatewayIp(gateway._address.bytes); - W5100.setSubnetMask(subnet._address.bytes); + W5100.setIPAddress(ip._address.bytes); + W5100.setGatewayIp(gateway._address.bytes); + W5100.setSubnetMask(subnet._address.bytes); #else - W5100.setIPAddress(ip._address); - W5100.setGatewayIp(gateway._address); - W5100.setSubnetMask(subnet._address); + W5100.setIPAddress(ip._address); + W5100.setGatewayIp(gateway._address); + W5100.setSubnetMask(subnet._address); #endif - SPI.endTransaction(); - _dnsServerAddress = dns; + SPI.endTransaction(); + _dnsServerAddress = dns; } void EthernetClass::init(uint8_t sspin) { - W5100.setSS(sspin); + W5100.setSS(sspin); } EthernetLinkStatus EthernetClass::linkStatus() { - switch (W5100.getLinkStatus()) { - case UNKNOWN: return Unknown; - case LINK_ON: return LinkON; - case LINK_OFF: return LinkOFF; - default: return Unknown; - } + switch (W5100.getLinkStatus()) + { + case UNKNOWN: + return Unknown; + + case LINK_ON: + return LinkON; + + case LINK_OFF: + return LinkOFF; + + default: + return Unknown; + } } EthernetHardwareStatus EthernetClass::hardwareStatus() { - switch (W5100.getChip()) { - case 51: return EthernetW5100; - case 52: return EthernetW5200; - case 55: return EthernetW5500; - default: return EthernetNoHardware; - } + switch (W5100.getChip()) + { + case 51: + return EthernetW5100; + + case 52: + return EthernetW5200; + + case 55: + return EthernetW5500; + + default: + return EthernetNoHardware; + } } int EthernetClass::maintain() { - int rc = DHCP_CHECK_NONE; - if (_dhcp != NULL) { - // we have a pointer to dhcp, use it - rc = _dhcp->checkLease(); - switch (rc) - { - case DHCP_CHECK_NONE: - //nothing done - break; - case DHCP_CHECK_RENEW_OK: - case DHCP_CHECK_REBIND_OK: - //we might have got a new IP. - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - W5100.setIPAddress(_dhcp->getLocalIp().raw_address()); - W5100.setGatewayIp(_dhcp->getGatewayIp().raw_address()); - W5100.setSubnetMask(_dhcp->getSubnetMask().raw_address()); - SPI.endTransaction(); - _dnsServerAddress = _dhcp->getDnsServerIp(); - break; - default: - //this is actually an error, it will retry though - break; - } - } - return rc; + int rc = DHCP_CHECK_NONE; + + if (_dhcp != NULL) + { + // we have a pointer to dhcp, use it + rc = _dhcp->checkLease(); + + switch (rc) + { + case DHCP_CHECK_NONE: + //nothing done + break; + + case DHCP_CHECK_RENEW_OK: + case DHCP_CHECK_REBIND_OK: + //we might have got a new IP. + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.setIPAddress(_dhcp->getLocalIp().raw_address()); + W5100.setGatewayIp(_dhcp->getGatewayIp().raw_address()); + W5100.setSubnetMask(_dhcp->getSubnetMask().raw_address()); + SPI.endTransaction(); + _dnsServerAddress = _dhcp->getDnsServerIp(); + break; + + default: + //this is actually an error, it will retry though + break; + } + } + + return rc; } void EthernetClass::MACAddress(uint8_t *mac_address) { - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - W5100.getMACAddress(mac_address); - SPI.endTransaction(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.getMACAddress(mac_address); + SPI.endTransaction(); } IPAddress EthernetClass::localIP() { - IPAddress ret; - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - W5100.getIPAddress(ret.raw_address()); - SPI.endTransaction(); - return ret; + IPAddress ret; + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.getIPAddress(ret.raw_address()); + SPI.endTransaction(); + return ret; } IPAddress EthernetClass::subnetMask() { - IPAddress ret; - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - W5100.getSubnetMask(ret.raw_address()); - SPI.endTransaction(); - return ret; + IPAddress ret; + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.getSubnetMask(ret.raw_address()); + SPI.endTransaction(); + return ret; } IPAddress EthernetClass::gatewayIP() { - IPAddress ret; - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - W5100.getGatewayIp(ret.raw_address()); - SPI.endTransaction(); - return ret; + IPAddress ret; + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.getGatewayIp(ret.raw_address()); + SPI.endTransaction(); + return ret; } void EthernetClass::setMACAddress(const uint8_t *mac_address) { - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - W5100.setMACAddress(mac_address); - SPI.endTransaction(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.setMACAddress(mac_address); + SPI.endTransaction(); } void EthernetClass::setLocalIP(const IPAddress local_ip) { - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - IPAddress ip = local_ip; - W5100.setIPAddress(ip.raw_address()); - SPI.endTransaction(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + IPAddress ip = local_ip; + W5100.setIPAddress(ip.raw_address()); + SPI.endTransaction(); } void EthernetClass::setSubnetMask(const IPAddress subnet) { - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - IPAddress ip = subnet; - W5100.setSubnetMask(ip.raw_address()); - SPI.endTransaction(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + IPAddress ip = subnet; + W5100.setSubnetMask(ip.raw_address()); + SPI.endTransaction(); } void EthernetClass::setGatewayIP(const IPAddress gateway) { - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - IPAddress ip = gateway; - W5100.setGatewayIp(ip.raw_address()); - SPI.endTransaction(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + IPAddress ip = gateway; + W5100.setGatewayIp(ip.raw_address()); + SPI.endTransaction(); } void EthernetClass::setRetransmissionTimeout(uint16_t milliseconds) { - if (milliseconds > 6553) milliseconds = 6553; - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - W5100.setRetransmissionTime(milliseconds * 10); - SPI.endTransaction(); + if (milliseconds > 6553) + milliseconds = 6553; + + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.setRetransmissionTime(milliseconds * 10); + SPI.endTransaction(); } void EthernetClass::setRetransmissionCount(uint8_t num) { - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - W5100.setRetransmissionCount(num); - SPI.endTransaction(); + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + W5100.setRetransmissionCount(num); + SPI.endTransaction(); } diff --git a/LibraryPatches/EthernetLarge/src/EthernetLarge.h b/LibraryPatches/EthernetLarge/src/EthernetLarge.h index 4a18a2d..b071cf6 100644 --- a/LibraryPatches/EthernetLarge/src/EthernetLarge.h +++ b/LibraryPatches/EthernetLarge/src/EthernetLarge.h @@ -9,17 +9,17 @@ Version: 1.0.9 Copyright 2018 Paul Stoffregen - + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -34,11 +34,11 @@ 1.0.2 K Hoang 20/02/2020 Add support to UIPEthernet library for ENC28J60 1.0.3 K Hoang 23/02/2020 Add support to SAM DUE / SAMD21 boards 1.0.4 K Hoang 16/04/2020 Add support to SAMD51 boards - 1.0.5 K Hoang 24/04/2020 Add support to nRF52 boards, such as AdaFruit Feather nRF52832, nRF52840 Express, BlueFruit Sense, - Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B30_ublox, etc. + 1.0.5 K Hoang 24/04/2020 Add support to nRF52 boards, such as AdaFruit Feather nRF52832, nRF52840 Express, BlueFruit Sense, + Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B30_ublox, etc. More Custom Ethernet libraries supported such as Ethernet2, Ethernet3, EthernetLarge - 1.0.6 K Hoang 27/04/2020 Add support to ESP32/ESP8266 boards - 1.0.7 K Hoang 30/04/2020 Add ENC28J60 support to ESP32/ESP8266 boards + 1.0.6 K Hoang 27/04/2020 Add support to ESP32/ESP8266 boards + 1.0.7 K Hoang 30/04/2020 Add ENC28J60 support to ESP32/ESP8266 boards 1.0.8 K Hoang 12/05/2020 Fix W5x00 support for ESP8266 boards. 1.0.9 K Hoang 15/05/2020 Add EthernetWrapper.h for easier W5x00 support as well as more Ethernet libs in the future. *****************************************************************************************************************************/ @@ -74,17 +74,19 @@ #include "Server.h" #include "Udp.h" -enum EthernetLinkStatus { - Unknown, - LinkON, - LinkOFF +enum EthernetLinkStatus +{ + Unknown, + LinkON, + LinkOFF }; -enum EthernetHardwareStatus { - EthernetNoHardware, - EthernetW5100, - EthernetW5200, - EthernetW5500 +enum EthernetHardwareStatus +{ + EthernetNoHardware, + EthernetW5100, + EthernetW5200, + EthernetW5500 }; class EthernetUDP; @@ -92,96 +94,103 @@ class EthernetClient; class EthernetServer; class DhcpClass; -class EthernetClass { -private: - static IPAddress _dnsServerAddress; - static DhcpClass* _dhcp; -public: - // KH - uint8_t _maxSockNum; - uint8_t _pinCS; - uint8_t _pinRST; - - void setRstPin(uint8_t pinRST = 9); // for WIZ550io or USR-ES1, must set befor Ethernet.begin - void setCsPin(uint8_t pinCS = 10); // must set befor Ethernet.begin - - // Initialize with less sockets but more RX/TX Buffer - // maxSockNum = 1 Socket 0 -> RX/TX Buffer 16k - // maxSockNum = 2 Socket 0, 1 -> RX/TX Buffer 8k - // maxSockNum = 4 Socket 0...3 -> RX/TX Buffer 4k - // maxSockNum = 8 (Standard) all sockets -> RX/TX Buffer 2k - // be carefull of the MAX_SOCK_NUM, because in the moment it can't dynamicly changed - void initMaxSockNum(uint8_t maxSockNum = 8); - - uint8_t softreset(); // can set only after Ethernet.begin - void hardreset(); // You need to set the Rst pin - - // Initialise the Ethernet shield to use the provided MAC address and - // gain the rest of the configuration through DHCP. - // Returns 0 if the DHCP configuration failed, and 1 if it succeeded - int begin(uint8_t *mac, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); - int maintain(); - EthernetLinkStatus linkStatus(); - EthernetHardwareStatus hardwareStatus(); - - // Manual configuration - void begin(uint8_t *mac, IPAddress ip); - void begin(uint8_t *mac, IPAddress ip, IPAddress dns); - void begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway); - void begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet); - void init(uint8_t sspin = 10); - - void MACAddress(uint8_t *mac_address); - IPAddress localIP(); - IPAddress subnetMask(); - IPAddress gatewayIP(); - IPAddress dnsServerIP() { return _dnsServerAddress; } - - void setMACAddress(const uint8_t *mac_address); - void setLocalIP(const IPAddress local_ip); - void setSubnetMask(const IPAddress subnet); - void setGatewayIP(const IPAddress gateway); - void setDnsServerIP(const IPAddress dns_server) { _dnsServerAddress = dns_server; } - void setRetransmissionTimeout(uint16_t milliseconds); - void setRetransmissionCount(uint8_t num); - - friend class EthernetClient; - friend class EthernetServer; - friend class EthernetUDP; -private: - // Opens a socket(TCP or UDP or IP_RAW mode) - uint8_t socketBegin(uint8_t protocol, uint16_t port); - uint8_t socketBeginMulticast(uint8_t protocol, IPAddress ip,uint16_t port); - uint8_t socketStatus(uint8_t s); - // Close socket - void socketClose(uint8_t s); - // Establish TCP connection (Active connection) - void socketConnect(uint8_t s, uint8_t * addr, uint16_t port); - // disconnect the connection - void socketDisconnect(uint8_t s); - // Establish TCP connection (Passive connection) - uint8_t socketListen(uint8_t s); - // Send data (TCP) - uint16_t socketSend(uint8_t s, const uint8_t * buf, uint16_t len); - uint16_t socketSendAvailable(uint8_t s); - // Receive data (TCP) - int socketRecv(uint8_t s, uint8_t * buf, int16_t len); - uint16_t socketRecvAvailable(uint8_t s); - uint8_t socketPeek(uint8_t s); - // sets up a UDP datagram, the data for which will be provided by one - // or more calls to bufferData and then finally sent with sendUDP. - // return true if the datagram was successfully set up, or false if there was an error - bool socketStartUDP(uint8_t s, uint8_t* addr, uint16_t port); - // copy up to len bytes of data from buf into a UDP datagram to be - // sent later by sendUDP. Allows datagrams to be built up from a series of bufferData calls. - // return Number of bytes successfully buffered - uint16_t socketBufferData(uint8_t s, uint16_t offset, const uint8_t* buf, uint16_t len); - // Send a UDP datagram built up from a sequence of startUDP followed by one or more - // calls to bufferData. - // return true if the datagram was successfully sent, or false if there was an error - bool socketSendUDP(uint8_t s); - // Initialize the "random" source port number - void socketPortRand(uint16_t n); +class EthernetClass +{ + private: + static IPAddress _dnsServerAddress; + static DhcpClass* _dhcp; + public: + // KH + uint8_t _maxSockNum; + uint8_t _pinCS; + uint8_t _pinRST; + + void setRstPin(uint8_t pinRST = 9); // for WIZ550io or USR-ES1, must set befor Ethernet.begin + void setCsPin(uint8_t pinCS = 10); // must set befor Ethernet.begin + + // Initialize with less sockets but more RX/TX Buffer + // maxSockNum = 1 Socket 0 -> RX/TX Buffer 16k + // maxSockNum = 2 Socket 0, 1 -> RX/TX Buffer 8k + // maxSockNum = 4 Socket 0...3 -> RX/TX Buffer 4k + // maxSockNum = 8 (Standard) all sockets -> RX/TX Buffer 2k + // be carefull of the MAX_SOCK_NUM, because in the moment it can't dynamicly changed + void initMaxSockNum(uint8_t maxSockNum = 8); + + uint8_t softreset(); // can set only after Ethernet.begin + void hardreset(); // You need to set the Rst pin + + // Initialise the Ethernet shield to use the provided MAC address and + // gain the rest of the configuration through DHCP. + // Returns 0 if the DHCP configuration failed, and 1 if it succeeded + int begin(uint8_t *mac, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); + int maintain(); + EthernetLinkStatus linkStatus(); + EthernetHardwareStatus hardwareStatus(); + + // Manual configuration + void begin(uint8_t *mac, IPAddress ip); + void begin(uint8_t *mac, IPAddress ip, IPAddress dns); + void begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway); + void begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet); + void init(uint8_t sspin = 10); + + void MACAddress(uint8_t *mac_address); + IPAddress localIP(); + IPAddress subnetMask(); + IPAddress gatewayIP(); + IPAddress dnsServerIP() + { + return _dnsServerAddress; + } + + void setMACAddress(const uint8_t *mac_address); + void setLocalIP(const IPAddress local_ip); + void setSubnetMask(const IPAddress subnet); + void setGatewayIP(const IPAddress gateway); + void setDnsServerIP(const IPAddress dns_server) + { + _dnsServerAddress = dns_server; + } + void setRetransmissionTimeout(uint16_t milliseconds); + void setRetransmissionCount(uint8_t num); + + friend class EthernetClient; + friend class EthernetServer; + friend class EthernetUDP; + private: + // Opens a socket(TCP or UDP or IP_RAW mode) + uint8_t socketBegin(uint8_t protocol, uint16_t port); + uint8_t socketBeginMulticast(uint8_t protocol, IPAddress ip, uint16_t port); + uint8_t socketStatus(uint8_t s); + // Close socket + void socketClose(uint8_t s); + // Establish TCP connection (Active connection) + void socketConnect(uint8_t s, uint8_t * addr, uint16_t port); + // disconnect the connection + void socketDisconnect(uint8_t s); + // Establish TCP connection (Passive connection) + uint8_t socketListen(uint8_t s); + // Send data (TCP) + uint16_t socketSend(uint8_t s, const uint8_t * buf, uint16_t len); + uint16_t socketSendAvailable(uint8_t s); + // Receive data (TCP) + int socketRecv(uint8_t s, uint8_t * buf, int16_t len); + uint16_t socketRecvAvailable(uint8_t s); + uint8_t socketPeek(uint8_t s); + // sets up a UDP datagram, the data for which will be provided by one + // or more calls to bufferData and then finally sent with sendUDP. + // return true if the datagram was successfully set up, or false if there was an error + bool socketStartUDP(uint8_t s, uint8_t* addr, uint16_t port); + // copy up to len bytes of data from buf into a UDP datagram to be + // sent later by sendUDP. Allows datagrams to be built up from a series of bufferData calls. + // return Number of bytes successfully buffered + uint16_t socketBufferData(uint8_t s, uint16_t offset, const uint8_t* buf, uint16_t len); + // Send a UDP datagram built up from a sequence of startUDP followed by one or more + // calls to bufferData. + // return true if the datagram was successfully sent, or false if there was an error + bool socketSendUDP(uint8_t s); + // Initialize the "random" source port number + void socketPortRand(uint16_t n); }; extern EthernetClass Ethernet; @@ -189,170 +198,206 @@ extern EthernetClass Ethernet; #define UDP_TX_PACKET_MAX_SIZE 24 -class EthernetUDP : public UDP { -private: - uint16_t _port; // local port to listen on - IPAddress _remoteIP; // remote IP address for the incoming packet whilst it's being processed - uint16_t _remotePort; // remote port for the incoming packet whilst it's being processed - uint16_t _offset; // offset into the packet being sent - -protected: - uint8_t sockindex; - uint16_t _remaining; // remaining bytes of incoming packet yet to be processed - -public: - EthernetUDP() : sockindex(MAX_SOCK_NUM) {} // Constructor - virtual uint8_t begin(uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use - virtual uint8_t beginMulticast(IPAddress, uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use - virtual void stop(); // Finish with the UDP socket - - // Sending UDP packets - - // Start building up a packet to send to the remote host specific in ip and port - // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port - virtual int beginPacket(IPAddress ip, uint16_t port); - // Start building up a packet to send to the remote host specific in host and port - // Returns 1 if successful, 0 if there was a problem resolving the hostname or port - virtual int beginPacket(const char *host, uint16_t port); - // Finish off this packet and send it - // Returns 1 if the packet was sent successfully, 0 if there was an error - virtual int endPacket(); - // Write a single byte into the packet - virtual size_t write(uint8_t); - // Write size bytes from buffer into the packet - virtual size_t write(const uint8_t *buffer, size_t size); - - using Print::write; - - // Start processing the next available incoming packet - // Returns the size of the packet in bytes, or 0 if no packets are available - virtual int parsePacket(); - // Number of bytes remaining in the current packet - virtual int available(); - // Read a single byte from the current packet - virtual int read(); - // Read up to len bytes from the current packet and place them into buffer - // Returns the number of bytes read, or 0 if none are available - virtual int read(unsigned char* buffer, size_t len); - // Read up to len characters from the current packet and place them into buffer - // Returns the number of characters read, or 0 if none are available - virtual int read(char* buffer, size_t len) { return read((unsigned char*)buffer, len); }; - // Return the next byte from the current packet without moving on to the next byte - virtual int peek(); - virtual void flush(); // Finish reading the current packet - - // Return the IP address of the host who sent the current incoming packet - virtual IPAddress remoteIP() { return _remoteIP; }; - // Return the port of the host who sent the current incoming packet - virtual uint16_t remotePort() { return _remotePort; }; - virtual uint16_t localPort() { return _port; } +class EthernetUDP : public UDP +{ + private: + uint16_t _port; // local port to listen on + IPAddress _remoteIP; // remote IP address for the incoming packet whilst it's being processed + uint16_t _remotePort; // remote port for the incoming packet whilst it's being processed + uint16_t _offset; // offset into the packet being sent + + protected: + uint8_t sockindex; + uint16_t _remaining; // remaining bytes of incoming packet yet to be processed + + public: + EthernetUDP() : sockindex(MAX_SOCK_NUM) {} // Constructor + virtual uint8_t begin( + uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use + virtual uint8_t beginMulticast(IPAddress, + uint16_t); // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use + virtual void stop(); // Finish with the UDP socket + + // Sending UDP packets + + // Start building up a packet to send to the remote host specific in ip and port + // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port + virtual int beginPacket(IPAddress ip, uint16_t port); + // Start building up a packet to send to the remote host specific in host and port + // Returns 1 if successful, 0 if there was a problem resolving the hostname or port + virtual int beginPacket(const char *host, uint16_t port); + // Finish off this packet and send it + // Returns 1 if the packet was sent successfully, 0 if there was an error + virtual int endPacket(); + // Write a single byte into the packet + virtual size_t write(uint8_t); + // Write size bytes from buffer into the packet + virtual size_t write(const uint8_t *buffer, size_t size); + + using Print::write; + + // Start processing the next available incoming packet + // Returns the size of the packet in bytes, or 0 if no packets are available + virtual int parsePacket(); + // Number of bytes remaining in the current packet + virtual int available(); + // Read a single byte from the current packet + virtual int read(); + // Read up to len bytes from the current packet and place them into buffer + // Returns the number of bytes read, or 0 if none are available + virtual int read(unsigned char* buffer, size_t len); + // Read up to len characters from the current packet and place them into buffer + // Returns the number of characters read, or 0 if none are available + virtual int read(char* buffer, size_t len) + { + return read((unsigned char*)buffer, len); + }; + // Return the next byte from the current packet without moving on to the next byte + virtual int peek(); + virtual void flush(); // Finish reading the current packet + + // Return the IP address of the host who sent the current incoming packet + virtual IPAddress remoteIP() + { + return _remoteIP; + }; + // Return the port of the host who sent the current incoming packet + virtual uint16_t remotePort() + { + return _remotePort; + }; + virtual uint16_t localPort() + { + return _port; + } }; -class EthernetClient : public Client { -public: - EthernetClient() : sockindex(MAX_SOCK_NUM), _timeout(1000) { } - EthernetClient(uint8_t s) : sockindex(s), _timeout(1000) { } - - uint8_t status(); - virtual int connect(IPAddress ip, uint16_t port); - virtual int connect(const char *host, uint16_t port); - virtual int availableForWrite(void); - virtual size_t write(uint8_t); - virtual size_t write(const uint8_t *buf, size_t size); - virtual int available(); - virtual int read(); - virtual int read(uint8_t *buf, size_t size); - virtual int peek(); - virtual void flush(); - virtual void stop(); - virtual uint8_t connected(); - virtual operator bool() { return sockindex < MAX_SOCK_NUM; } - virtual bool operator==(const bool value) { return bool() == value; } - virtual bool operator!=(const bool value) { return bool() != value; } - virtual bool operator==(const EthernetClient&); - virtual bool operator!=(const EthernetClient& rhs) { return !this->operator==(rhs); } - uint8_t getSocketNumber() const { return sockindex; } - virtual uint16_t localPort(); - virtual IPAddress remoteIP(); - virtual uint16_t remotePort(); - virtual void setConnectionTimeout(uint16_t timeout) { _timeout = timeout; } - - friend class EthernetServer; - - using Print::write; - -private: - uint8_t sockindex; // MAX_SOCK_NUM means client not in use - uint16_t _timeout; +class EthernetClient : public Client +{ + public: + EthernetClient() : sockindex(MAX_SOCK_NUM), _timeout(1000) { } + EthernetClient(uint8_t s) : sockindex(s), _timeout(1000) { } + + uint8_t status(); + virtual int connect(IPAddress ip, uint16_t port); + virtual int connect(const char *host, uint16_t port); + virtual int availableForWrite(void); + virtual size_t write(uint8_t); + virtual size_t write(const uint8_t *buf, size_t size); + virtual int available(); + virtual int read(); + virtual int read(uint8_t *buf, size_t size); + virtual int peek(); + virtual void flush(); + virtual void stop(); + virtual uint8_t connected(); + virtual operator bool() + { + return sockindex < MAX_SOCK_NUM; + } + virtual bool operator==(const bool value) + { + return bool() == value; + } + virtual bool operator!=(const bool value) + { + return bool() != value; + } + virtual bool operator==(const EthernetClient&); + virtual bool operator!=(const EthernetClient& rhs) + { + return !this->operator==(rhs); + } + uint8_t getSocketNumber() const + { + return sockindex; + } + virtual uint16_t localPort(); + virtual IPAddress remoteIP(); + virtual uint16_t remotePort(); + virtual void setConnectionTimeout(uint16_t timeout) + { + _timeout = timeout; + } + + friend class EthernetServer; + + using Print::write; + + private: + uint8_t sockindex; // MAX_SOCK_NUM means client not in use + uint16_t _timeout; }; -class EthernetServer : public Server { -private: - uint16_t _port; -public: - EthernetServer(uint16_t port) : _port(port) { } - EthernetClient available(); - EthernetClient accept(); - virtual void begin(); - virtual size_t write(uint8_t); - virtual size_t write(const uint8_t *buf, size_t size); - virtual operator bool(); - using Print::write; - //void statusreport(); - - // TODO: make private when socket allocation moves to EthernetClass - static uint16_t server_port[MAX_SOCK_NUM]; +class EthernetServer : public Server +{ + private: + uint16_t _port; + public: + EthernetServer(uint16_t port) : _port(port) { } + EthernetClient available(); + EthernetClient accept(); + virtual void begin(); + virtual size_t write(uint8_t); + virtual size_t write(const uint8_t *buf, size_t size); + virtual operator bool(); + using Print::write; + //void statusreport(); + + // TODO: make private when socket allocation moves to EthernetClass + static uint16_t server_port[MAX_SOCK_NUM]; }; -class DhcpClass { -private: - uint32_t _dhcpInitialTransactionId; - uint32_t _dhcpTransactionId; - uint8_t _dhcpMacAddr[6]; +class DhcpClass +{ + private: + uint32_t _dhcpInitialTransactionId; + uint32_t _dhcpTransactionId; + uint8_t _dhcpMacAddr[6]; #ifdef __arm__ - uint8_t _dhcpLocalIp[4] __attribute__((aligned(4))); - uint8_t _dhcpSubnetMask[4] __attribute__((aligned(4))); - uint8_t _dhcpGatewayIp[4] __attribute__((aligned(4))); - uint8_t _dhcpDhcpServerIp[4] __attribute__((aligned(4))); - uint8_t _dhcpDnsServerIp[4] __attribute__((aligned(4))); + uint8_t _dhcpLocalIp[4] __attribute__((aligned(4))); + uint8_t _dhcpSubnetMask[4] __attribute__((aligned(4))); + uint8_t _dhcpGatewayIp[4] __attribute__((aligned(4))); + uint8_t _dhcpDhcpServerIp[4] __attribute__((aligned(4))); + uint8_t _dhcpDnsServerIp[4] __attribute__((aligned(4))); #else - uint8_t _dhcpLocalIp[4]; - uint8_t _dhcpSubnetMask[4]; - uint8_t _dhcpGatewayIp[4]; - uint8_t _dhcpDhcpServerIp[4]; - uint8_t _dhcpDnsServerIp[4]; + uint8_t _dhcpLocalIp[4]; + uint8_t _dhcpSubnetMask[4]; + uint8_t _dhcpGatewayIp[4]; + uint8_t _dhcpDhcpServerIp[4]; + uint8_t _dhcpDnsServerIp[4]; #endif - uint32_t _dhcpLeaseTime; - uint32_t _dhcpT1, _dhcpT2; - uint32_t _renewInSec; - uint32_t _rebindInSec; - unsigned long _timeout; - unsigned long _responseTimeout; - unsigned long _lastCheckLeaseMillis; - uint8_t _dhcp_state; - EthernetUDP _dhcpUdpSocket; - - int request_DHCP_lease(); - void reset_DHCP_lease(); - void presend_DHCP(); - void send_DHCP_MESSAGE(uint8_t, uint16_t); - void printByte(char *, uint8_t); - - uint8_t parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId); -public: - IPAddress getLocalIp(); - IPAddress getSubnetMask(); - IPAddress getGatewayIp(); - IPAddress getDhcpServerIp(); - IPAddress getDnsServerIp(); - - int beginWithDHCP(uint8_t *, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); - int checkLease(); + uint32_t _dhcpLeaseTime; + uint32_t _dhcpT1, _dhcpT2; + uint32_t _renewInSec; + uint32_t _rebindInSec; + unsigned long _timeout; + unsigned long _responseTimeout; + unsigned long _lastCheckLeaseMillis; + uint8_t _dhcp_state; + EthernetUDP _dhcpUdpSocket; + + int request_DHCP_lease(); + void reset_DHCP_lease(); + void presend_DHCP(); + void send_DHCP_MESSAGE(uint8_t, uint16_t); + void printByte(char *, uint8_t); + + uint8_t parseDHCPResponse(unsigned long responseTimeout, uint32_t& transactionId); + public: + IPAddress getLocalIp(); + IPAddress getSubnetMask(); + IPAddress getGatewayIp(); + IPAddress getDhcpServerIp(); + IPAddress getDnsServerIp(); + + int beginWithDHCP(uint8_t *, unsigned long timeout = 60000, unsigned long responseTimeout = 4000); + int checkLease(); }; diff --git a/LibraryPatches/EthernetLarge/src/EthernetServer.cpp b/LibraryPatches/EthernetLarge/src/EthernetServer.cpp index a77b569..63d8436 100644 --- a/LibraryPatches/EthernetLarge/src/EthernetServer.cpp +++ b/LibraryPatches/EthernetLarge/src/EthernetServer.cpp @@ -9,17 +9,17 @@ Version: 1.0.9 Copyright 2018 Paul Stoffregen - + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -34,11 +34,11 @@ 1.0.2 K Hoang 20/02/2020 Add support to UIPEthernet library for ENC28J60 1.0.3 K Hoang 23/02/2020 Add support to SAM DUE / SAMD21 boards 1.0.4 K Hoang 16/04/2020 Add support to SAMD51 boards - 1.0.5 K Hoang 24/04/2020 Add support to nRF52 boards, such as AdaFruit Feather nRF52832, nRF52840 Express, BlueFruit Sense, - Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B30_ublox, etc. + 1.0.5 K Hoang 24/04/2020 Add support to nRF52 boards, such as AdaFruit Feather nRF52832, nRF52840 Express, BlueFruit Sense, + Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B30_ublox, etc. More Custom Ethernet libraries supported such as Ethernet2, Ethernet3, EthernetLarge - 1.0.6 K Hoang 27/04/2020 Add support to ESP32/ESP8266 boards - 1.0.7 K Hoang 30/04/2020 Add ENC28J60 support to ESP32/ESP8266 boards + 1.0.6 K Hoang 27/04/2020 Add support to ESP32/ESP8266 boards + 1.0.7 K Hoang 30/04/2020 Add ENC28J60 support to ESP32/ESP8266 boards 1.0.8 K Hoang 12/05/2020 Fix W5x00 support for ESP8266 boards. 1.0.9 K Hoang 15/05/2020 Add EthernetWrapper.h for easier W5x00 support as well as more Ethernet libs in the future. *****************************************************************************************************************************/ @@ -52,189 +52,269 @@ uint16_t EthernetServer::server_port[MAX_SOCK_NUM]; void EthernetServer::begin() { - uint8_t sockindex = Ethernet.socketBegin(SnMR::TCP, _port); - if (sockindex < MAX_SOCK_NUM) { - if (Ethernet.socketListen(sockindex)) { - server_port[sockindex] = _port; - } else { - Ethernet.socketDisconnect(sockindex); - } - } + uint8_t sockindex = Ethernet.socketBegin(SnMR::TCP, _port); + + if (sockindex < MAX_SOCK_NUM) + { + if (Ethernet.socketListen(sockindex)) + { + server_port[sockindex] = _port; + } + else + { + Ethernet.socketDisconnect(sockindex); + } + } } EthernetClient EthernetServer::available() { - bool listening = false; - uint8_t sockindex = MAX_SOCK_NUM; - uint8_t chip, maxindex=MAX_SOCK_NUM; + bool listening = false; + uint8_t sockindex = MAX_SOCK_NUM; + uint8_t chip, maxindex = MAX_SOCK_NUM; + + chip = W5100.getChip(); + + if (!chip) + return EthernetClient(MAX_SOCK_NUM); - chip = W5100.getChip(); - if (!chip) return EthernetClient(MAX_SOCK_NUM); #if MAX_SOCK_NUM > 4 - if (chip == 51) maxindex = 4; // W5100 chip never supports more than 4 sockets + + if (chip == 51) + maxindex = 4; // W5100 chip never supports more than 4 sockets + #endif - for (uint8_t i=0; i < maxindex; i++) - { - if (server_port[i] == _port) - { - uint8_t stat = Ethernet.socketStatus(i); - if (stat == SnSR::ESTABLISHED || stat == SnSR::CLOSE_WAIT) - { - if (Ethernet.socketRecvAvailable(i) > 0) - { - sockindex = i; - } - else - { - // remote host closed connection, our end still open - if (stat == SnSR::CLOSE_WAIT) - { - Ethernet.socketDisconnect(i); - // status becomes LAST_ACK for short time - } - } - } - else if (stat == SnSR::LISTEN) - { - listening = true; - } - else if (stat == SnSR::CLOSED) - { - server_port[i] = 0; - } - } - } - - if (!listening) - { - begin(); - } - - return EthernetClient(sockindex); + for (uint8_t i = 0; i < maxindex; i++) + { + if (server_port[i] == _port) + { + uint8_t stat = Ethernet.socketStatus(i); + + if (stat == SnSR::ESTABLISHED || stat == SnSR::CLOSE_WAIT) + { + if (Ethernet.socketRecvAvailable(i) > 0) + { + sockindex = i; + } + else + { + // remote host closed connection, our end still open + if (stat == SnSR::CLOSE_WAIT) + { + Ethernet.socketDisconnect(i); + // status becomes LAST_ACK for short time + } + } + } + else if (stat == SnSR::LISTEN) + { + listening = true; + } + else if (stat == SnSR::CLOSED) + { + server_port[i] = 0; + } + } + } + + if (!listening) + { + begin(); + } + + return EthernetClient(sockindex); } EthernetClient EthernetServer::accept() { - bool listening = false; - uint8_t sockindex = MAX_SOCK_NUM; - uint8_t chip, maxindex=MAX_SOCK_NUM; + bool listening = false; + uint8_t sockindex = MAX_SOCK_NUM; + uint8_t chip, maxindex = MAX_SOCK_NUM; + + chip = W5100.getChip(); + + if (!chip) + return EthernetClient(MAX_SOCK_NUM); - chip = W5100.getChip(); - if (!chip) return EthernetClient(MAX_SOCK_NUM); #if MAX_SOCK_NUM > 4 - if (chip == 51) maxindex = 4; // W5100 chip never supports more than 4 sockets + + if (chip == 51) + maxindex = 4; // W5100 chip never supports more than 4 sockets + #endif - for (uint8_t i=0; i < maxindex; i++) - { - if (server_port[i] == _port) - { - uint8_t stat = Ethernet.socketStatus(i); - - if (sockindex == MAX_SOCK_NUM && (stat == SnSR::ESTABLISHED || stat == SnSR::CLOSE_WAIT)) - { - // Return the connected client even if no data received. - // Some protocols like FTP expect the server to send the - // first data. - sockindex = i; - server_port[i] = 0; // only return the client once - } - else if (stat == SnSR::LISTEN) + for (uint8_t i = 0; i < maxindex; i++) + { + if (server_port[i] == _port) + { + uint8_t stat = Ethernet.socketStatus(i); + + if (sockindex == MAX_SOCK_NUM && (stat == SnSR::ESTABLISHED || stat == SnSR::CLOSE_WAIT)) + { + // Return the connected client even if no data received. + // Some protocols like FTP expect the server to send the + // first data. + sockindex = i; + server_port[i] = 0; // only return the client once + } + else if (stat == SnSR::LISTEN) { - listening = true; - } - else if (stat == SnSR::CLOSED) - { - server_port[i] = 0; - } - } - } - - if (!listening) - begin(); - - return EthernetClient(sockindex); + listening = true; + } + else if (stat == SnSR::CLOSED) + { + server_port[i] = 0; + } + } + } + + if (!listening) + begin(); + + return EthernetClient(sockindex); } EthernetServer::operator bool() { - uint8_t maxindex=MAX_SOCK_NUM; + uint8_t maxindex = MAX_SOCK_NUM; #if MAX_SOCK_NUM > 4 - if (W5100.getChip() == 51) maxindex = 4; // W5100 chip never supports more than 4 sockets + + if (W5100.getChip() == 51) + maxindex = 4; // W5100 chip never supports more than 4 sockets + #endif - for (uint8_t i=0; i < maxindex; i++) - { - if (server_port[i] == _port) - { - if (Ethernet.socketStatus(i) == SnSR::LISTEN) - { - return true; // server is listening for incoming clients - } - } - } - return false; + for (uint8_t i = 0; i < maxindex; i++) + { + if (server_port[i] == _port) + { + if (Ethernet.socketStatus(i) == SnSR::LISTEN) + { + return true; // server is listening for incoming clients + } + } + } + + return false; } #if 0 void EthernetServer::statusreport() { - Serial.printf("EthernetServer, port=%d\n", _port); - for (uint8_t i=0; i < MAX_SOCK_NUM; i++) { - uint16_t port = server_port[i]; - uint8_t stat = Ethernet.socketStatus(i); - const char *name; - switch (stat) { - case 0x00: name = "CLOSED"; break; - case 0x13: name = "INIT"; break; - case 0x14: name = "LISTEN"; break; - case 0x15: name = "SYNSENT"; break; - case 0x16: name = "SYNRECV"; break; - case 0x17: name = "ESTABLISHED"; break; - case 0x18: name = "FIN_WAIT"; break; - case 0x1A: name = "CLOSING"; break; - case 0x1B: name = "TIME_WAIT"; break; - case 0x1C: name = "CLOSE_WAIT"; break; - case 0x1D: name = "LAST_ACK"; break; - case 0x22: name = "UDP"; break; - case 0x32: name = "IPRAW"; break; - case 0x42: name = "MACRAW"; break; - case 0x5F: name = "PPPOE"; break; - default: name = "???"; - } - int avail = Ethernet.socketRecvAvailable(i); - Serial.printf(" %d: port=%d, status=%s (0x%02X), avail=%d\n", - i, port, name, stat, avail); - } + Serial.printf("EthernetServer, port=%d\n", _port); + + for (uint8_t i = 0; i < MAX_SOCK_NUM; i++) + { + uint16_t port = server_port[i]; + uint8_t stat = Ethernet.socketStatus(i); + const char *name; + + switch (stat) + { + case 0x00: + name = "CLOSED"; + break; + + case 0x13: + name = "INIT"; + break; + + case 0x14: + name = "LISTEN"; + break; + + case 0x15: + name = "SYNSENT"; + break; + + case 0x16: + name = "SYNRECV"; + break; + + case 0x17: + name = "ESTABLISHED"; + break; + + case 0x18: + name = "FIN_WAIT"; + break; + + case 0x1A: + name = "CLOSING"; + break; + + case 0x1B: + name = "TIME_WAIT"; + break; + + case 0x1C: + name = "CLOSE_WAIT"; + break; + + case 0x1D: + name = "LAST_ACK"; + break; + + case 0x22: + name = "UDP"; + break; + + case 0x32: + name = "IPRAW"; + break; + + case 0x42: + name = "MACRAW"; + break; + + case 0x5F: + name = "PPPOE"; + break; + + default: + name = "???"; + } + + int avail = Ethernet.socketRecvAvailable(i); + Serial.printf(" %d: port=%d, status=%s (0x%02X), avail=%d\n", + i, port, name, stat, avail); + } } #endif size_t EthernetServer::write(uint8_t b) { - return write(&b, 1); + return write(&b, 1); } size_t EthernetServer::write(const uint8_t *buffer, size_t size) { - uint8_t chip, maxindex=MAX_SOCK_NUM; + uint8_t chip, maxindex = MAX_SOCK_NUM; + + chip = W5100.getChip(); + + if (!chip) + return 0; - chip = W5100.getChip(); - if (!chip) return 0; #if MAX_SOCK_NUM > 4 - if (chip == 51) maxindex = 4; // W5100 chip never supports more than 4 sockets + + if (chip == 51) + maxindex = 4; // W5100 chip never supports more than 4 sockets + #endif - available(); - - for (uint8_t i=0; i < maxindex; i++) - { - if (server_port[i] == _port) - { - if (Ethernet.socketStatus(i) == SnSR::ESTABLISHED) - { - Ethernet.socketSend(i, buffer, size); - } - } - } - return size; + available(); + + for (uint8_t i = 0; i < maxindex; i++) + { + if (server_port[i] == _port) + { + if (Ethernet.socketStatus(i) == SnSR::ESTABLISHED) + { + Ethernet.socketSend(i, buffer, size); + } + } + } + + return size; } diff --git a/LibraryPatches/EthernetLarge/src/utility/w5100.cpp b/LibraryPatches/EthernetLarge/src/utility/w5100.cpp index 2e2e5a6..c74c12f 100644 --- a/LibraryPatches/EthernetLarge/src/utility/w5100.cpp +++ b/LibraryPatches/EthernetLarge/src/utility/w5100.cpp @@ -10,7 +10,7 @@ Copyright 2018 Paul Stoffregen Copyright (c) 2010 by Cristian Maglie - + This file is free software; you can redistribute it and/or modify it under the terms of either the GNU General Public License version 2 or the GNU Lesser General Public License version 2.1, both as @@ -23,13 +23,13 @@ 1.0.2 K Hoang 20/02/2020 Add support to UIPEthernet library for ENC28J60 1.0.3 K Hoang 23/02/2020 Add support to SAM DUE / SAMD21 boards 1.0.4 K Hoang 16/04/2020 Add support to SAMD51 boards - 1.0.5 K Hoang 24/04/2020 Add support to nRF52 boards, such as AdaFruit Feather nRF52832, nRF52840 Express, BlueFruit Sense, - Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B30_ublox, etc. + 1.0.5 K Hoang 24/04/2020 Add support to nRF52 boards, such as AdaFruit Feather nRF52832, nRF52840 Express, BlueFruit Sense, + Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B30_ublox, etc. More Custom Ethernet libraries supported such as Ethernet2, Ethernet3, EthernetLarge 1.0.6 K Hoang 27/04/2020 Add support to ESP32/ESP8266 boards - 1.0.7 K Hoang 30/04/2020 Add ENC28J60 support to ESP32/ESP8266 boards + 1.0.7 K Hoang 30/04/2020 Add ENC28J60 support to ESP32/ESP8266 boards 1.0.8 K Hoang 12/05/2020 Fix W5x00 support for ESP8266 boards. - 1.0.9 K Hoang 15/05/2020 Add EthernetWrapper.h for easier W5x00 support as well as more Ethernet libs in the future. + 1.0.9 K Hoang 15/05/2020 Add EthernetWrapper.h for easier W5x00 support as well as more Ethernet libs in the future. *****************************************************************************************************************************/ #include @@ -46,71 +46,71 @@ // default SS pin for ethernet, use it. #if defined(PIN_SPI_SS_ETHERNET_LIB) -#define SS_PIN_DEFAULT PIN_SPI_SS_ETHERNET_LIB -//KH -#warning w5100.cpp Use PIN_SPI_SS_ETHERNET_LIB defined, change SS_PIN_DEFAULT to PIN_SPI_SS_ETHERNET_LIB + #define SS_PIN_DEFAULT PIN_SPI_SS_ETHERNET_LIB + //KH + #warning w5100.cpp Use PIN_SPI_SS_ETHERNET_LIB defined, change SS_PIN_DEFAULT to PIN_SPI_SS_ETHERNET_LIB -// MKR boards default to pin 5 for MKR ETH -// Pins 8-10 are MOSI/SCK/MISO on MRK, so don't use pin 10 + // MKR boards default to pin 5 for MKR ETH + // Pins 8-10 are MOSI/SCK/MISO on MRK, so don't use pin 10 #elif defined(USE_ARDUINO_MKR_PIN_LAYOUT) || defined(ARDUINO_SAMD_MKRZERO) || defined(ARDUINO_SAMD_MKR1000) || defined(ARDUINO_SAMD_MKRFox1200) || defined(ARDUINO_SAMD_MKRGSM1400) || defined(ARDUINO_SAMD_MKRWAN1300) -#define SS_PIN_DEFAULT 5 -//KH -#warning w5100.cpp Use MKR, change SS_PIN_DEFAULT to 5 + #define SS_PIN_DEFAULT 5 + //KH + #warning w5100.cpp Use MKR, change SS_PIN_DEFAULT to 5 -// For boards using AVR, assume shields with SS on pin 10 -// will be used. This allows for Arduino Mega (where -// SS is pin 53) and Arduino Leonardo (where SS is pin 17) -// to work by default with Arduino Ethernet Shield R2 & R3. + // For boards using AVR, assume shields with SS on pin 10 + // will be used. This allows for Arduino Mega (where + // SS is pin 53) and Arduino Leonardo (where SS is pin 17) + // to work by default with Arduino Ethernet Shield R2 & R3. #elif defined(__AVR__) -#define SS_PIN_DEFAULT 10 -//KH -#warning w5100.cpp Use __AVR__, change SS_PIN_DEFAULT to 10 + #define SS_PIN_DEFAULT 10 + //KH + #warning w5100.cpp Use __AVR__, change SS_PIN_DEFAULT to 10 -// If variant.h or other headers define these names -// use them if none of the other cases match + // If variant.h or other headers define these names + // use them if none of the other cases match #elif defined(PIN_SPI_SS) -#if defined(__SAMD21G18A__) -//10 - 2 (6 conflict) all not OK for Nano 33 IoT !!! SPI corrupted??? -#warning w5100.cpp Use __SAMD21G18A__, change SS_PIN_DEFAULT to 10 -#define SS_PIN_DEFAULT 10 -#else -#define SS_PIN_DEFAULT PIN_SPI_SS + #if defined(__SAMD21G18A__) + //10 - 2 (6 conflict) all not OK for Nano 33 IoT !!! SPI corrupted??? + #warning w5100.cpp Use __SAMD21G18A__, change SS_PIN_DEFAULT to 10 + #define SS_PIN_DEFAULT 10 + #else + #define SS_PIN_DEFAULT PIN_SPI_SS -//KH -#warning w5100.cpp Use PIN_SPI_SS defined, change SS_PIN_DEFAULT to PIN_SPI_SS -#endif + //KH + #warning w5100.cpp Use PIN_SPI_SS defined, change SS_PIN_DEFAULT to PIN_SPI_SS + #endif #elif defined(CORE_SS0_PIN) -#define SS_PIN_DEFAULT CORE_SS0_PIN + #define SS_PIN_DEFAULT CORE_SS0_PIN -//KH -#warning w5100.cpp Use CORE_SS0_PIN defined, change SS_PIN_DEFAULT to CORE_SS0_PIN + //KH + #warning w5100.cpp Use CORE_SS0_PIN defined, change SS_PIN_DEFAULT to CORE_SS0_PIN -//KH for ESP32 + //KH for ESP32 #elif defined(ESP32) -//pin SS already defined in ESP32 as pin 5, don't use this as conflict with SPIFFS, EEPROM, etc. -// Use in GPIO22 -#warning w5100.cpp Use ESP32, change SS_PIN_DEFAULT to GPIO22, MOSI(23), MISO(19), SCK(18) -#define SS_PIN_DEFAULT 22 //SS -/////// + //pin SS already defined in ESP32 as pin 5, don't use this as conflict with SPIFFS, EEPROM, etc. + // Use in GPIO22 + #warning w5100.cpp Use ESP32, change SS_PIN_DEFAULT to GPIO22, MOSI(23), MISO(19), SCK(18) + #define SS_PIN_DEFAULT 22 //SS + /////// -//KH for ESP8266 + //KH for ESP8266 #elif defined(ESP8266) -//pin SS already defined in ESP8266 as pin 15. Conflict => Move to pin GPIO4 (D2) -#warning w5100.cpp Use ESP8266, change SS_PIN_DEFAULT to SS(4), MOSI(13), MISO(12), SCK(14) -#define SS_PIN_DEFAULT D2 // GPIO4, SS + //pin SS already defined in ESP8266 as pin 15. Conflict => Move to pin GPIO4 (D2) + #warning w5100.cpp Use ESP8266, change SS_PIN_DEFAULT to SS(4), MOSI(13), MISO(12), SCK(14) + #define SS_PIN_DEFAULT D2 // GPIO4, SS -/////// + /////// -// As a final fallback, use pin 10 + // As a final fallback, use pin 10 #else -#define SS_PIN_DEFAULT 10 + #define SS_PIN_DEFAULT 10 -//KH -#warning w5100.cpp Use fallback, change SS_PIN_DEFAULT to 10 + //KH + #warning w5100.cpp Use fallback, change SS_PIN_DEFAULT to 10 #endif @@ -119,8 +119,8 @@ uint8_t W5100Class::chip = 0; uint8_t W5100Class::CH_BASE_MSB; uint8_t W5100Class::ss_pin = SS_PIN_DEFAULT; #ifdef ETHERNET_LARGE_BUFFERS -uint16_t W5100Class::SSIZE = 2048; -uint16_t W5100Class::SMASK = 0x07FF; + uint16_t W5100Class::SSIZE = 2048; + uint16_t W5100Class::SMASK = 0x07FF; #endif W5100Class W5100; @@ -155,549 +155,582 @@ W5100Class W5100; uint8_t W5100Class::init(uint8_t socketNumbers, uint8_t new_ss_pin) { // KH - uint8_t i; - - if (initialized) return 1; - - // Many Ethernet shields have a CAT811 or similar reset chip - // connected to W5100 or W5200 chips. The W5200 will not work at - // all, and may even drive its MISO pin, until given an active low - // reset pulse! The CAT811 has a 240 ms typical pulse length, and - // a 400 ms worst case maximum pulse length. MAX811 has a worst - // case maximum 560 ms pulse length. This delay is meant to wait - // until the reset pulse is ended. If your hardware has a shorter - // reset time, this can be edited or removed. - delay(560); - - //W5100Class::ss_pin = new_ss_pin; - -#if ( W5100_DEBUG > 0 ) - //KH - Serial.print("\nW5100 init, using SS_PIN_DEFAULT = "); - Serial.print(SS_PIN_DEFAULT); - Serial.print(", new ss_pin = "); - Serial.print(new_ss_pin); - Serial.print(", W5100Class::ss_pin = "); - Serial.println(W5100Class::ss_pin); + uint8_t i; + + if (initialized) + return 1; + + // Many Ethernet shields have a CAT811 or similar reset chip + // connected to W5100 or W5200 chips. The W5200 will not work at + // all, and may even drive its MISO pin, until given an active low + // reset pulse! The CAT811 has a 240 ms typical pulse length, and + // a 400 ms worst case maximum pulse length. MAX811 has a worst + // case maximum 560 ms pulse length. This delay is meant to wait + // until the reset pulse is ended. If your hardware has a shorter + // reset time, this can be edited or removed. + delay(560); + + //W5100Class::ss_pin = new_ss_pin; + +#if ( W5100_DEBUG > 0 ) + //KH + Serial.print("\nW5100 init, using SS_PIN_DEFAULT = "); + Serial.print(SS_PIN_DEFAULT); + Serial.print(", new ss_pin = "); + Serial.print(new_ss_pin); + Serial.print(", W5100Class::ss_pin = "); + Serial.println(W5100Class::ss_pin); #endif - SPI.begin(); - - initSS(); - resetSS(); - - // From #define SPI_ETHERNET_SETTINGS SPISettings(14000000, MSBFIRST, SPI_MODE0) - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - - // Attempt W5200 detection first, because W5200 does not properly - // reset its SPI state when CS goes high (inactive). Communication - // from detecting the other chips can leave the W5200 in a state - // where it won't recover, unless given a reset pulse. - if (isW5200()) - { - CH_BASE_MSB = 0x40; + SPI.begin(); + + initSS(); + resetSS(); + + // From #define SPI_ETHERNET_SETTINGS SPISettings(14000000, MSBFIRST, SPI_MODE0) + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + + // Attempt W5200 detection first, because W5200 does not properly + // reset its SPI state when CS goes high (inactive). Communication + // from detecting the other chips can leave the W5200 in a state + // where it won't recover, unless given a reset pulse. + if (isW5200()) + { + CH_BASE_MSB = 0x40; #ifdef ETHERNET_LARGE_BUFFERS #if MAX_SOCK_NUM <= 1 - SSIZE = 16384; + SSIZE = 16384; #elif MAX_SOCK_NUM <= 2 - SSIZE = 8192; + SSIZE = 8192; #elif MAX_SOCK_NUM <= 4 - SSIZE = 4096; + SSIZE = 4096; #else - SSIZE = 2048; + SSIZE = 2048; #endif - SMASK = SSIZE - 1; + SMASK = SSIZE - 1; #endif - for (i=0; i> 10); - writeSnTX_SIZE(i, SSIZE >> 10); - } - for (; i<8; i++) - { - writeSnRX_SIZE(i, 0); - writeSnTX_SIZE(i, 0); - } - -#if ( W5100_DEBUG > 0 ) - Serial.print("W5100::init: W5200, SSIZE ="); + + for (i = 0; i < MAX_SOCK_NUM; i++) + { + writeSnRX_SIZE(i, SSIZE >> 10); + writeSnTX_SIZE(i, SSIZE >> 10); + } + + for (; i < 8; i++) + { + writeSnRX_SIZE(i, 0); + writeSnTX_SIZE(i, 0); + } + +#if ( W5100_DEBUG > 0 ) + Serial.print("W5100::init: W5200, SSIZE ="); Serial.println(SSIZE); #endif - - // Try W5500 next. Wiznet finally seems to have implemented - // SPI well with this chip. It appears to be very resilient, - // so try it after the fragile W5200 - } - else if (isW5500()) - { - CH_BASE_MSB = 0x10; + + // Try W5500 next. Wiznet finally seems to have implemented + // SPI well with this chip. It appears to be very resilient, + // so try it after the fragile W5200 + } + else if (isW5500()) + { + CH_BASE_MSB = 0x10; #ifdef ETHERNET_LARGE_BUFFERS #if MAX_SOCK_NUM <= 1 - SSIZE = 16384; + SSIZE = 16384; #elif MAX_SOCK_NUM <= 2 - SSIZE = 8192; + SSIZE = 8192; #elif MAX_SOCK_NUM <= 4 - SSIZE = 4096; + SSIZE = 4096; #else - SSIZE = 2048; + SSIZE = 2048; #endif - SMASK = SSIZE - 1; - for (i=0; i> 10); - writeSnTX_SIZE(i, SSIZE >> 10); - } - for (; i<8; i++) - { - writeSnRX_SIZE(i, 0); - writeSnTX_SIZE(i, 0); - } + SMASK = SSIZE - 1; + + for (i = 0; i < MAX_SOCK_NUM; i++) + { + writeSnRX_SIZE(i, SSIZE >> 10); + writeSnTX_SIZE(i, SSIZE >> 10); + } + + for (; i < 8; i++) + { + writeSnRX_SIZE(i, 0); + writeSnTX_SIZE(i, 0); + } + #endif - -#if ( W5100_DEBUG > 0 ) + +#if ( W5100_DEBUG > 0 ) Serial.print("W5100::init: W5500, SSIZE ="); Serial.println(SSIZE); #endif - - - // Try W5100 last. This simple chip uses fixed 4 byte frames - // for every 8 bit access. Terribly inefficient, but so simple - // it recovers from "hearing" unsuccessful W5100 or W5200 - // communication. W5100 is also the only chip without a VERSIONR - // register for identification, so we check this last. - } else if (isW5100()) - { - CH_BASE_MSB = 0x04; + + + // Try W5100 last. This simple chip uses fixed 4 byte frames + // for every 8 bit access. Terribly inefficient, but so simple + // it recovers from "hearing" unsuccessful W5100 or W5200 + // communication. W5100 is also the only chip without a VERSIONR + // register for identification, so we check this last. + } + else if (isW5100()) + { + CH_BASE_MSB = 0x04; #ifdef ETHERNET_LARGE_BUFFERS #if MAX_SOCK_NUM <= 1 - SSIZE = 8192; - writeTMSR(0x03); - writeRMSR(0x03); + SSIZE = 8192; + writeTMSR(0x03); + writeRMSR(0x03); #elif MAX_SOCK_NUM <= 2 - SSIZE = 4096; - writeTMSR(0x0A); - writeRMSR(0x0A); + SSIZE = 4096; + writeTMSR(0x0A); + writeRMSR(0x0A); #else - SSIZE = 2048; - writeTMSR(0x55); - writeRMSR(0x55); + SSIZE = 2048; + writeTMSR(0x55); + writeRMSR(0x55); #endif - SMASK = SSIZE - 1; + SMASK = SSIZE - 1; #else - writeTMSR(0x55); - writeRMSR(0x55); + writeTMSR(0x55); + writeRMSR(0x55); #endif -#if ( W5100_DEBUG > 0 ) - Serial.print("W5100::init: W5100, SSIZE ="); - Serial.println(SSIZE); +#if ( W5100_DEBUG > 0 ) + Serial.print("W5100::init: W5100, SSIZE ="); + Serial.println(SSIZE); #endif - // No hardware seems to be present. Or it could be a W5200 - // that's heard other SPI communication if its chip select - // pin wasn't high when a SD card or other SPI chip was used. - } - else - { -#if ( W5100_DEBUG > 0 ) - Serial.println("no chip :-("); + // No hardware seems to be present. Or it could be a W5200 + // that's heard other SPI communication if its chip select + // pin wasn't high when a SD card or other SPI chip was used. + } + else + { +#if ( W5100_DEBUG > 0 ) + Serial.println("no chip :-("); #endif - - chip = 0; - SPI.endTransaction(); - return 0; // no known chip is responding :-( - } - SPI.endTransaction(); - initialized = true; - return 1; // successful init + + chip = 0; + SPI.endTransaction(); + return 0; // no known chip is responding :-( + } + + SPI.endTransaction(); + initialized = true; + return 1; // successful init } // Soft reset the Wiznet chip, by writing to its MR register reset bit uint8_t W5100Class::softReset(void) { - uint16_t count=0; + uint16_t count = 0; -#if ( W5100_DEBUG > 1 ) - Serial.println("EthernetLarge:Wiznet soft reset"); +#if ( W5100_DEBUG > 1 ) + Serial.println("EthernetLarge:Wiznet soft reset"); #endif - - // write to reset bit - writeMR(0x80); - // then wait for soft reset to complete - do - { - uint8_t mr = readMR(); - -#if ( W5100_DEBUG > 2 ) - Serial.print("mr="); - Serial.println(mr, HEX); + + // write to reset bit + writeMR(0x80); + + // then wait for soft reset to complete + do + { + uint8_t mr = readMR(); + +#if ( W5100_DEBUG > 2 ) + Serial.print("mr="); + Serial.println(mr, HEX); #endif - - if (mr == 0) - return 1; - - delay(1); - } while (++count < 20); - return 0; + + if (mr == 0) + return 1; + + delay(1); + } while (++count < 20); + + return 0; } uint8_t W5100Class::isW5100(void) { - chip = 51; - -#if ( W5100_DEBUG > 1 ) - Serial.println("W5100.cpp: detect W5100 chip"); + chip = 51; + +#if ( W5100_DEBUG > 1 ) + Serial.println("W5100.cpp: detect W5100 chip"); #endif - - if (!softReset()) - return 0; - - writeMR(0x10); - if (readMR() != 0x10) - return 0; - - writeMR(0x12); - if (readMR() != 0x12) - return 0; - - writeMR(0x00); - if (readMR() != 0x00) - return 0; - -#if ( W5100_DEBUG > 1 ) - Serial.println("chip is W5100"); + + if (!softReset()) + return 0; + + writeMR(0x10); + + if (readMR() != 0x10) + return 0; + + writeMR(0x12); + + if (readMR() != 0x12) + return 0; + + writeMR(0x00); + + if (readMR() != 0x00) + return 0; + +#if ( W5100_DEBUG > 1 ) + Serial.println("chip is W5100"); #endif - - return 1; + + return 1; } uint8_t W5100Class::isW5200(void) { - chip = 52; - -#if ( W5100_DEBUG > 1 ) - Serial.println("W5100.cpp: detect W5200 chip"); + chip = 52; + +#if ( W5100_DEBUG > 1 ) + Serial.println("W5100.cpp: detect W5200 chip"); #endif - - if (!softReset()) - return 0; - - writeMR(0x08); - if (readMR() != 0x08) - return 0; - - writeMR(0x10); - if (readMR() != 0x10) - return 0; - - writeMR(0x00); - if (readMR() != 0x00) - return 0; - - int ver = readVERSIONR_W5200(); - -#if ( W5100_DEBUG > 1 ) - Serial.print("version="); - Serial.println(ver); + + if (!softReset()) + return 0; + + writeMR(0x08); + + if (readMR() != 0x08) + return 0; + + writeMR(0x10); + + if (readMR() != 0x10) + return 0; + + writeMR(0x00); + + if (readMR() != 0x00) + return 0; + + int ver = readVERSIONR_W5200(); + +#if ( W5100_DEBUG > 1 ) + Serial.print("version="); + Serial.println(ver); #endif - - if (ver != 3) - return 0; - -#if ( W5100_DEBUG > 1 ) - Serial.println("chip is W5200"); + + if (ver != 3) + return 0; + +#if ( W5100_DEBUG > 1 ) + Serial.println("chip is W5200"); #endif - - return 1; + + return 1; } uint8_t W5100Class::isW5500(void) { - chip = 55; - -#if ( W5100_DEBUG > 1 ) - Serial.println("W5100.cpp: detect W5500 chip"); + chip = 55; + +#if ( W5100_DEBUG > 1 ) + Serial.println("W5100.cpp: detect W5500 chip"); #endif - - if (!softReset()) - return 0; - - writeMR(0x08); - if (readMR() != 0x08) - return 0; - - writeMR(0x10); - if (readMR() != 0x10) - return 0; - - writeMR(0x00); - if (readMR() != 0x00) - return 0; - - int ver = readVERSIONR_W5500(); - -#if ( W5100_DEBUG > 1 ) - Serial.print("version="); - Serial.println(ver); + + if (!softReset()) + return 0; + + writeMR(0x08); + + if (readMR() != 0x08) + return 0; + + writeMR(0x10); + + if (readMR() != 0x10) + return 0; + + writeMR(0x00); + + if (readMR() != 0x00) + return 0; + + int ver = readVERSIONR_W5500(); + +#if ( W5100_DEBUG > 1 ) + Serial.print("version="); + Serial.println(ver); #endif - - if (ver != 4) - return 0; - -#if ( W5100_DEBUG > 1 ) - Serial.println("chip is W5500"); + + if (ver != 4) + return 0; + +#if ( W5100_DEBUG > 1 ) + Serial.println("chip is W5500"); #endif - return 1; + return 1; } W5100Linkstatus W5100Class::getLinkStatus() { - uint8_t phystatus; - - // KH - if (!initialized) return UNKNOWN; - - switch (chip) - { - case 52: - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - phystatus = readPSTATUS_W5200(); - SPI.endTransaction(); - if (phystatus & 0x20) - return LINK_ON; - - return LINK_OFF; - - case 55: - SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - phystatus = readPHYCFGR_W5500(); - SPI.endTransaction(); - if (phystatus & 0x01) - return LINK_ON; - - return LINK_OFF; - - default: - return UNKNOWN; - } + uint8_t phystatus; + + // KH + if (!initialized) + return UNKNOWN; + + switch (chip) + { + case 52: + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + phystatus = readPSTATUS_W5200(); + SPI.endTransaction(); + + if (phystatus & 0x20) + return LINK_ON; + + return LINK_OFF; + + case 55: + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + phystatus = readPHYCFGR_W5500(); + SPI.endTransaction(); + + if (phystatus & 0x01) + return LINK_ON; + + return LINK_OFF; + + default: + return UNKNOWN; + } } uint16_t W5100Class::write(uint16_t addr, const uint8_t *buf, uint16_t len) { - uint8_t cmd[8]; - - if (chip == 51) - { - for (uint16_t i=0; i> 8); - SPI.transfer(addr & 0xFF); - addr++; - SPI.transfer(buf[i]); - resetSS(); - } - } - else if (chip == 52) - { - setSS(); - cmd[0] = addr >> 8; - cmd[1] = addr & 0xFF; - cmd[2] = ((len >> 8) & 0x7F) | 0x80; - cmd[3] = len & 0xFF; - SPI.transfer(cmd, 4); - + uint8_t cmd[8]; + + if (chip == 51) + { + for (uint16_t i = 0; i < len; i++) + { + setSS(); + SPI.transfer(0xF0); + SPI.transfer(addr >> 8); + SPI.transfer(addr & 0xFF); + addr++; + SPI.transfer(buf[i]); + resetSS(); + } + } + else if (chip == 52) + { + setSS(); + cmd[0] = addr >> 8; + cmd[1] = addr & 0xFF; + cmd[2] = ((len >> 8) & 0x7F) | 0x80; + cmd[3] = len & 0xFF; + SPI.transfer(cmd, 4); + #ifdef SPI_HAS_TRANSFER_BUF - SPI.transfer(buf, NULL, len); + SPI.transfer(buf, NULL, len); #else - // TODO: copy 8 bytes at a time to cmd[] and block transfer - for (uint16_t i=0; i < len; i++) - { - SPI.transfer(buf[i]); - } + + // TODO: copy 8 bytes at a time to cmd[] and block transfer + for (uint16_t i = 0; i < len; i++) + { + SPI.transfer(buf[i]); + } + #endif - resetSS(); - } - else - { - // chip == 55 - setSS(); - if (addr < 0x100) - { - // common registers 00nn - cmd[0] = 0; - cmd[1] = addr & 0xFF; - cmd[2] = 0x04; - } - else if (addr < 0x8000) - { - // socket registers 10nn, 11nn, 12nn, 13nn, etc - cmd[0] = 0; - cmd[1] = addr & 0xFF; - cmd[2] = ((addr >> 3) & 0xE0) | 0x0C; - } - else if (addr < 0xC000) - { - // transmit buffers 8000-87FF, 8800-8FFF, 9000-97FF, etc - // 10## #nnn nnnn nnnn - cmd[0] = addr >> 8; - cmd[1] = addr & 0xFF; - #if defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 1 - cmd[2] = 0x14; // 16K buffers - #elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 2 - cmd[2] = ((addr >> 8) & 0x20) | 0x14; // 8K buffers - #elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 4 - cmd[2] = ((addr >> 7) & 0x60) | 0x14; // 4K buffers - #else - cmd[2] = ((addr >> 6) & 0xE0) | 0x14; // 2K buffers - #endif - } - else - { - // receive buffers - cmd[0] = addr >> 8; - cmd[1] = addr & 0xFF; - #if defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 1 - cmd[2] = 0x1C; // 16K buffers - #elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 2 - cmd[2] = ((addr >> 8) & 0x20) | 0x1C; // 8K buffers - #elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 4 - cmd[2] = ((addr >> 7) & 0x60) | 0x1C; // 4K buffers - #else - cmd[2] = ((addr >> 6) & 0xE0) | 0x1C; // 2K buffers - #endif - } - - if (len <= 5) - { - for (uint8_t i=0; i < len; i++) - { - cmd[i + 3] = buf[i]; - } - - SPI.transfer(cmd, len + 3); - } - else - { - SPI.transfer(cmd, 3); + resetSS(); + } + else + { + // chip == 55 + setSS(); + + if (addr < 0x100) + { + // common registers 00nn + cmd[0] = 0; + cmd[1] = addr & 0xFF; + cmd[2] = 0x04; + } + else if (addr < 0x8000) + { + // socket registers 10nn, 11nn, 12nn, 13nn, etc + cmd[0] = 0; + cmd[1] = addr & 0xFF; + cmd[2] = ((addr >> 3) & 0xE0) | 0x0C; + } + else if (addr < 0xC000) + { + // transmit buffers 8000-87FF, 8800-8FFF, 9000-97FF, etc + // 10## #nnn nnnn nnnn + cmd[0] = addr >> 8; + cmd[1] = addr & 0xFF; +#if defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 1 + cmd[2] = 0x14; // 16K buffers +#elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 2 + cmd[2] = ((addr >> 8) & 0x20) | 0x14; // 8K buffers +#elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 4 + cmd[2] = ((addr >> 7) & 0x60) | 0x14; // 4K buffers +#else + cmd[2] = ((addr >> 6) & 0xE0) | 0x14; // 2K buffers +#endif + } + else + { + // receive buffers + cmd[0] = addr >> 8; + cmd[1] = addr & 0xFF; +#if defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 1 + cmd[2] = 0x1C; // 16K buffers +#elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 2 + cmd[2] = ((addr >> 8) & 0x20) | 0x1C; // 8K buffers +#elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 4 + cmd[2] = ((addr >> 7) & 0x60) | 0x1C; // 4K buffers +#else + cmd[2] = ((addr >> 6) & 0xE0) | 0x1C; // 2K buffers +#endif + } + + if (len <= 5) + { + for (uint8_t i = 0; i < len; i++) + { + cmd[i + 3] = buf[i]; + } + + SPI.transfer(cmd, len + 3); + } + else + { + SPI.transfer(cmd, 3); #ifdef SPI_HAS_TRANSFER_BUF - SPI.transfer(buf, NULL, len); + SPI.transfer(buf, NULL, len); #else - // TODO: copy 8 bytes at a time to cmd[] and block transfer - for (uint16_t i=0; i < len; i++) - { - SPI.transfer(buf[i]); - } + + // TODO: copy 8 bytes at a time to cmd[] and block transfer + for (uint16_t i = 0; i < len; i++) + { + SPI.transfer(buf[i]); + } + #endif - } - resetSS(); - } - return len; + } + + resetSS(); + } + + return len; } uint16_t W5100Class::read(uint16_t addr, uint8_t *buf, uint16_t len) { - uint8_t cmd[4]; - - if (chip == 51) - { - for (uint16_t i=0; i < len; i++) - { - setSS(); - #if 1 - SPI.transfer(0x0F); - SPI.transfer(addr >> 8); - SPI.transfer(addr & 0xFF); - addr++; - buf[i] = SPI.transfer(0); - #else - cmd[0] = 0x0F; - cmd[1] = addr >> 8; - cmd[2] = addr & 0xFF; - cmd[3] = 0; - SPI.transfer(cmd, 4); // TODO: why doesn't this work? - buf[i] = cmd[3]; - addr++; - #endif - resetSS(); - } - } - else if (chip == 52) - { - setSS(); - cmd[0] = addr >> 8; - cmd[1] = addr & 0xFF; - cmd[2] = (len >> 8) & 0x7F; - cmd[3] = len & 0xFF; - SPI.transfer(cmd, 4); - memset(buf, 0, len); - SPI.transfer(buf, len); - resetSS(); - } - else - { - // chip == 55 - setSS(); - - if (addr < 0x100) - { - // common registers 00nn - cmd[0] = 0; - cmd[1] = addr & 0xFF; - cmd[2] = 0x00; - } - else if (addr < 0x8000) - { - // socket registers 10nn, 11nn, 12nn, 13nn, etc - cmd[0] = 0; - cmd[1] = addr & 0xFF; - cmd[2] = ((addr >> 3) & 0xE0) | 0x08; - } - else if (addr < 0xC000) - { - // transmit buffers 8000-87FF, 8800-8FFF, 9000-97FF, etc - // 10## #nnn nnnn nnnn - cmd[0] = addr >> 8; - cmd[1] = addr & 0xFF; - #if defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 1 - cmd[2] = 0x10; // 16K buffers - #elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 2 - cmd[2] = ((addr >> 8) & 0x20) | 0x10; // 8K buffers - #elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 4 - cmd[2] = ((addr >> 7) & 0x60) | 0x10; // 4K buffers - #else - cmd[2] = ((addr >> 6) & 0xE0) | 0x10; // 2K buffers - #endif - } else - { - // receive buffers - cmd[0] = addr >> 8; - cmd[1] = addr & 0xFF; - #if defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 1 - cmd[2] = 0x18; // 16K buffers - #elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 2 - cmd[2] = ((addr >> 8) & 0x20) | 0x18; // 8K buffers - #elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 4 - cmd[2] = ((addr >> 7) & 0x60) | 0x18; // 4K buffers - #else - cmd[2] = ((addr >> 6) & 0xE0) | 0x18; // 2K buffers - #endif - } - SPI.transfer(cmd, 3); - memset(buf, 0, len); - SPI.transfer(buf, len); - resetSS(); - } - return len; + uint8_t cmd[4]; + + if (chip == 51) + { + for (uint16_t i = 0; i < len; i++) + { + setSS(); +#if 1 + SPI.transfer(0x0F); + SPI.transfer(addr >> 8); + SPI.transfer(addr & 0xFF); + addr++; + buf[i] = SPI.transfer(0); +#else + cmd[0] = 0x0F; + cmd[1] = addr >> 8; + cmd[2] = addr & 0xFF; + cmd[3] = 0; + SPI.transfer(cmd, 4); // TODO: why doesn't this work? + buf[i] = cmd[3]; + addr++; +#endif + resetSS(); + } + } + else if (chip == 52) + { + setSS(); + cmd[0] = addr >> 8; + cmd[1] = addr & 0xFF; + cmd[2] = (len >> 8) & 0x7F; + cmd[3] = len & 0xFF; + SPI.transfer(cmd, 4); + memset(buf, 0, len); + SPI.transfer(buf, len); + resetSS(); + } + else + { + // chip == 55 + setSS(); + + if (addr < 0x100) + { + // common registers 00nn + cmd[0] = 0; + cmd[1] = addr & 0xFF; + cmd[2] = 0x00; + } + else if (addr < 0x8000) + { + // socket registers 10nn, 11nn, 12nn, 13nn, etc + cmd[0] = 0; + cmd[1] = addr & 0xFF; + cmd[2] = ((addr >> 3) & 0xE0) | 0x08; + } + else if (addr < 0xC000) + { + // transmit buffers 8000-87FF, 8800-8FFF, 9000-97FF, etc + // 10## #nnn nnnn nnnn + cmd[0] = addr >> 8; + cmd[1] = addr & 0xFF; +#if defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 1 + cmd[2] = 0x10; // 16K buffers +#elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 2 + cmd[2] = ((addr >> 8) & 0x20) | 0x10; // 8K buffers +#elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 4 + cmd[2] = ((addr >> 7) & 0x60) | 0x10; // 4K buffers +#else + cmd[2] = ((addr >> 6) & 0xE0) | 0x10; // 2K buffers +#endif + } + else + { + // receive buffers + cmd[0] = addr >> 8; + cmd[1] = addr & 0xFF; +#if defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 1 + cmd[2] = 0x18; // 16K buffers +#elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 2 + cmd[2] = ((addr >> 8) & 0x20) | 0x18; // 8K buffers +#elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 4 + cmd[2] = ((addr >> 7) & 0x60) | 0x18; // 4K buffers +#else + cmd[2] = ((addr >> 6) & 0xE0) | 0x18; // 2K buffers +#endif + } + + SPI.transfer(cmd, 3); + memset(buf, 0, len); + SPI.transfer(buf, len); + resetSS(); + } + + return len; } void W5100Class::execCmdSn(SOCKET s, SockCMD _cmd) { - // Send command to socket - writeSnCR(s, _cmd); - // Wait for command to complete - while (readSnCR(s)) ; + // Send command to socket + writeSnCR(s, _cmd); + + // Wait for command to complete + while (readSnCR(s)) ; } diff --git a/LibraryPatches/EthernetLarge/src/utility/w5100.h b/LibraryPatches/EthernetLarge/src/utility/w5100.h index e5a71c0..c2c420f 100644 --- a/LibraryPatches/EthernetLarge/src/utility/w5100.h +++ b/LibraryPatches/EthernetLarge/src/utility/w5100.h @@ -10,7 +10,7 @@ Copyright 2018 Paul Stoffregen Copyright (c) 2010 by Cristian Maglie - + This file is free software; you can redistribute it and/or modify it under the terms of either the GNU General Public License version 2 or the GNU Lesser General Public License version 2.1, both as @@ -23,89 +23,91 @@ 1.0.2 K Hoang 20/02/2020 Add support to UIPEthernet library for ENC28J60 1.0.3 K Hoang 23/02/2020 Add support to SAM DUE / SAMD21 boards 1.0.4 K Hoang 16/04/2020 Add support to SAMD51 boards - 1.0.5 K Hoang 24/04/2020 Add support to nRF52 boards, such as AdaFruit Feather nRF52832, nRF52840 Express, BlueFruit Sense, - Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B30_ublox, etc. + 1.0.5 K Hoang 24/04/2020 Add support to nRF52 boards, such as AdaFruit Feather nRF52832, nRF52840 Express, BlueFruit Sense, + Itsy-Bitsy nRF52840 Express, Metro nRF52840 Express, NINA_B30_ublox, etc. More Custom Ethernet libraries supported such as Ethernet2, Ethernet3, EthernetLarge 1.0.6 K Hoang 27/04/2020 Add support to ESP32/ESP8266 boards - 1.0.7 K Hoang 30/04/2020 Add ENC28J60 support to ESP32/ESP8266 boards + 1.0.7 K Hoang 30/04/2020 Add ENC28J60 support to ESP32/ESP8266 boards 1.0.8 K Hoang 12/05/2020 Fix W5x00 support for ESP8266 boards. - 1.0.9 K Hoang 15/05/2020 Add EthernetWrapper.h for easier W5x00 support as well as more Ethernet libs in the future. + 1.0.9 K Hoang 15/05/2020 Add EthernetWrapper.h for easier W5x00 support as well as more Ethernet libs in the future. *****************************************************************************************************************************/ // w5100.h contains private W5x00 hardware "driver" level definitions // which are not meant to be exposed to other libraries or Arduino users -#ifndef W5100_H_INCLUDED -#define W5100_H_INCLUDED +#ifndef W5100_H_INCLUDED +#define W5100_H_INCLUDED #include #include #ifndef USE_W5100 -#define USE_W5100 false + #define USE_W5100 false #else -#define USE_W5100 true + #define USE_W5100 true #endif #if !USE_W5100 -// Safe for W5200 and W5500, but also tested OK on W5100 -// Use 14MHz if you know your W5100 can't run -// Higher SPI clock results in faster transfer to hosts on a LAN -// or with very low packet latency. With ordinary internet latency, -// the TCP window size & packet loss determine your overall speed. -#warning Use 25MHz clock for W5200/W5500. Not for W5100 -#define SPI_ETHERNET_SETTINGS SPISettings(25000000, MSBFIRST, SPI_MODE0) + // Safe for W5200 and W5500, but also tested OK on W5100 + // Use 14MHz if you know your W5100 can't run + // Higher SPI clock results in faster transfer to hosts on a LAN + // or with very low packet latency. With ordinary internet latency, + // the TCP window size & packet loss determine your overall speed. + #warning Use 25MHz clock for W5200/W5500. Not for W5100 + #define SPI_ETHERNET_SETTINGS SPISettings(25000000, MSBFIRST, SPI_MODE0) #else -// Safe for all chips but too slow -#define SPI_ETHERNET_SETTINGS SPISettings(14000000, MSBFIRST, SPI_MODE0) -#warning Use 14MHz clock for W5100/W5200/W5500. Slow. + // Safe for all chips but too slow + #define SPI_ETHERNET_SETTINGS SPISettings(14000000, MSBFIRST, SPI_MODE0) + #warning Use 14MHz clock for W5100/W5200/W5500. Slow. #endif // Require Ethernet.h, because we need MAX_SOCK_NUM #ifndef ethernet_h_ -#error "EthernetLarge.h must be included before w5100.h" + #error "EthernetLarge.h must be included before w5100.h" #endif // Arduino 101's SPI can not run faster than 8 MHz. #if defined(ARDUINO_ARCH_ARC32) -#undef SPI_ETHERNET_SETTINGS -#define SPI_ETHERNET_SETTINGS SPISettings(8000000, MSBFIRST, SPI_MODE0) + #undef SPI_ETHERNET_SETTINGS + #define SPI_ETHERNET_SETTINGS SPISettings(8000000, MSBFIRST, SPI_MODE0) #endif // Arduino Zero can't use W5100-based shields faster than 8 MHz // https://github.com/arduino-libraries/Ethernet/issues/37#issuecomment-408036848 // W5500 does seem to work at 12 MHz. Delete this if only using W5500 #if defined(__SAMD21G18A__) -#undef SPI_ETHERNET_SETTINGS -//#warning Use SAMD21 architecture SPISettings(8000000, MSBFIRST, SPI_MODE3) => IP OK -#warning Use SAMD21 architecture SPISettings(30000000, MSBFIRST, SPI_MODE3) => IP OK -// Still not working !!! Original SPI_MODE0 not OK at all -//#define SPI_ETHERNET_SETTINGS SPISettings(8000000, MSBFIRST, SPI_MODE3) -#define SPI_ETHERNET_SETTINGS SPISettings(30000000, MSBFIRST, SPI_MODE3) + #undef SPI_ETHERNET_SETTINGS + //#warning Use SAMD21 architecture SPISettings(8000000, MSBFIRST, SPI_MODE3) => IP OK + #warning Use SAMD21 architecture SPISettings(30000000, MSBFIRST, SPI_MODE3) => IP OK + // Still not working !!! Original SPI_MODE0 not OK at all + //#define SPI_ETHERNET_SETTINGS SPISettings(8000000, MSBFIRST, SPI_MODE3) + #define SPI_ETHERNET_SETTINGS SPISettings(30000000, MSBFIRST, SPI_MODE3) #endif typedef uint8_t SOCKET; -class SnMR { -public: - static const uint8_t CLOSE = 0x00; - static const uint8_t TCP = 0x21; - static const uint8_t UDP = 0x02; - static const uint8_t IPRAW = 0x03; - static const uint8_t MACRAW = 0x04; - static const uint8_t PPPOE = 0x05; - static const uint8_t ND = 0x20; - static const uint8_t MULTI = 0x80; +class SnMR +{ + public: + static const uint8_t CLOSE = 0x00; + static const uint8_t TCP = 0x21; + static const uint8_t UDP = 0x02; + static const uint8_t IPRAW = 0x03; + static const uint8_t MACRAW = 0x04; + static const uint8_t PPPOE = 0x05; + static const uint8_t ND = 0x20; + static const uint8_t MULTI = 0x80; }; -enum SockCMD { +enum SockCMD +{ Sock_OPEN = 0x01, Sock_LISTEN = 0x02, Sock_CONNECT = 0x04, @@ -117,97 +119,132 @@ enum SockCMD { Sock_RECV = 0x40 }; -class SnIR { -public: - static const uint8_t SEND_OK = 0x10; - static const uint8_t TIMEOUT = 0x08; - static const uint8_t RECV = 0x04; - static const uint8_t DISCON = 0x02; - static const uint8_t CON = 0x01; +class SnIR +{ + public: + static const uint8_t SEND_OK = 0x10; + static const uint8_t TIMEOUT = 0x08; + static const uint8_t RECV = 0x04; + static const uint8_t DISCON = 0x02; + static const uint8_t CON = 0x01; }; -class SnSR { -public: - static const uint8_t CLOSED = 0x00; - static const uint8_t INIT = 0x13; - static const uint8_t LISTEN = 0x14; - static const uint8_t SYNSENT = 0x15; - static const uint8_t SYNRECV = 0x16; - static const uint8_t ESTABLISHED = 0x17; - static const uint8_t FIN_WAIT = 0x18; - static const uint8_t CLOSING = 0x1A; - static const uint8_t TIME_WAIT = 0x1B; - static const uint8_t CLOSE_WAIT = 0x1C; - static const uint8_t LAST_ACK = 0x1D; - static const uint8_t UDP = 0x22; - static const uint8_t IPRAW = 0x32; - static const uint8_t MACRAW = 0x42; - static const uint8_t PPPOE = 0x5F; +class SnSR +{ + public: + static const uint8_t CLOSED = 0x00; + static const uint8_t INIT = 0x13; + static const uint8_t LISTEN = 0x14; + static const uint8_t SYNSENT = 0x15; + static const uint8_t SYNRECV = 0x16; + static const uint8_t ESTABLISHED = 0x17; + static const uint8_t FIN_WAIT = 0x18; + static const uint8_t CLOSING = 0x1A; + static const uint8_t TIME_WAIT = 0x1B; + static const uint8_t CLOSE_WAIT = 0x1C; + static const uint8_t LAST_ACK = 0x1D; + static const uint8_t UDP = 0x22; + static const uint8_t IPRAW = 0x32; + static const uint8_t MACRAW = 0x42; + static const uint8_t PPPOE = 0x5F; }; -class IPPROTO { -public: - static const uint8_t IP = 0; - static const uint8_t ICMP = 1; - static const uint8_t IGMP = 2; - static const uint8_t GGP = 3; - static const uint8_t TCP = 6; - static const uint8_t PUP = 12; - static const uint8_t UDP = 17; - static const uint8_t IDP = 22; - static const uint8_t ND = 77; - static const uint8_t RAW = 255; +class IPPROTO +{ + public: + static const uint8_t IP = 0; + static const uint8_t ICMP = 1; + static const uint8_t IGMP = 2; + static const uint8_t GGP = 3; + static const uint8_t TCP = 6; + static const uint8_t PUP = 12; + static const uint8_t UDP = 17; + static const uint8_t IDP = 22; + static const uint8_t ND = 77; + static const uint8_t RAW = 255; }; -enum W5100Linkstatus { +enum W5100Linkstatus +{ UNKNOWN, LINK_ON, LINK_OFF }; -class W5100Class { +class W5100Class +{ -public: - // KH - uint8_t init(uint8_t socketNumbers = MAX_SOCK_NUM, uint8_t new_ss_pin = 10); + public: + // KH + uint8_t init(uint8_t socketNumbers = MAX_SOCK_NUM, uint8_t new_ss_pin = 10); - inline void setGatewayIp(const uint8_t * addr) { writeGAR(addr); } - inline void getGatewayIp(uint8_t * addr) { readGAR(addr); } + inline void setGatewayIp(const uint8_t * addr) + { + writeGAR(addr); + } + inline void getGatewayIp(uint8_t * addr) + { + readGAR(addr); + } - inline void setSubnetMask(const uint8_t * addr) { writeSUBR(addr); } - inline void getSubnetMask(uint8_t * addr) { readSUBR(addr); } + inline void setSubnetMask(const uint8_t * addr) + { + writeSUBR(addr); + } + inline void getSubnetMask(uint8_t * addr) + { + readSUBR(addr); + } - inline void setMACAddress(const uint8_t * addr) { writeSHAR(addr); } - inline void getMACAddress(uint8_t * addr) { readSHAR(addr); } + inline void setMACAddress(const uint8_t * addr) + { + writeSHAR(addr); + } + inline void getMACAddress(uint8_t * addr) + { + readSHAR(addr); + } - inline void setIPAddress(const uint8_t * addr) { writeSIPR(addr); } - inline void getIPAddress(uint8_t * addr) { readSIPR(addr); } + inline void setIPAddress(const uint8_t * addr) + { + writeSIPR(addr); + } + inline void getIPAddress(uint8_t * addr) + { + readSIPR(addr); + } - inline void setRetransmissionTime(uint16_t timeout) { writeRTR(timeout); } - inline void setRetransmissionCount(uint8_t retry) { writeRCR(retry); } + inline void setRetransmissionTime(uint16_t timeout) + { + writeRTR(timeout); + } + inline void setRetransmissionCount(uint8_t retry) + { + writeRCR(retry); + } - static void execCmdSn(SOCKET s, SockCMD _cmd); + static void execCmdSn(SOCKET s, SockCMD _cmd); - // W5100 Registers - // --------------- -//private: -public: - static uint16_t write(uint16_t addr, const uint8_t *buf, uint16_t len); - - static uint8_t write(uint16_t addr, uint8_t data) - { - return write(addr, &data, 1); - } - - static uint16_t read(uint16_t addr, uint8_t *buf, uint16_t len); - - static uint8_t read(uint16_t addr) - { - uint8_t data; - read(addr, &data, 1); - return data; - } + // W5100 Registers + // --------------- + //private: + public: + static uint16_t write(uint16_t addr, const uint8_t *buf, uint16_t len); + + static uint8_t write(uint16_t addr, uint8_t data) + { + return write(addr, &data, 1); + } + + static uint16_t read(uint16_t addr, uint8_t *buf, uint16_t len); + + static uint8_t read(uint16_t addr) + { + uint8_t data; + read(addr, &data, 1); + return data; + } #define __GP_REGISTER8(name, address) \ static inline void write##name(uint8_t _data) { \ @@ -235,66 +272,67 @@ class W5100Class { static uint16_t read##name(uint8_t *_buff) { \ return read(address, _buff, size); \ } - - // KH - W5100Linkstatus getLinkStatus(); - - -public: - __GP_REGISTER8 (MR, 0x0000); // Mode - __GP_REGISTER_N(GAR, 0x0001, 4); // Gateway IP address - __GP_REGISTER_N(SUBR, 0x0005, 4); // Subnet mask address - __GP_REGISTER_N(SHAR, 0x0009, 6); // Source MAC address - __GP_REGISTER_N(SIPR, 0x000F, 4); // Source IP address - __GP_REGISTER8 (IR, 0x0015); // Interrupt - __GP_REGISTER8 (IMR, 0x0016); // Interrupt Mask - __GP_REGISTER16(RTR, 0x0017); // Timeout address - __GP_REGISTER8 (RCR, 0x0019); // Retry count - __GP_REGISTER8 (RMSR, 0x001A); // Receive memory size (W5100 only) - __GP_REGISTER8 (TMSR, 0x001B); // Transmit memory size (W5100 only) - __GP_REGISTER8 (PATR, 0x001C); // Authentication type address in PPPoE mode - __GP_REGISTER8 (PTIMER, 0x0028); // PPP LCP Request Timer - __GP_REGISTER8 (PMAGIC, 0x0029); // PPP LCP Magic Number - __GP_REGISTER_N(UIPR, 0x002A, 4); // Unreachable IP address in UDP mode (W5100 only) - __GP_REGISTER16(UPORT, 0x002E); // Unreachable Port address in UDP mode (W5100 only) - __GP_REGISTER8 (VERSIONR_W5200,0x001F); // Chip Version Register (W5200 only) - __GP_REGISTER8 (VERSIONR_W5500,0x0039); // Chip Version Register (W5500 only) - __GP_REGISTER8 (PSTATUS_W5200, 0x0035); // PHY Status - __GP_REGISTER8 (PHYCFGR_W5500, 0x002E); // PHY Configuration register, default: 10111xxx + + // KH + W5100Linkstatus getLinkStatus(); + + + public: + __GP_REGISTER8 (MR, 0x0000); // Mode + __GP_REGISTER_N(GAR, 0x0001, 4); // Gateway IP address + __GP_REGISTER_N(SUBR, 0x0005, 4); // Subnet mask address + __GP_REGISTER_N(SHAR, 0x0009, 6); // Source MAC address + __GP_REGISTER_N(SIPR, 0x000F, 4); // Source IP address + __GP_REGISTER8 (IR, 0x0015); // Interrupt + __GP_REGISTER8 (IMR, 0x0016); // Interrupt Mask + __GP_REGISTER16(RTR, 0x0017); // Timeout address + __GP_REGISTER8 (RCR, 0x0019); // Retry count + __GP_REGISTER8 (RMSR, 0x001A); // Receive memory size (W5100 only) + __GP_REGISTER8 (TMSR, 0x001B); // Transmit memory size (W5100 only) + __GP_REGISTER8 (PATR, 0x001C); // Authentication type address in PPPoE mode + __GP_REGISTER8 (PTIMER, 0x0028); // PPP LCP Request Timer + __GP_REGISTER8 (PMAGIC, 0x0029); // PPP LCP Magic Number + __GP_REGISTER_N(UIPR, 0x002A, 4); // Unreachable IP address in UDP mode (W5100 only) + __GP_REGISTER16(UPORT, 0x002E); // Unreachable Port address in UDP mode (W5100 only) + __GP_REGISTER8 (VERSIONR_W5200, 0x001F); // Chip Version Register (W5200 only) + __GP_REGISTER8 (VERSIONR_W5500, 0x0039); // Chip Version Register (W5500 only) + __GP_REGISTER8 (PSTATUS_W5200, 0x0035); // PHY Status + __GP_REGISTER8 (PHYCFGR_W5500, 0x002E); // PHY Configuration register, default: 10111xxx #undef __GP_REGISTER8 #undef __GP_REGISTER16 #undef __GP_REGISTER_N - // W5100 Socket registers - // ---------------------- -private: - static uint16_t CH_BASE(void) { - //if (chip == 55) return 0x1000; - //if (chip == 52) return 0x4000; - //return 0x0400; - return CH_BASE_MSB << 8; - } - static uint8_t CH_BASE_MSB; // 1 redundant byte, saves ~80 bytes code on AVR - static const uint16_t CH_SIZE = 0x0100; + // W5100 Socket registers + // ---------------------- + private: + static uint16_t CH_BASE(void) + { + //if (chip == 55) return 0x1000; + //if (chip == 52) return 0x4000; + //return 0x0400; + return CH_BASE_MSB << 8; + } + static uint8_t CH_BASE_MSB; // 1 redundant byte, saves ~80 bytes code on AVR + static const uint16_t CH_SIZE = 0x0100; - static inline uint8_t readSn(SOCKET s, uint16_t addr) - { - return read(CH_BASE() + s * CH_SIZE + addr); - } - static inline uint8_t writeSn(SOCKET s, uint16_t addr, uint8_t data) - { - return write(CH_BASE() + s * CH_SIZE + addr, data); - } - static inline uint16_t readSn(SOCKET s, uint16_t addr, uint8_t *buf, uint16_t len) - { - return read(CH_BASE() + s * CH_SIZE + addr, buf, len); - } - static inline uint16_t writeSn(SOCKET s, uint16_t addr, uint8_t *buf, uint16_t len) - { - return write(CH_BASE() + s * CH_SIZE + addr, buf, len); - } + static inline uint8_t readSn(SOCKET s, uint16_t addr) + { + return read(CH_BASE() + s * CH_SIZE + addr); + } + static inline uint8_t writeSn(SOCKET s, uint16_t addr, uint8_t data) + { + return write(CH_BASE() + s * CH_SIZE + addr, data); + } + static inline uint16_t readSn(SOCKET s, uint16_t addr, uint8_t *buf, uint16_t len) + { + return read(CH_BASE() + s * CH_SIZE + addr, buf, len); + } + static inline uint16_t writeSn(SOCKET s, uint16_t addr, uint8_t *buf, uint16_t len) + { + return write(CH_BASE() + s * CH_SIZE + addr, buf, len); + } #define __SOCKET_REGISTER8(name, address) \ static inline void write##name(SOCKET _s, uint8_t _data) { \ @@ -323,283 +361,290 @@ class W5100Class { return readSn(_s, address, _buff, size); \ } -public: - __SOCKET_REGISTER8(SnMR, 0x0000) // Mode - __SOCKET_REGISTER8(SnCR, 0x0001) // Command - __SOCKET_REGISTER8(SnIR, 0x0002) // Interrupt - __SOCKET_REGISTER8(SnSR, 0x0003) // Status - __SOCKET_REGISTER16(SnPORT, 0x0004) // Source Port - __SOCKET_REGISTER_N(SnDHAR, 0x0006, 6) // Destination Hardw Addr - __SOCKET_REGISTER_N(SnDIPR, 0x000C, 4) // Destination IP Addr - __SOCKET_REGISTER16(SnDPORT, 0x0010) // Destination Port - __SOCKET_REGISTER16(SnMSSR, 0x0012) // Max Segment Size - __SOCKET_REGISTER8(SnPROTO, 0x0014) // Protocol in IP RAW Mode - __SOCKET_REGISTER8(SnTOS, 0x0015) // IP TOS - __SOCKET_REGISTER8(SnTTL, 0x0016) // IP TTL - __SOCKET_REGISTER8(SnRX_SIZE, 0x001E) // RX Memory Size (W5200 only) - __SOCKET_REGISTER8(SnTX_SIZE, 0x001F) // RX Memory Size (W5200 only) - __SOCKET_REGISTER16(SnTX_FSR, 0x0020) // TX Free Size - __SOCKET_REGISTER16(SnTX_RD, 0x0022) // TX Read Pointer - __SOCKET_REGISTER16(SnTX_WR, 0x0024) // TX Write Pointer - __SOCKET_REGISTER16(SnRX_RSR, 0x0026) // RX Free Size - __SOCKET_REGISTER16(SnRX_RD, 0x0028) // RX Read Pointer - __SOCKET_REGISTER16(SnRX_WR, 0x002A) // RX Write Pointer (supported?) + public: + __SOCKET_REGISTER8(SnMR, 0x0000) // Mode + __SOCKET_REGISTER8(SnCR, 0x0001) // Command + __SOCKET_REGISTER8(SnIR, 0x0002) // Interrupt + __SOCKET_REGISTER8(SnSR, 0x0003) // Status + __SOCKET_REGISTER16(SnPORT, 0x0004) // Source Port + __SOCKET_REGISTER_N(SnDHAR, 0x0006, 6) // Destination Hardw Addr + __SOCKET_REGISTER_N(SnDIPR, 0x000C, 4) // Destination IP Addr + __SOCKET_REGISTER16(SnDPORT, 0x0010) // Destination Port + __SOCKET_REGISTER16(SnMSSR, 0x0012) // Max Segment Size + __SOCKET_REGISTER8(SnPROTO, 0x0014) // Protocol in IP RAW Mode + __SOCKET_REGISTER8(SnTOS, 0x0015) // IP TOS + __SOCKET_REGISTER8(SnTTL, 0x0016) // IP TTL + __SOCKET_REGISTER8(SnRX_SIZE, 0x001E) // RX Memory Size (W5200 only) + __SOCKET_REGISTER8(SnTX_SIZE, 0x001F) // RX Memory Size (W5200 only) + __SOCKET_REGISTER16(SnTX_FSR, 0x0020) // TX Free Size + __SOCKET_REGISTER16(SnTX_RD, 0x0022) // TX Read Pointer + __SOCKET_REGISTER16(SnTX_WR, 0x0024) // TX Write Pointer + __SOCKET_REGISTER16(SnRX_RSR, 0x0026) // RX Free Size + __SOCKET_REGISTER16(SnRX_RD, 0x0028) // RX Read Pointer + __SOCKET_REGISTER16(SnRX_WR, 0x002A) // RX Write Pointer (supported?) #undef __SOCKET_REGISTER8 #undef __SOCKET_REGISTER16 #undef __SOCKET_REGISTER_N -private: - // KH - bool initialized = false; - static uint8_t chip; - static uint8_t ss_pin; + private: + // KH + bool initialized = false; + static uint8_t chip; + static uint8_t ss_pin; - static uint8_t isW5100(void); - static uint8_t isW5200(void); - static uint8_t isW5500(void); + static uint8_t isW5100(void); + static uint8_t isW5200(void); + static uint8_t isW5500(void); -public: - // KH - static uint8_t softReset(void); - static uint8_t getChip(void) { return chip; } + public: + // KH + static uint8_t softReset(void); + static uint8_t getChip(void) + { + return chip; + } #ifdef ETHERNET_LARGE_BUFFERS - static uint16_t SSIZE; - static uint16_t SMASK; + static uint16_t SSIZE; + static uint16_t SMASK; #else - static const uint16_t SSIZE = 2048; - static const uint16_t SMASK = 0x07FF; + static const uint16_t SSIZE = 2048; + static const uint16_t SMASK = 0x07FF; #endif - static uint16_t SBASE(uint8_t socknum) - { - if (chip == 51) + static uint16_t SBASE(uint8_t socknum) { - return socknum * SSIZE + 0x4000; - } - else + if (chip == 51) + { + return socknum * SSIZE + 0x4000; + } + else + { + return socknum * SSIZE + 0x8000; + } + } + + static uint16_t RBASE(uint8_t socknum) { - return socknum * SSIZE + 0x8000; + if (chip == 51) + { + return socknum * SSIZE + 0x6000; + } + else + { + return socknum * SSIZE + 0xC000; + } } - } - - static uint16_t RBASE(uint8_t socknum) - { - if (chip == 51) { - return socknum * SSIZE + 0x6000; - } - else + + static bool hasOffsetAddressMapping(void) { - return socknum * SSIZE + 0xC000; + if (chip == 55) + return true; + + return false; } - } - static bool hasOffsetAddressMapping(void) - { - if (chip == 55) - return true; - - return false; - } - - static void setSS(uint8_t pin) { ss_pin = pin; } + static void setSS(uint8_t pin) + { + ss_pin = pin; + } -private: + private: #if defined(__AVR__) #warning Use AVR architecture - static volatile uint8_t *ss_pin_reg; - static uint8_t ss_pin_mask; - - inline static void initSS() - { - ss_pin_reg = portOutputRegister(digitalPinToPort(ss_pin)); - ss_pin_mask = digitalPinToBitMask(ss_pin); - pinMode(ss_pin, OUTPUT); - } - - inline static void setSS() - { - *(ss_pin_reg) &= ~ss_pin_mask; - } - - inline static void resetSS() - { - *(ss_pin_reg) |= ss_pin_mask; - } + static volatile uint8_t *ss_pin_reg; + static uint8_t ss_pin_mask; + + inline static void initSS() + { + ss_pin_reg = portOutputRegister(digitalPinToPort(ss_pin)); + ss_pin_mask = digitalPinToBitMask(ss_pin); + pinMode(ss_pin, OUTPUT); + } + + inline static void setSS() + { + *(ss_pin_reg) &= ~ss_pin_mask; + } + + inline static void resetSS() + { + *(ss_pin_reg) |= ss_pin_mask; + } #elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK66FX1M0__) || defined(__MK64FX512__) #warning Use MK architecture - static volatile uint8_t *ss_pin_reg; - - inline static void initSS() - { - ss_pin_reg = portOutputRegister(ss_pin); - pinMode(ss_pin, OUTPUT); - } - - inline static void setSS() - { - *(ss_pin_reg+256) = 1; - } - - inline static void resetSS() - { - *(ss_pin_reg+128) = 1; - } + static volatile uint8_t *ss_pin_reg; + + inline static void initSS() + { + ss_pin_reg = portOutputRegister(ss_pin); + pinMode(ss_pin, OUTPUT); + } + + inline static void setSS() + { + *(ss_pin_reg + 256) = 1; + } + + inline static void resetSS() + { + *(ss_pin_reg + 128) = 1; + } #elif defined(__IMXRT1062__) #warning Use Teensy architecture - static volatile uint32_t *ss_pin_reg; - static uint32_t ss_pin_mask; - - inline static void initSS() - { - ss_pin_reg = portOutputRegister(digitalPinToPort(ss_pin)); - ss_pin_mask = digitalPinToBitMask(ss_pin); - pinMode(ss_pin, OUTPUT); - } - - inline static void setSS() - { - *(ss_pin_reg+34) = ss_pin_mask; - } - - inline static void resetSS() - { - *(ss_pin_reg+33) = ss_pin_mask; - } + static volatile uint32_t *ss_pin_reg; + static uint32_t ss_pin_mask; + + inline static void initSS() + { + ss_pin_reg = portOutputRegister(digitalPinToPort(ss_pin)); + ss_pin_mask = digitalPinToBitMask(ss_pin); + pinMode(ss_pin, OUTPUT); + } + + inline static void setSS() + { + *(ss_pin_reg + 34) = ss_pin_mask; + } + + inline static void resetSS() + { + *(ss_pin_reg + 33) = ss_pin_mask; + } #elif defined(__MKL26Z64__) - static volatile uint8_t *ss_pin_reg; - static uint8_t ss_pin_mask; - inline static void initSS() - { - ss_pin_reg = portOutputRegister(digitalPinToPort(ss_pin)); - ss_pin_mask = digitalPinToBitMask(ss_pin); - pinMode(ss_pin, OUTPUT); - } - - inline static void setSS() - { - *(ss_pin_reg+8) = ss_pin_mask; - } - - inline static void resetSS() - { - *(ss_pin_reg+4) = ss_pin_mask; - } + static volatile uint8_t *ss_pin_reg; + static uint8_t ss_pin_mask; + inline static void initSS() + { + ss_pin_reg = portOutputRegister(digitalPinToPort(ss_pin)); + ss_pin_mask = digitalPinToBitMask(ss_pin); + pinMode(ss_pin, OUTPUT); + } + + inline static void setSS() + { + *(ss_pin_reg + 8) = ss_pin_mask; + } + + inline static void resetSS() + { + *(ss_pin_reg + 4) = ss_pin_mask; + } #elif defined(__SAM3X8E__) || defined(__SAM3A8C__) || defined(__SAM3A4C__) #warning Use SAM3 architecture - static volatile uint32_t *ss_pin_reg; - static uint32_t ss_pin_mask; - - inline static void initSS() - { - ss_pin_reg = &(digitalPinToPort(ss_pin)->PIO_PER); - ss_pin_mask = digitalPinToBitMask(ss_pin); - pinMode(ss_pin, OUTPUT); - } - - inline static void setSS() - { - *(ss_pin_reg+13) = ss_pin_mask; - } - - inline static void resetSS() - { - *(ss_pin_reg+12) = ss_pin_mask; - } + static volatile uint32_t *ss_pin_reg; + static uint32_t ss_pin_mask; + + inline static void initSS() + { + ss_pin_reg = &(digitalPinToPort(ss_pin)->PIO_PER); + ss_pin_mask = digitalPinToBitMask(ss_pin); + pinMode(ss_pin, OUTPUT); + } + + inline static void setSS() + { + *(ss_pin_reg + 13) = ss_pin_mask; + } + + inline static void resetSS() + { + *(ss_pin_reg + 12) = ss_pin_mask; + } #elif defined(__PIC32MX__) - static volatile uint32_t *ss_pin_reg; - static uint32_t ss_pin_mask; - - inline static void initSS() - { - ss_pin_reg = portModeRegister(digitalPinToPort(ss_pin)); - ss_pin_mask = digitalPinToBitMask(ss_pin); - pinMode(ss_pin, OUTPUT); - } - - inline static void setSS() - { - *(ss_pin_reg+8+1) = ss_pin_mask; - } - - inline static void resetSS() - { - *(ss_pin_reg+8+2) = ss_pin_mask; - } + static volatile uint32_t *ss_pin_reg; + static uint32_t ss_pin_mask; + + inline static void initSS() + { + ss_pin_reg = portModeRegister(digitalPinToPort(ss_pin)); + ss_pin_mask = digitalPinToBitMask(ss_pin); + pinMode(ss_pin, OUTPUT); + } + + inline static void setSS() + { + *(ss_pin_reg + 8 + 1) = ss_pin_mask; + } + + inline static void resetSS() + { + *(ss_pin_reg + 8 + 2) = ss_pin_mask; + } #elif defined(ARDUINO_ARCH_ESP8266) #warning Use ARDUINO_ARCH_ESP8266 architecture - static volatile uint32_t *ss_pin_reg; - static uint32_t ss_pin_mask; - - inline static void initSS() - { - ss_pin_reg = (volatile uint32_t*)GPO; - ss_pin_mask = 1 << ss_pin; - pinMode(ss_pin, OUTPUT); - } - - inline static void setSS() - { - GPOC = ss_pin_mask; - } - - inline static void resetSS() - { - GPOS = ss_pin_mask; - } + static volatile uint32_t *ss_pin_reg; + static uint32_t ss_pin_mask; + + inline static void initSS() + { + ss_pin_reg = (volatile uint32_t*)GPO; + ss_pin_mask = 1 << ss_pin; + pinMode(ss_pin, OUTPUT); + } + + inline static void setSS() + { + GPOC = ss_pin_mask; + } + + inline static void resetSS() + { + GPOS = ss_pin_mask; + } #elif defined(__SAMD21G18A__) #warning Use SAMD21 architecture - static volatile uint32_t *ss_pin_reg; - static uint32_t ss_pin_mask; - - inline static void initSS() - { - ss_pin_reg = portModeRegister(digitalPinToPort(ss_pin)); - ss_pin_mask = digitalPinToBitMask(ss_pin); - pinMode(ss_pin, OUTPUT); - } - - inline static void setSS() - { - *(ss_pin_reg+5) = ss_pin_mask; - } - - inline static void resetSS() - { - *(ss_pin_reg+6) = ss_pin_mask; - } + static volatile uint32_t *ss_pin_reg; + static uint32_t ss_pin_mask; + + inline static void initSS() + { + ss_pin_reg = portModeRegister(digitalPinToPort(ss_pin)); + ss_pin_mask = digitalPinToBitMask(ss_pin); + pinMode(ss_pin, OUTPUT); + } + + inline static void setSS() + { + *(ss_pin_reg + 5) = ss_pin_mask; + } + + inline static void resetSS() + { + *(ss_pin_reg + 6) = ss_pin_mask; + } #else #warning Use Default architecture - inline static void initSS() - { - pinMode(ss_pin, OUTPUT); - } - - inline static void setSS() - { - digitalWrite(ss_pin, LOW); - } - - inline static void resetSS() - { - digitalWrite(ss_pin, HIGH); - } + inline static void initSS() + { + pinMode(ss_pin, OUTPUT); + } + + inline static void setSS() + { + digitalWrite(ss_pin, LOW); + } + + inline static void resetSS() + { + digitalWrite(ss_pin, HIGH); + } #endif }; @@ -611,11 +656,11 @@ extern W5100Class W5100; #define UTIL_H #ifndef htons -#define htons(x) ( (((x)<<8)&0xFF00) | (((x)>>8)&0xFF) ) + #define htons(x) ( (((x)<<8)&0xFF00) | (((x)>>8)&0xFF) ) #endif #ifndef ntohs -#define ntohs(x) htons(x) + #define ntohs(x) htons(x) #endif #ifndef htonl @@ -624,9 +669,9 @@ extern W5100Class W5100; ((x)>> 8 & 0x0000FF00UL) | \ ((x)>>24 & 0x000000FFUL) ) #endif - -#ifndef ntohl -#define ntohl(x) htonl(x) + +#ifndef ntohl + #define ntohl(x) htonl(x) #endif #endif //W5100_H_INCLUDED diff --git a/LibraryPatches/UIPEthernet-2.0.9/UIPEthernet.cpp b/LibraryPatches/UIPEthernet-2.0.9/UIPEthernet.cpp index 2af3cfb..f798aa7 100644 --- a/LibraryPatches/UIPEthernet-2.0.9/UIPEthernet.cpp +++ b/LibraryPatches/UIPEthernet-2.0.9/UIPEthernet.cpp @@ -1,625 +1,684 @@ -/* - UIPEthernet.cpp - Arduino implementation of a uIP wrapper class. - Copyright (c) 2013 Norbert Truchsess - All rights reserved. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -#if defined(ARDUINO) - #include -#endif -#if defined(__MBED__) - #include - #include "mbed/millis.h" -#endif -#include "UIPEthernet.h" -#include "utility/logging.h" -#include "utility/Enc28J60Network.h" - -#include "UIPUdp.h" - -extern "C" -{ -#include "utility/uipopt.h" -#include "utility/uip.h" -#include "utility/uip_arp.h" -} - -#define ETH_HDR ((struct uip_eth_hdr *)&uip_buf[0]) - -memhandle UIPEthernetClass::in_packet(NOBLOCK); -memhandle UIPEthernetClass::uip_packet(NOBLOCK); -uint8_t UIPEthernetClass::uip_hdrlen(0); -uint8_t UIPEthernetClass::packetstate(0); - -unsigned long UIPEthernetClass::periodic_timer; - -IPAddress UIPEthernetClass::_dnsServerAddress; -#if UIP_UDP - DhcpClass* UIPEthernetClass::_dhcp(NULL); - static DhcpClass s_dhcp; // Placing this instance here is saving 40K to final *.bin (see bug below) -#endif - -// Because uIP isn't encapsulated within a class we have to use global -// variables, so we can only have one TCP/IP stack per program. - -UIPEthernetClass::UIPEthernetClass() -{ -} - -void UIPEthernetClass::init(const uint8_t pin) -{ - ENC28J60ControlCS = pin; -} - -#if UIP_UDP -int -UIPEthernetClass::begin(const uint8_t* mac) -{ - // KH mod to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ - // Now store to private var _mac_address - //uint8_t _mac_address[6] ={0,}; - memcpy(_mac_address, mac, sizeof(_mac_address)); - ////// - - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::begin(const uint8_t* mac) DEBUG_V3:Function started")); - #endif - //static DhcpClass s_dhcp; // <-- this is a bug ! - // I leave it there commented for history. It is bring all GCC "new" memory allocation code, making the *.bin almost 40K bigger. I've move it globally. - _dhcp = &s_dhcp; - // Initialise the basic info - netInit(mac); - - // Now try to get our config info from a DHCP server - int ret = _dhcp->beginWithDHCP((uint8_t*)mac); - if(ret == 1) - { - // We've successfully found a DHCP server and got our configuration info, so set things - // accordingly - configure(_dhcp->getLocalIp(),_dhcp->getDnsServerIp(),_dhcp->getGatewayIp(),_dhcp->getSubnetMask()); - } - return ret; -} -#endif - -void -UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip) -{ - // KH mod to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ - // Now store to private var _mac_address - //uint8_t _mac_address[6] ={0,}; - memcpy(_mac_address, mac, sizeof(_mac_address)); - ////// - - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip) DEBUG_V3:Function started")); - #endif - IPAddress dns = ip; - dns[3] = 1; - begin(mac, ip, dns); -} - -void -UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns) -{ - // KH mod to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ - // Now store to private var _mac_address - //uint8_t _mac_address[6] ={0,}; - memcpy(_mac_address, mac, sizeof(_mac_address)); - ////// - - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns) DEBUG_V3:Function started")); - #endif - IPAddress gateway = ip; - gateway[3] = 1; - begin(mac, ip, dns, gateway); -} - -void -UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway) -{ - // KH mod to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ - // Now store to private var _mac_address - //uint8_t _mac_address[6] ={0,}; - memcpy(_mac_address, mac, sizeof(_mac_address)); - ////// - - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway) DEBUG_V3:Function started")); - #endif - IPAddress subnet(255, 255, 255, 0); - begin(mac, ip, dns, gateway, subnet); -} - -void -UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) -{ - // KH mod to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ - // Now store to private var _mac_address - //uint8_t _mac_address[6] ={0,}; - memcpy(_mac_address, mac, sizeof(_mac_address)); - ////// - - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) DEBUG_V3:Function started")); - #endif - netInit(mac); - configure(ip,dns,gateway,subnet); -} - -int UIPEthernetClass::maintain(){ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::maintain() DEBUG_V3:Function started")); - #endif - tick(); - int rc = DHCP_CHECK_NONE; -#if UIP_UDP - if(_dhcp != NULL){ - //we have a pointer to dhcp, use it - rc = _dhcp->checkLease(); - switch ( rc ){ - case DHCP_CHECK_NONE: - //nothing done - break; - case DHCP_CHECK_RENEW_OK: - case DHCP_CHECK_REBIND_OK: - //we might have got a new IP. - configure(_dhcp->getLocalIp(),_dhcp->getDnsServerIp(),_dhcp->getGatewayIp(),_dhcp->getSubnetMask()); - break; - default: - //this is actually a error, it will retry though - break; - } - } - return rc; -#endif -} - -EthernetLinkStatus UIPEthernetClass::linkStatus() -{ - if (!Enc28J60Network::geterevid()) - return Unknown; - return Enc28J60Network::linkStatus() ? LinkON : LinkOFF; -} - -EthernetHardwareStatus UIPEthernetClass::hardwareStatus() { - if (!Enc28J60Network::geterevid()) - return EthernetNoHardware; - return EthernetENC28J60; -} - -IPAddress UIPEthernetClass::localIP() -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::localIP() DEBUG_V3:Function started")); - #endif - IPAddress ret; - uip_ipaddr_t a; - uip_gethostaddr(a); - return ip_addr_uip(a); -} - -IPAddress UIPEthernetClass::subnetMask() -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::subnetMask() DEBUG_V3:Function started")); - #endif - IPAddress ret; - uip_ipaddr_t a; - uip_getnetmask(a); - return ip_addr_uip(a); -} - -IPAddress UIPEthernetClass::gatewayIP() -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::gatewayIP() DEBUG_V3:Function started")); - #endif - IPAddress ret; - uip_ipaddr_t a; - uip_getdraddr(a); - return ip_addr_uip(a); -} - -IPAddress UIPEthernetClass::dnsServerIP() -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::dnsServerIP() DEBUG_V3:Function started")); - #endif - return _dnsServerAddress; -} - -void -UIPEthernetClass::tick() -{ -#if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::tick() DEBUG_V3:Function started")); -#endif -if (Enc28J60Network::geterevid()==0) - { - #if ACTLOGLEVEL>=LOG_ERR - LogObject.uart_send_strln(F("UIPEthernetClass::tick() ERROR:EREVID=0 -> Not found ENC28j60 device !! Function ended !!")); - #endif - return; - } -#if defined(ESP8266) - wdt_reset(); -#endif - if (in_packet == NOBLOCK) - { - in_packet = Enc28J60Network::receivePacket(); - #if ACTLOGLEVEL>=LOG_DEBUG - if (in_packet != NOBLOCK) - { - LogObject.uart_send_str(F("UIPEthernetClass::tick() DEBUG:receivePacket: ")); - LogObject.uart_send_decln(in_packet); - } - #endif - } - if (in_packet != NOBLOCK) - { - packetstate = UIPETHERNET_FREEPACKET; - uip_len = Enc28J60Network::blockSize(in_packet); - if (uip_len > 0) - { - Enc28J60Network::readPacket(in_packet,0,(uint8_t*)uip_buf,UIP_BUFSIZE); - if (ETH_HDR ->type == HTONS(UIP_ETHTYPE_IP)) - { - uip_packet = in_packet; //required for upper_layer_checksum of in_packet! - #if ACTLOGLEVEL>=LOG_DEBUG - LogObject.uart_send_str(F("UIPEthernetClass::tick() DEBUG:readPacket type IP, uip_len: ")); - LogObject.uart_send_decln(uip_len); - #endif - uip_arp_ipin(); - uip_input(); - if (uip_len > 0) - { - uip_arp_out(); - network_send(); - } - } - else if (ETH_HDR ->type == HTONS(UIP_ETHTYPE_ARP)) - { - #if ACTLOGLEVEL>=LOG_DEBUG - LogObject.uart_send_str(F("UIPEthernetClass::tick() DEBUG:readPacket type ARP, uip_len: ")); - LogObject.uart_send_decln(uip_len); - #endif - uip_arp_arpin(); - if (uip_len > 0) - { - network_send(); - } - } - } - if (in_packet != NOBLOCK && (packetstate & UIPETHERNET_FREEPACKET)) - { - #if ACTLOGLEVEL>=LOG_DEBUG - LogObject.uart_send_str(F("UIPEthernetClass::tick() DEBUG:freeing packet: ")); - LogObject.uart_send_decln(in_packet); - #endif - Enc28J60Network::freePacket(); - in_packet = NOBLOCK; - } - } - - unsigned long now = millis(); - -#if UIP_CLIENT_TIMER >= 0 - bool periodic = (long)( now - periodic_timer ) >= 0; - for (int i = 0; i < UIP_CONNS; i++) - { -#else - if ((long)( now - periodic_timer ) >= 0) - { - periodic_timer = now + UIP_PERIODIC_TIMER; - - for (int i = 0; i < UIP_CONNS; i++) - { -#endif - - uip_conn = &uip_conns[i]; - -#if UIP_CLIENT_TIMER >= 0 - if (periodic) - { -#endif - - uip_process(UIP_TIMER); - -#if UIP_CLIENT_TIMER >= 0 - } - else - { - if (((uip_userdata_t*)uip_conn->appstate)!=NULL) - { - if ((long)( now - ((uip_userdata_t*)uip_conn->appstate)->timer) >= 0) - { - uip_process(UIP_POLL_REQUEST); - ((uip_userdata_t*)uip_conn->appstate)->timer = millis() + UIP_CLIENT_TIMER; - } - else - { - continue; - } - } - else - continue; - } -#endif - // If the above function invocation resulted in data that - // should be sent out on the Enc28J60Network, the global variable - // uip_len is set to a value > 0. - if (uip_len > 0) - { - uip_arp_out(); - network_send(); - } - } -#if UIP_CLIENT_TIMER >= 0 - if (periodic) - { - periodic_timer = now + UIP_PERIODIC_TIMER; -#endif -#if UIP_UDP - for (int i = 0; i < UIP_UDP_CONNS; i++) - { - uip_udp_periodic(i); - // If the above function invocation resulted in data that - // should be sent out on the Enc28J60Network, the global variable - // uip_len is set to a value > 0. */ - if (uip_len > 0) - { - UIPUDP::_send((uip_udp_userdata_t *)(uip_udp_conns[i].appstate)); - } - } -#endif /* UIP_UDP */ - } -} - -bool UIPEthernetClass::network_send() -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::network_send() DEBUG_V3:Function started")); - #endif - if (packetstate & UIPETHERNET_SENDPACKET) - { -#if ACTLOGLEVEL>=LOG_DEBUG - LogObject.uart_send_str(F("UIPEthernetClass::network_send() DEBUG:uip_packet: ")); - LogObject.uart_send_dec(uip_packet); - LogObject.uart_send_str(F(", hdrlen: ")); - LogObject.uart_send_decln(uip_hdrlen); -#endif - Enc28J60Network::writePacket(uip_packet, UIP_SENDBUFFER_OFFSET,uip_buf,uip_hdrlen); - packetstate &= ~ UIPETHERNET_SENDPACKET; - goto sendandfree; - } - uip_packet = Enc28J60Network::allocBlock(uip_len + UIP_SENDBUFFER_OFFSET + UIP_SENDBUFFER_PADDING); - if (uip_packet != NOBLOCK) - { -#if ACTLOGLEVEL>=LOG_DEBUG - LogObject.uart_send_str(F("UIPEthernetClass::network_send() DEBUG:uip_buf (uip_len): ")); - LogObject.uart_send_dec(uip_len); - LogObject.uart_send_str(F(", packet: ")); - LogObject.uart_send_decln(uip_packet); -#endif - Enc28J60Network::writePacket(uip_packet, UIP_SENDBUFFER_OFFSET,uip_buf,uip_len); - goto sendandfree; - } - return false; -sendandfree: - bool success = Enc28J60Network::sendPacket(uip_packet); - Enc28J60Network::freeBlock(uip_packet); - uip_packet = NOBLOCK; - return success; -} - -void UIPEthernetClass::netInit(const uint8_t* mac) { - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::netInit(const uint8_t* mac) DEBUG_V3:Function started")); - #endif - periodic_timer = millis() + UIP_PERIODIC_TIMER; - - Enc28J60Network::init((uint8_t*)mac); - uip_seteth_addr(mac); - - uip_init(); - uip_arp_init(); -} - -void UIPEthernetClass::configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) { - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) DEBUG_V3:Function started")); - #endif - uip_ipaddr_t ipaddr; - - uip_ip_addr(ipaddr, ip); - uip_sethostaddr(ipaddr); - - uip_ip_addr(ipaddr, gateway); - uip_setdraddr(ipaddr); - - uip_ip_addr(ipaddr, subnet); - uip_setnetmask(ipaddr); - - _dnsServerAddress = dns; -} - -UIPEthernetClass UIPEthernet; - -/*---------------------------------------------------------------------------*/ -uint16_t -UIPEthernetClass::chksum(uint16_t sum, const uint8_t *data, uint16_t len) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::chksum(uint16_t sum, const uint8_t *data, uint16_t len) DEBUG_V3:Function started")); - #endif - uint16_t t; - const uint8_t *dataptr; - const uint8_t *last_byte; - - dataptr = data; - last_byte = data + len - 1; - - while(dataptr < last_byte) { /* At least two more bytes */ - t = (dataptr[0] << 8) + dataptr[1]; - sum += t; - if(sum < t) { - sum++; /* carry */ - } - dataptr += 2; - } - - if(dataptr == last_byte) { - t = (dataptr[0] << 8) + 0; - sum += t; - if(sum < t) { - sum++; /* carry */ - } - } - - /* Return sum in host byte order. */ - return sum; -} - -/*---------------------------------------------------------------------------*/ - -uint16_t -UIPEthernetClass::ipchksum(void) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::ipchksum(void) DEBUG_V3:Function started")); - #endif - uint16_t sum; - - sum = chksum(0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN); - return (sum == 0) ? 0xffff : htons(sum); -} - -/*---------------------------------------------------------------------------*/ -uint16_t -#if UIP_UDP -UIPEthernetClass::upper_layer_chksum(uint8_t proto) -#else -uip_tcpchksum(void) -#endif -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - #if UIP_UDP - LogObject.uart_send_strln(F("UIPEthernetClass::upper_layer_chksum(uint8_t proto) DEBUG_V3:Function started")); - #else - LogObject.uart_send_strln(F("uip_tcpchksum(void) INFO:Function started")); - #endif - #endif - uint16_t upper_layer_len; - uint16_t sum; - -#if UIP_CONF_IPV6 - upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]); -#else /* UIP_CONF_IPV6 */ - upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - UIP_IPH_LEN; -#endif /* UIP_CONF_IPV6 */ - - /* First sum pseudoheader. */ - - /* IP protocol and length fields. This addition cannot carry. */ -#if UIP_UDP - sum = upper_layer_len + proto; -#else - sum = upper_layer_len + UIP_PROTO_TCP; -#endif - /* Sum IP source and destination addresses. */ - sum = UIPEthernetClass::chksum(sum, (u8_t *)&BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t)); - - uint8_t upper_layer_memlen; -#if UIP_UDP - switch(proto) - { -// case UIP_PROTO_ICMP: -// case UIP_PROTO_ICMP6: -// upper_layer_memlen = upper_layer_len; -// break; - case UIP_PROTO_UDP: - upper_layer_memlen = UIP_UDPH_LEN; - break; - default: -// case UIP_PROTO_TCP: -#endif - upper_layer_memlen = (BUF->tcpoffset >> 4) << 2; -#if UIP_UDP - break; - } -#endif - sum = UIPEthernetClass::chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], upper_layer_memlen); -#if ACTLOGLEVEL>=LOG_DEBUG - #if UIP_UDP - LogObject.uart_send_str(F("UIPEthernetClass::upper_layer_chksum(uint8_t proto) DEBUG:uip_buf[")); - #else - LogObject.uart_send_str(F("uip_tcpchksum(void) DEBUG:uip_buf[")); - #endif - LogObject.uart_send_dec(UIP_IPH_LEN + UIP_LLH_LEN); - LogObject.uart_send_str(F("-")); - LogObject.uart_send_dec(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen); - LogObject.uart_send_str(F("]: ")); - LogObject.uart_send_hexln(htons(sum)); -#endif - if (upper_layer_memlen < upper_layer_len) - { - sum = Enc28J60Network::chksum( - sum, - UIPEthernetClass::uip_packet, - (UIPEthernetClass::packetstate & UIPETHERNET_SENDPACKET ? UIP_IPH_LEN + UIP_LLH_LEN + UIP_SENDBUFFER_OFFSET : UIP_IPH_LEN + UIP_LLH_LEN) + upper_layer_memlen, - upper_layer_len - upper_layer_memlen - ); -#if ACTLOGLEVEL>=LOG_DEBUG - #if UIP_UDP - LogObject.uart_send_str(F("UIPEthernetClass::upper_layer_chksum(uint8_t proto) DEBUG:uip_packet(")); - #else - LogObject.uart_send_str(F("uip_tcpchksum(void) DEBUG:uip_packet(")); - #endif - LogObject.uart_send_dec(UIPEthernetClass::uip_packet); - LogObject.uart_send_str(F(")[")); - LogObject.uart_send_dec(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen); - LogObject.uart_send_str(F("-")); - LogObject.uart_send_dec(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_len); - LogObject.uart_send_str(F("]: ")); - LogObject.uart_send_hexln(htons(sum)); -#endif - } - return (sum == 0) ? 0xffff : htons(sum); -} - -uint16_t -uip_ipchksum(void) -{ - return UIPEthernet.ipchksum(); -} - -#if UIP_UDP -uint16_t -uip_tcpchksum(void) -{ - uint16_t sum = UIPEthernet.upper_layer_chksum(UIP_PROTO_TCP); - return sum; -} - -uint16_t -uip_udpchksum(void) -{ - uint16_t sum = UIPEthernet.upper_layer_chksum(UIP_PROTO_UDP); - return sum; -} -#endif +/* + UIPEthernet.cpp - Arduino implementation of a uIP wrapper class. + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if defined(ARDUINO) + #include +#endif +#if defined(__MBED__) + #include + #include "mbed/millis.h" +#endif +#include "UIPEthernet.h" +#include "utility/logging.h" +#include "utility/Enc28J60Network.h" + +#include "UIPUdp.h" + +extern "C" +{ +#include "utility/uipopt.h" +#include "utility/uip.h" +#include "utility/uip_arp.h" +} + +#define ETH_HDR ((struct uip_eth_hdr *)&uip_buf[0]) + +memhandle UIPEthernetClass::in_packet(NOBLOCK); +memhandle UIPEthernetClass::uip_packet(NOBLOCK); +uint8_t UIPEthernetClass::uip_hdrlen(0); +uint8_t UIPEthernetClass::packetstate(0); + +unsigned long UIPEthernetClass::periodic_timer; + +IPAddress UIPEthernetClass::_dnsServerAddress; +#if UIP_UDP + DhcpClass* UIPEthernetClass::_dhcp(NULL); + static DhcpClass s_dhcp; // Placing this instance here is saving 40K to final *.bin (see bug below) +#endif + +// Because uIP isn't encapsulated within a class we have to use global +// variables, so we can only have one TCP/IP stack per program. + +UIPEthernetClass::UIPEthernetClass() +{ +} + +void UIPEthernetClass::init(const uint8_t pin) +{ + ENC28J60ControlCS = pin; +} + +#if UIP_UDP +int +UIPEthernetClass::begin(const uint8_t* mac) +{ + // KH mod to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ + // Now store to private var _mac_address + //uint8_t _mac_address[6] ={0,}; + memcpy(_mac_address, mac, sizeof(_mac_address)); + ////// + +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("UIPEthernetClass::begin(const uint8_t* mac) DEBUG_V3:Function started")); +#endif + //static DhcpClass s_dhcp; // <-- this is a bug ! + // I leave it there commented for history. It is bring all GCC "new" memory allocation code, making the *.bin almost 40K bigger. I've move it globally. + _dhcp = &s_dhcp; + // Initialise the basic info + netInit(mac); + + // Now try to get our config info from a DHCP server + int ret = _dhcp->beginWithDHCP((uint8_t*)mac); + + if (ret == 1) + { + // We've successfully found a DHCP server and got our configuration info, so set things + // accordingly + configure(_dhcp->getLocalIp(), _dhcp->getDnsServerIp(), _dhcp->getGatewayIp(), _dhcp->getSubnetMask()); + } + + return ret; +} +#endif + +void +UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip) +{ + // KH mod to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ + // Now store to private var _mac_address + //uint8_t _mac_address[6] ={0,}; + memcpy(_mac_address, mac, sizeof(_mac_address)); + ////// + +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip) DEBUG_V3:Function started")); +#endif + IPAddress dns = ip; + dns[3] = 1; + begin(mac, ip, dns); +} + +void +UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns) +{ + // KH mod to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ + // Now store to private var _mac_address + //uint8_t _mac_address[6] ={0,}; + memcpy(_mac_address, mac, sizeof(_mac_address)); + ////// + +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln( + F("UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns) DEBUG_V3:Function started")); +#endif + IPAddress gateway = ip; + gateway[3] = 1; + begin(mac, ip, dns, gateway); +} + +void +UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway) +{ + // KH mod to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ + // Now store to private var _mac_address + //uint8_t _mac_address[6] ={0,}; + memcpy(_mac_address, mac, sizeof(_mac_address)); + ////// + +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln( + F("UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway) DEBUG_V3:Function started")); +#endif + IPAddress subnet(255, 255, 255, 0); + begin(mac, ip, dns, gateway, subnet); +} + +void +UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) +{ + // KH mod to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ + // Now store to private var _mac_address + //uint8_t _mac_address[6] ={0,}; + memcpy(_mac_address, mac, sizeof(_mac_address)); + ////// + +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln( + F("UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) DEBUG_V3:Function started")); +#endif + netInit(mac); + configure(ip, dns, gateway, subnet); +} + +int UIPEthernetClass::maintain() +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("UIPEthernetClass::maintain() DEBUG_V3:Function started")); +#endif + tick(); + int rc = DHCP_CHECK_NONE; +#if UIP_UDP + + if (_dhcp != NULL) + { + //we have a pointer to dhcp, use it + rc = _dhcp->checkLease(); + + switch ( rc ) + { + case DHCP_CHECK_NONE: + //nothing done + break; + + case DHCP_CHECK_RENEW_OK: + case DHCP_CHECK_REBIND_OK: + //we might have got a new IP. + configure(_dhcp->getLocalIp(), _dhcp->getDnsServerIp(), _dhcp->getGatewayIp(), _dhcp->getSubnetMask()); + break; + + default: + //this is actually a error, it will retry though + break; + } + } + + return rc; +#endif +} + +EthernetLinkStatus UIPEthernetClass::linkStatus() +{ + if (!Enc28J60Network::geterevid()) + return Unknown; + + return Enc28J60Network::linkStatus() ? LinkON : LinkOFF; +} + +EthernetHardwareStatus UIPEthernetClass::hardwareStatus() +{ + if (!Enc28J60Network::geterevid()) + return EthernetNoHardware; + + return EthernetENC28J60; +} + +IPAddress UIPEthernetClass::localIP() +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("UIPEthernetClass::localIP() DEBUG_V3:Function started")); +#endif + IPAddress ret; + uip_ipaddr_t a; + uip_gethostaddr(a); + return ip_addr_uip(a); +} + +IPAddress UIPEthernetClass::subnetMask() +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("UIPEthernetClass::subnetMask() DEBUG_V3:Function started")); +#endif + IPAddress ret; + uip_ipaddr_t a; + uip_getnetmask(a); + return ip_addr_uip(a); +} + +IPAddress UIPEthernetClass::gatewayIP() +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("UIPEthernetClass::gatewayIP() DEBUG_V3:Function started")); +#endif + IPAddress ret; + uip_ipaddr_t a; + uip_getdraddr(a); + return ip_addr_uip(a); +} + +IPAddress UIPEthernetClass::dnsServerIP() +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("UIPEthernetClass::dnsServerIP() DEBUG_V3:Function started")); +#endif + return _dnsServerAddress; +} + +void +UIPEthernetClass::tick() +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("UIPEthernetClass::tick() DEBUG_V3:Function started")); +#endif + + if (Enc28J60Network::geterevid() == 0) + { +#if ACTLOGLEVEL>=LOG_ERR + LogObject.uart_send_strln( + F("UIPEthernetClass::tick() ERROR:EREVID=0 -> Not found ENC28j60 device !! Function ended !!")); +#endif + return; + } + +#if defined(ESP8266) + wdt_reset(); +#endif + + if (in_packet == NOBLOCK) + { + in_packet = Enc28J60Network::receivePacket(); +#if ACTLOGLEVEL>=LOG_DEBUG + + if (in_packet != NOBLOCK) + { + LogObject.uart_send_str(F("UIPEthernetClass::tick() DEBUG:receivePacket: ")); + LogObject.uart_send_decln(in_packet); + } + +#endif + } + + if (in_packet != NOBLOCK) + { + packetstate = UIPETHERNET_FREEPACKET; + uip_len = Enc28J60Network::blockSize(in_packet); + + if (uip_len > 0) + { + Enc28J60Network::readPacket(in_packet, 0, (uint8_t*)uip_buf, UIP_BUFSIZE); + + if (ETH_HDR ->type == HTONS(UIP_ETHTYPE_IP)) + { + uip_packet = in_packet; //required for upper_layer_checksum of in_packet! +#if ACTLOGLEVEL>=LOG_DEBUG + LogObject.uart_send_str(F("UIPEthernetClass::tick() DEBUG:readPacket type IP, uip_len: ")); + LogObject.uart_send_decln(uip_len); +#endif + uip_arp_ipin(); + uip_input(); + + if (uip_len > 0) + { + uip_arp_out(); + network_send(); + } + } + else if (ETH_HDR ->type == HTONS(UIP_ETHTYPE_ARP)) + { +#if ACTLOGLEVEL>=LOG_DEBUG + LogObject.uart_send_str(F("UIPEthernetClass::tick() DEBUG:readPacket type ARP, uip_len: ")); + LogObject.uart_send_decln(uip_len); +#endif + uip_arp_arpin(); + + if (uip_len > 0) + { + network_send(); + } + } + } + + if (in_packet != NOBLOCK && (packetstate & UIPETHERNET_FREEPACKET)) + { +#if ACTLOGLEVEL>=LOG_DEBUG + LogObject.uart_send_str(F("UIPEthernetClass::tick() DEBUG:freeing packet: ")); + LogObject.uart_send_decln(in_packet); +#endif + Enc28J60Network::freePacket(); + in_packet = NOBLOCK; + } + } + + unsigned long now = millis(); + +#if UIP_CLIENT_TIMER >= 0 + bool periodic = (long)( now - periodic_timer ) >= 0; + + for (int i = 0; i < UIP_CONNS; i++) + { +#else + + if ((long)( now - periodic_timer ) >= 0) + { + periodic_timer = now + UIP_PERIODIC_TIMER; + + for (int i = 0; i < UIP_CONNS; i++) + { +#endif + + uip_conn = &uip_conns[i]; + +#if UIP_CLIENT_TIMER >= 0 + + if (periodic) + { +#endif + + uip_process(UIP_TIMER); + +#if UIP_CLIENT_TIMER >= 0 + } + else + { + if (((uip_userdata_t*)uip_conn->appstate) != NULL) + { + if ((long)( now - ((uip_userdata_t*)uip_conn->appstate)->timer) >= 0) + { + uip_process(UIP_POLL_REQUEST); + ((uip_userdata_t*)uip_conn->appstate)->timer = millis() + UIP_CLIENT_TIMER; + } + else + { + continue; + } + } + else + continue; + } + +#endif + + // If the above function invocation resulted in data that + // should be sent out on the Enc28J60Network, the global variable + // uip_len is set to a value > 0. + if (uip_len > 0) + { + uip_arp_out(); + network_send(); + } + } + +#if UIP_CLIENT_TIMER >= 0 + + if (periodic) + { + periodic_timer = now + UIP_PERIODIC_TIMER; +#endif +#if UIP_UDP + + for (int i = 0; i < UIP_UDP_CONNS; i++) + { + uip_udp_periodic(i); + + // If the above function invocation resulted in data that + // should be sent out on the Enc28J60Network, the global variable + // uip_len is set to a value > 0. */ + if (uip_len > 0) + { + UIPUDP::_send((uip_udp_userdata_t *)(uip_udp_conns[i].appstate)); + } + } + +#endif /* UIP_UDP */ + } +} + +bool UIPEthernetClass::network_send() +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("UIPEthernetClass::network_send() DEBUG_V3:Function started")); +#endif + + if (packetstate & UIPETHERNET_SENDPACKET) + { +#if ACTLOGLEVEL>=LOG_DEBUG + LogObject.uart_send_str(F("UIPEthernetClass::network_send() DEBUG:uip_packet: ")); + LogObject.uart_send_dec(uip_packet); + LogObject.uart_send_str(F(", hdrlen: ")); + LogObject.uart_send_decln(uip_hdrlen); +#endif + Enc28J60Network::writePacket(uip_packet, UIP_SENDBUFFER_OFFSET, uip_buf, uip_hdrlen); + packetstate &= ~ UIPETHERNET_SENDPACKET; + goto sendandfree; + } + + uip_packet = Enc28J60Network::allocBlock(uip_len + UIP_SENDBUFFER_OFFSET + UIP_SENDBUFFER_PADDING); + + if (uip_packet != NOBLOCK) + { +#if ACTLOGLEVEL>=LOG_DEBUG + LogObject.uart_send_str(F("UIPEthernetClass::network_send() DEBUG:uip_buf (uip_len): ")); + LogObject.uart_send_dec(uip_len); + LogObject.uart_send_str(F(", packet: ")); + LogObject.uart_send_decln(uip_packet); +#endif + Enc28J60Network::writePacket(uip_packet, UIP_SENDBUFFER_OFFSET, uip_buf, uip_len); + goto sendandfree; + } + + return false; +sendandfree: + bool success = Enc28J60Network::sendPacket(uip_packet); + Enc28J60Network::freeBlock(uip_packet); + uip_packet = NOBLOCK; + return success; +} + +void UIPEthernetClass::netInit(const uint8_t* mac) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("UIPEthernetClass::netInit(const uint8_t* mac) DEBUG_V3:Function started")); +#endif + periodic_timer = millis() + UIP_PERIODIC_TIMER; + + Enc28J60Network::init((uint8_t*)mac); + uip_seteth_addr(mac); + + uip_init(); + uip_arp_init(); +} + +void UIPEthernetClass::configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln( + F("UIPEthernetClass::configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) DEBUG_V3:Function started")); +#endif + uip_ipaddr_t ipaddr; + + uip_ip_addr(ipaddr, ip); + uip_sethostaddr(ipaddr); + + uip_ip_addr(ipaddr, gateway); + uip_setdraddr(ipaddr); + + uip_ip_addr(ipaddr, subnet); + uip_setnetmask(ipaddr); + + _dnsServerAddress = dns; +} + +UIPEthernetClass UIPEthernet; + +/*---------------------------------------------------------------------------*/ +uint16_t +UIPEthernetClass::chksum(uint16_t sum, const uint8_t *data, uint16_t len) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln( + F("UIPEthernetClass::chksum(uint16_t sum, const uint8_t *data, uint16_t len) DEBUG_V3:Function started")); +#endif + uint16_t t; + const uint8_t *dataptr; + const uint8_t *last_byte; + + dataptr = data; + last_byte = data + len - 1; + + while (dataptr < last_byte) /* At least two more bytes */ + { + t = (dataptr[0] << 8) + dataptr[1]; + sum += t; + + if (sum < t) + { + sum++; /* carry */ + } + + dataptr += 2; + } + + if (dataptr == last_byte) + { + t = (dataptr[0] << 8) + 0; + sum += t; + + if (sum < t) + { + sum++; /* carry */ + } + } + + /* Return sum in host byte order. */ + return sum; +} + +/*---------------------------------------------------------------------------*/ + +uint16_t +UIPEthernetClass::ipchksum(void) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("UIPEthernetClass::ipchksum(void) DEBUG_V3:Function started")); +#endif + uint16_t sum; + + sum = chksum(0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN); + return (sum == 0) ? 0xffff : htons(sum); +} + +/*---------------------------------------------------------------------------*/ +uint16_t +#if UIP_UDP +UIPEthernetClass::upper_layer_chksum(uint8_t proto) +#else +uip_tcpchksum(void) +#endif +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 +#if UIP_UDP + LogObject.uart_send_strln(F("UIPEthernetClass::upper_layer_chksum(uint8_t proto) DEBUG_V3:Function started")); +#else + LogObject.uart_send_strln(F("uip_tcpchksum(void) INFO:Function started")); +#endif +#endif + uint16_t upper_layer_len; + uint16_t sum; + +#if UIP_CONF_IPV6 + upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]); +#else /* UIP_CONF_IPV6 */ + upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - UIP_IPH_LEN; +#endif /* UIP_CONF_IPV6 */ + + /* First sum pseudoheader. */ + + /* IP protocol and length fields. This addition cannot carry. */ +#if UIP_UDP + sum = upper_layer_len + proto; +#else + sum = upper_layer_len + UIP_PROTO_TCP; +#endif + /* Sum IP source and destination addresses. */ + sum = UIPEthernetClass::chksum(sum, (u8_t *)&BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t)); + + uint8_t upper_layer_memlen; +#if UIP_UDP + + switch (proto) + { + // case UIP_PROTO_ICMP: + // case UIP_PROTO_ICMP6: + // upper_layer_memlen = upper_layer_len; + // break; + case UIP_PROTO_UDP: + upper_layer_memlen = UIP_UDPH_LEN; + break; + + default: + // case UIP_PROTO_TCP: +#endif + upper_layer_memlen = (BUF->tcpoffset >> 4) << 2; +#if UIP_UDP + break; + } + +#endif + sum = UIPEthernetClass::chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], upper_layer_memlen); +#if ACTLOGLEVEL>=LOG_DEBUG +#if UIP_UDP + LogObject.uart_send_str(F("UIPEthernetClass::upper_layer_chksum(uint8_t proto) DEBUG:uip_buf[")); +#else + LogObject.uart_send_str(F("uip_tcpchksum(void) DEBUG:uip_buf[")); +#endif + LogObject.uart_send_dec(UIP_IPH_LEN + UIP_LLH_LEN); + LogObject.uart_send_str(F("-")); + LogObject.uart_send_dec(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen); + LogObject.uart_send_str(F("]: ")); + LogObject.uart_send_hexln(htons(sum)); +#endif + + if (upper_layer_memlen < upper_layer_len) + { + sum = Enc28J60Network::chksum( + sum, + UIPEthernetClass::uip_packet, + (UIPEthernetClass::packetstate & UIPETHERNET_SENDPACKET ? UIP_IPH_LEN + UIP_LLH_LEN + UIP_SENDBUFFER_OFFSET : + UIP_IPH_LEN + UIP_LLH_LEN) + upper_layer_memlen, + upper_layer_len - upper_layer_memlen + ); +#if ACTLOGLEVEL>=LOG_DEBUG +#if UIP_UDP + LogObject.uart_send_str(F("UIPEthernetClass::upper_layer_chksum(uint8_t proto) DEBUG:uip_packet(")); +#else + LogObject.uart_send_str(F("uip_tcpchksum(void) DEBUG:uip_packet(")); +#endif + LogObject.uart_send_dec(UIPEthernetClass::uip_packet); + LogObject.uart_send_str(F(")[")); + LogObject.uart_send_dec(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen); + LogObject.uart_send_str(F("-")); + LogObject.uart_send_dec(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_len); + LogObject.uart_send_str(F("]: ")); + LogObject.uart_send_hexln(htons(sum)); +#endif + } + + return (sum == 0) ? 0xffff : htons(sum); +} + +uint16_t +uip_ipchksum(void) +{ + return UIPEthernet.ipchksum(); +} + +#if UIP_UDP +uint16_t +uip_tcpchksum(void) +{ + uint16_t sum = UIPEthernet.upper_layer_chksum(UIP_PROTO_TCP); + return sum; +} + +uint16_t +uip_udpchksum(void) +{ + uint16_t sum = UIPEthernet.upper_layer_chksum(UIP_PROTO_UDP); + return sum; +} +#endif diff --git a/LibraryPatches/UIPEthernet-2.0.9/UIPEthernet.h b/LibraryPatches/UIPEthernet-2.0.9/UIPEthernet.h index 4d3e0eb..b5feabc 100644 --- a/LibraryPatches/UIPEthernet-2.0.9/UIPEthernet.h +++ b/LibraryPatches/UIPEthernet-2.0.9/UIPEthernet.h @@ -1,166 +1,168 @@ -/* - UIPEthernet.h - Arduino implementation of a uIP wrapper class. - Copyright (c) 2013 Norbert Truchsess - All rights reserved. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -#ifndef UIPETHERNET_H -#define UIPETHERNET_H - -#include "ethernet_comp.h" -#if defined(__MBED__) - #include -#endif -#if defined(ARDUINO) - #include - #if defined(__STM32F3__) || (!defined(ARDUINO_ARCH_STM32) && defined(STM32F3)) || defined(__RFduino__) - #include "mbed/IPAddress.h" - #else - #include "IPAddress.h" - #endif -#endif -#include "utility/Enc28J60Network.h" -#include "utility/uipopt.h" -#include "Dhcp.h" -#if UIP_UDP - #include "UIPUdp.h" -#endif -#include "UIPClient.h" -#include "UIPServer.h" - -extern "C" -{ -#include "utility/uip.h" -} - -#define UIPETHERNET_FREEPACKET 1 -#define UIPETHERNET_SENDPACKET 2 -#define UIPETHERNET_BUFFERREAD 4 - -#define uip_ip_addr(addr, ip) do { \ - ((u16_t *)(addr))[0] = HTONS(((ip[0]) << 8) | (ip[1])); \ - ((u16_t *)(addr))[1] = HTONS(((ip[2]) << 8) | (ip[3])); \ - } while(0) - -#define ip_addr_uip(a) IPAddress(a[0] & 0xFF, a[0] >> 8 , a[1] & 0xFF, a[1] >> 8) //TODO this is not IPV6 capable - -#define uip_seteth_addr(eaddr) do {uip_ethaddr.addr[0] = eaddr[0]; \ - uip_ethaddr.addr[1] = eaddr[1];\ - uip_ethaddr.addr[2] = eaddr[2];\ - uip_ethaddr.addr[3] = eaddr[3];\ - uip_ethaddr.addr[4] = eaddr[4];\ - uip_ethaddr.addr[5] = eaddr[5];} while(0) - -#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) - -enum EthernetLinkStatus { - Unknown, - LinkON, - LinkOFF -}; - -enum EthernetHardwareStatus { - EthernetNoHardware, - EthernetW5100, - EthernetW5200, - EthernetW5500, - EthernetENC28J60 = 10 -}; - -class UIPEthernetClass -{ -public: - UIPEthernetClass(); - - void init(const uint8_t pin); - - int begin(const uint8_t* mac); - void begin(const uint8_t* mac, IPAddress ip); - void begin(const uint8_t* mac, IPAddress ip, IPAddress dns); - void begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway); - void begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet); - - // maintain() must be called at regular intervals to process the incoming serial - // data and issue IP events to the sketch. It does not return until all IP - // events have been processed. Renews dhcp-lease if required. - int maintain(); - - EthernetLinkStatus linkStatus(); - EthernetHardwareStatus hardwareStatus(); - - // KH add to have similar function to Ethernet lib - // Certainly we can use void macAddress(uint8_t mac[]) to read from W5x00. - void MACAddress(uint8_t *mac_address) - { - memcpy(mac_address, _mac_address, sizeof(_mac_address)); - } - ////// - - IPAddress localIP(); - IPAddress subnetMask(); - IPAddress gatewayIP(); - IPAddress dnsServerIP(); - -private: - - // KH add to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ - uint8_t _mac_address[6] ={0,}; - ////// - - static memhandle in_packet; - static memhandle uip_packet; - static uint8_t uip_hdrlen; - static uint8_t packetstate; - - static IPAddress _dnsServerAddress; - #if UIP_UDP - static DhcpClass* _dhcp; - #endif - static unsigned long periodic_timer; - - static void netInit(const uint8_t* mac); - static void configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet); - - static void tick(); - - static bool network_send(); - - friend class UIPServer; - - friend class UIPClient; - - friend class UIPUDP; - - static uint16_t chksum(uint16_t sum, const uint8_t* data, uint16_t len); - static uint16_t ipchksum(void); -#if UIP_UDP - static uint16_t upper_layer_chksum(uint8_t proto); -#endif - friend uint16_t uip_ipchksum(void); - friend uint16_t uip_tcpchksum(void); - friend uint16_t uip_udpchksum(void); - - friend void uipclient_appcall(void); - friend void uipudp_appcall(void); - -#if UIP_CONF_IPV6 - uint16_t uip_icmp6chksum(void); -#endif /* UIP_CONF_IPV6 */ -}; - -extern UIPEthernetClass UIPEthernet; - -#endif +/* + UIPEthernet.h - Arduino implementation of a uIP wrapper class. + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef UIPETHERNET_H +#define UIPETHERNET_H + +#include "ethernet_comp.h" +#if defined(__MBED__) + #include +#endif +#if defined(ARDUINO) + #include + #if defined(__STM32F3__) || (!defined(ARDUINO_ARCH_STM32) && defined(STM32F3)) || defined(__RFduino__) + #include "mbed/IPAddress.h" + #else + #include "IPAddress.h" + #endif +#endif +#include "utility/Enc28J60Network.h" +#include "utility/uipopt.h" +#include "Dhcp.h" +#if UIP_UDP + #include "UIPUdp.h" +#endif +#include "UIPClient.h" +#include "UIPServer.h" + +extern "C" +{ +#include "utility/uip.h" +} + +#define UIPETHERNET_FREEPACKET 1 +#define UIPETHERNET_SENDPACKET 2 +#define UIPETHERNET_BUFFERREAD 4 + +#define uip_ip_addr(addr, ip) do { \ + ((u16_t *)(addr))[0] = HTONS(((ip[0]) << 8) | (ip[1])); \ + ((u16_t *)(addr))[1] = HTONS(((ip[2]) << 8) | (ip[3])); \ + } while(0) + +#define ip_addr_uip(a) IPAddress(a[0] & 0xFF, a[0] >> 8 , a[1] & 0xFF, a[1] >> 8) //TODO this is not IPV6 capable + +#define uip_seteth_addr(eaddr) do {uip_ethaddr.addr[0] = eaddr[0]; \ + uip_ethaddr.addr[1] = eaddr[1];\ + uip_ethaddr.addr[2] = eaddr[2];\ + uip_ethaddr.addr[3] = eaddr[3];\ + uip_ethaddr.addr[4] = eaddr[4];\ + uip_ethaddr.addr[5] = eaddr[5];} while(0) + +#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) + +enum EthernetLinkStatus +{ + Unknown, + LinkON, + LinkOFF +}; + +enum EthernetHardwareStatus +{ + EthernetNoHardware, + EthernetW5100, + EthernetW5200, + EthernetW5500, + EthernetENC28J60 = 10 +}; + +class UIPEthernetClass +{ + public: + UIPEthernetClass(); + + void init(const uint8_t pin); + + int begin(const uint8_t* mac); + void begin(const uint8_t* mac, IPAddress ip); + void begin(const uint8_t* mac, IPAddress ip, IPAddress dns); + void begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway); + void begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet); + + // maintain() must be called at regular intervals to process the incoming serial + // data and issue IP events to the sketch. It does not return until all IP + // events have been processed. Renews dhcp-lease if required. + int maintain(); + + EthernetLinkStatus linkStatus(); + EthernetHardwareStatus hardwareStatus(); + + // KH add to have similar function to Ethernet lib + // Certainly we can use void macAddress(uint8_t mac[]) to read from W5x00. + void MACAddress(uint8_t *mac_address) + { + memcpy(mac_address, _mac_address, sizeof(_mac_address)); + } + ////// + + IPAddress localIP(); + IPAddress subnetMask(); + IPAddress gatewayIP(); + IPAddress dnsServerIP(); + + private: + + // KH add to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ + uint8_t _mac_address[6] = {0,}; + ////// + + static memhandle in_packet; + static memhandle uip_packet; + static uint8_t uip_hdrlen; + static uint8_t packetstate; + + static IPAddress _dnsServerAddress; +#if UIP_UDP + static DhcpClass* _dhcp; +#endif + static unsigned long periodic_timer; + + static void netInit(const uint8_t* mac); + static void configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet); + + static void tick(); + + static bool network_send(); + + friend class UIPServer; + + friend class UIPClient; + + friend class UIPUDP; + + static uint16_t chksum(uint16_t sum, const uint8_t* data, uint16_t len); + static uint16_t ipchksum(void); +#if UIP_UDP + static uint16_t upper_layer_chksum(uint8_t proto); +#endif + friend uint16_t uip_ipchksum(void); + friend uint16_t uip_tcpchksum(void); + friend uint16_t uip_udpchksum(void); + + friend void uipclient_appcall(void); + friend void uipudp_appcall(void); + +#if UIP_CONF_IPV6 + uint16_t uip_icmp6chksum(void); +#endif /* UIP_CONF_IPV6 */ +}; + +extern UIPEthernetClass UIPEthernet; + +#endif diff --git a/LibraryPatches/UIPEthernet-2.0.9/utility/Enc28J60Network.cpp b/LibraryPatches/UIPEthernet-2.0.9/utility/Enc28J60Network.cpp index 8c405d6..d63167d 100644 --- a/LibraryPatches/UIPEthernet-2.0.9/utility/Enc28J60Network.cpp +++ b/LibraryPatches/UIPEthernet-2.0.9/utility/Enc28J60Network.cpp @@ -1,1216 +1,1313 @@ -/* - Enc28J60NetworkClass.h - UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface. - - Copyright (c) 2013 Norbert Truchsess - All rights reserved. - - based on enc28j60.c file from the AVRlib library by Pascal Stang. - For AVRlib See http://www.procyonengineering.com/ - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -#include "Enc28J60Network.h" -#if defined(ARDUINO) - #include "Arduino.h" -#endif -#if defined(__MBED__) - #include - #include "mbed/millis.h" - #define delay(x) wait_ms(x) -#endif -#include "logging.h" - -// KH, For nRF52 -//#define ENC28J60_USE_SPILIB true - -uint8_t ENC28J60ControlCS = ENC28J60_CONTROL_CS; - -#if ENC28J60_USE_SPILIB - #if defined(ARDUINO) - #if defined(STM32F2) - #include - #elif (defined(ARDUINO_ARCH_STM32) || !defined(STM32F3)) && !defined(__STM32F4__) - #include - extern SPIClass SPI; - //#elif defined(ARDUINO_ARCH_AMEBA) - //SPIClass SPI((void *)(&spi_obj), 11, 12, 13, 10); - //SPI _spi(SPI_MOSI,SPI_MISO,SPI_SCK,ENC28J60ControlCS); - #else - #include "HardwareSPI.h" - extern HardwareSPI SPI(1); - #endif - #endif - #if defined(__MBED__) - SPI _spi(SPI_MOSI,SPI_MISO,SPI_SCK); - DigitalOut _cs(ENC28J60ControlCS); - Serial LogObject(SERIAL_TX,SERIAL_RX); - #endif -#endif - -extern "C" { - #if defined(ARDUINO_ARCH_AVR) - // AVR-specific code - #include - #elif defined(ARDUINO_ARCH_SAM) - // SAM-specific code - #elif defined(ARDUINO_ARCH_SAMD) - // SAMD-specific code - #else - // generic, non-platform specific code - #endif -#include "enc28j60.h" -#include "uip.h" -} - -#if defined(ARDUINO) - // set CS to 0 = active - #define CSACTIVE digitalWrite(ENC28J60ControlCS, LOW) - // set CS to 1 = passive - #define CSPASSIVE digitalWrite(ENC28J60ControlCS, HIGH) -#endif -#if defined(__MBED__) - // set CS to 0 = active - #define CSACTIVE _cs=0 - // set CS to 1 = passive - #define CSPASSIVE _cs=1 -#endif - -// -#if defined(ARDUINO_ARCH_AVR) -#define waitspi() while(!(SPSR&(1<=LOG_DEBUG - LogObject.uart_send_str(F("ENC28J60::init DEBUG:csPin = ")); - LogObject.uart_send_decln(ENC28J60ControlCS); - LogObject.uart_send_str(F("ENC28J60::init DEBUG:miso = ")); - LogObject.uart_send_decln(SPI_MISO); - LogObject.uart_send_str(F("ENC28J60::init DEBUG:mosi = ")); - LogObject.uart_send_decln(SPI_MOSI); - LogObject.uart_send_str(F("ENC28J60::init DEBUG:sck = ")); - LogObject.uart_send_decln(SPI_SCK); - #endif -#if ENC28J60_USE_SPILIB - #if ACTLOGLEVEL>=LOG_DEBUG - LogObject.uart_send_strln(F("ENC28J60::init DEBUG:Use SPI lib SPI.begin()")); - #endif - #if defined(ARDUINO) - #if defined(__STM32F3__) || (!defined(ARDUINO_ARCH_STM32) && defined(STM32F3)) || defined(__STM32F4__) - SPI.begin(SPI_9MHZ, MSBFIRST, 0); - #else - SPI.begin(); - #endif - #endif - #if defined(ARDUINO_ARCH_AVR) - // AVR-specific code - SPI.setClockDivider(SPI_CLOCK_DIV2); //results in 8MHZ at 16MHZ system clock. - #elif defined(ARDUINO_ARCH_SAM) - // SAM-specific code - SPI.setClockDivider(10); //defaults to 21 which results in aprox. 4MHZ. A 10 should result in a little more than 8MHZ. - #elif defined(ARDUINO_ARCH_SAMD) - // SAMD-specific code - // Should we set clock divider? - SPI.setClockDivider(10); - #elif defined(__STM32F1__) || defined(__STM32F3__) - // generic, non-platform specific code - #define USE_STM32F1_DMAC 1 //on STM32 - // BOARD_NR_SPI >= 1 BOARD_SPI1_NSS_PIN, BOARD_SPI1_SCK_PIN, BOARD_SPI1_MISO_PIN, BOARD_SPI1_MOSI_PIN - SPI.setBitOrder(MSBFIRST); - SPI.setDataMode(SPI_MODE0); - SPI.setClockDivider(SPI_CLOCK_DIV8); //value 8 the result is 9MHz at 72MHz clock. - #else - #if defined(ARDUINO) - #if !defined(__STM32F3__) && !defined(STM32F3) && !defined(__STM32F4__) - SPI.setBitOrder(MSBFIRST); - #endif - //Settings for ESP8266 - //SPI.setDataMode(SPI_MODE0); - //SPI.setClockDivider(SPI_CLOCK_DIV16); - #endif - #if defined(__MBED__) - _spi.format(8, 0); // 8bit, mode 0 - _spi.frequency(7000000); // 7MHz - #endif - #endif -#else - #if ACTLOGLEVEL>=LOG_DEBUG - LogObject.uart_send_strln(F("ENC28J60::init DEBUG:Use Native hardware SPI")); - #endif - pinMode(SPI_MOSI, OUTPUT); - pinMode(SPI_SCK, OUTPUT); - pinMode(SPI_MISO, INPUT); - //Hardware SS must be configured as OUTPUT to enable SPI-master (regardless of which pin is configured as ENC28J60ControlCS) - pinMode(SS, OUTPUT); - digitalWrite(SS,HIGH); - - digitalWrite(SPI_MOSI, LOW); - digitalWrite(SPI_SCK, LOW); - - // initialize SPI interface - // master mode and Fosc/2 clock: - SPCR = (1<=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:Before readOp(ENC28J60_READ_CTRL_REG, ESTAT)")); - #endif - nextPacketPtr = RXSTART_INIT; - while ((!readOp(ENC28J60_READ_CTRL_REG, ESTAT) & ESTAT_CLKRDY) && (timeout>0)) - { - timeout=timeout-1; - delay(10); - #if defined(ESP8266) - wdt_reset(); - #endif - } - #if ACTLOGLEVEL>=LOG_ERR - if (timeout==0) {LogObject.uart_send_strln(F("ENC28J60::init ERROR:TIMEOUT !!"));} - #endif - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:After readOp(ENC28J60_READ_CTRL_REG, ESTAT)")); - #endif - // Rx start - writeRegPair(ERXSTL, RXSTART_INIT); - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:After writeRegPair(ERXSTL, RXSTART_INIT)")); - #endif - // set receive pointer address - writeRegPair(ERXRDPTL, RXSTART_INIT); - // RX end - writeRegPair(ERXNDL, RXSTOP_INIT); - // TX start - //writeRegPair(ETXSTL, TXSTART_INIT); - // TX end - //writeRegPair(ETXNDL, TXSTOP_INIT); - // do bank 1 stuff, packet filter: - // For broadcast packets we allow only ARP packtets - // All other packets should be unicast only for our mac (MAADR) - // - // The pattern to match on is therefore - // Type ETH.DST - // ARP BROADCAST - // 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9 - // in binary these poitions are:11 0000 0011 1111 - // This is hex 303F->EPMM0=0x3f,EPMM1=0x30 - //TODO define specific pattern to receive dhcp-broadcast packages instead of setting ERFCON_BCEN! -// enableBroadcast(); // change to add ERXFCON_BCEN recommended by epam - writeReg(ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN|ERXFCON_BCEN); - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:After writeReg(ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN|ERXFCON_BCEN)")); - #endif - #if defined(ESP8266) - wdt_reset(); - #endif - writeRegPair(EPMM0, 0x303f); - writeRegPair(EPMCSL, 0xf7f9); - // - // - // do bank 2 stuff - // enable MAC receive - // and bring MAC out of reset (writes 0x00 to MACON2) - writeRegPair(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS); - // enable automatic padding to 60bytes and CRC operations - writeOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN); - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:After writeOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN)")); - #endif - // set inter-frame gap (non-back-to-back) - writeRegPair(MAIPGL, 0x0C12); - // set inter-frame gap (back-to-back) - writeReg(MABBIPG, 0x12); - // Set the maximum packet size which the controller will accept - // Do not send packets longer than MAX_FRAMELEN: - writeRegPair(MAMXFLL, MAX_FRAMELEN); - // do bank 3 stuff - // write MAC address - // NOTE: MAC address in ENC28J60 is byte-backward - writeReg(MAADR5, macaddr[0]); - writeReg(MAADR4, macaddr[1]); - writeReg(MAADR3, macaddr[2]); - writeReg(MAADR2, macaddr[3]); - writeReg(MAADR1, macaddr[4]); - writeReg(MAADR0, macaddr[5]); - // no loopback of transmitted frames - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:Before phyWrite(PHCON2, PHCON2_HDLDIS)")); - #endif - phyWrite(PHCON2, PHCON2_HDLDIS); - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:After phyWrite(PHCON2, PHCON2_HDLDIS)")); - #endif - // switch to bank 0 - setBank(ECON1); - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:After setBank(ECON1)")); - #endif - // enable interrutps - writeOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE); - // enable packet reception - writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); - //Configure leds - phyWrite(PHLCON,0x476); - - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:Before readReg(EREVID);")); - #endif - erevid=readReg(EREVID); - if (erevid==0xFF) {erevid=0;} - // microchip forgot to step the number on the silcon when they - // released the revision B7. 6 is now rev B7. We still have - // to see what they do when they release B8. At the moment - // there is no B8 out yet - //if (erevid > 5) ++erevid; - #if ACTLOGLEVEL>=LOG_INFO - LogObject.uart_send_str(F("ENC28J60::init INFO: Chip erevid=")); - LogObject.uart_send_dec(erevid); - LogObject.uart_send_strln(F(" initialization completed.")); - #endif - -// return Enc28J60Network::erevid; -} - -memhandle -Enc28J60Network::receivePacket(void) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::receivePacket(void) DEBUG_V3:Function started")); - #endif - #if defined(ESP8266) - wdt_reset(); - #endif - uint8_t rxstat; - uint16_t len; - // check if a packet has been received and buffered - //if( !(readReg(EIR) & EIR_PKTIF) ){ - // The above does not work. See Rev. B4 Silicon Errata point 6. - #if ACTLOGLEVEL>=LOG_ERR - if (erevid==0) - { - LogObject.uart_send_strln(F("Enc28J60Network::receivePacket(void) ERROR:ENC28j50 Device not found !! Bypass receivePacket function !!")); - } - #endif - uint8_t epktcnt=readReg(EPKTCNT); - if ((erevid!=0) && (epktcnt!=0)) - { - uint16_t readPtr = nextPacketPtr+6 > RXSTOP_INIT ? nextPacketPtr+6-((RXSTOP_INIT + 1)-RXSTART_INIT) : nextPacketPtr+6; - // Set the read pointer to the start of the received packet - writeRegPair(ERDPTL, nextPacketPtr); - // read the next packet pointer - nextPacketPtr = readOp(ENC28J60_READ_BUF_MEM, 0); - nextPacketPtr |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; - // read the packet length (see datasheet page 43) - len = readOp(ENC28J60_READ_BUF_MEM, 0); - len |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; - len -= 4; //remove the CRC count - // read the receive status (see datasheet page 43) - rxstat = readOp(ENC28J60_READ_BUF_MEM, 0); - //rxstat |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; - #if ACTLOGLEVEL>=LOG_DEBUG - LogObject.uart_send_str(F("Enc28J60Network::receivePacket(void) DEBUG:receivePacket [")); - LogObject.uart_send_hex(readPtr); - LogObject.uart_send_str(F("-")); - LogObject.uart_send_hex((readPtr+len) % (RXSTOP_INIT+1)); - LogObject.uart_send_str(F("], next: ")); - LogObject.uart_send_hex(nextPacketPtr); - LogObject.uart_send_str(F(", stat: ")); - LogObject.uart_send_hex(rxstat); - LogObject.uart_send_str(F(", Packet count: ")); - LogObject.uart_send_dec(epktcnt); - LogObject.uart_send_str(F(" -> ")); - LogObject.uart_send_strln((rxstat & 0x80)!=0 ? "OK" : "failed"); - #endif - // decrement the packet counter indicate we are done with this packet - writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC); - // check CRC and symbol errors (see datasheet page 44, table 7-3): - // The ERXFCON.CRCEN is set by default. Normally we should not - // need to check this. - if (((rxstat & 0x80) != 0) && (nextPacketPtr<=RXSTOP_INIT)) - { - receivePkt.begin = readPtr; - receivePkt.size = len; - #if ACTLOGLEVEL>=LOG_DEBUG - LogObject.uart_send_str(F("Enc28J60Network::receivePacket(void) DEBUG: rxstat OK. receivePkt.size=")); - LogObject.uart_send_decln(len); - #endif - return UIP_RECEIVEBUFFERHANDLE; - } - // Move the RX read pointer to the start of the next received packet - // This frees the memory we just read out - setERXRDPT(); - } - return (NOBLOCK); -} - -void -Enc28J60Network::setERXRDPT(void) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::setERXRDPT(void) DEBUG_V3:Function started")); - #endif - // Make sure the value is odd. See Rev. B1,B4,B5,B7 Silicon Errata issues 14 - uint16_t actnextPacketPtr = nextPacketPtr == RXSTART_INIT ? RXSTOP_INIT : nextPacketPtr-1; - #if ACTLOGLEVEL>=LOG_DEBUG - LogObject.uart_send_str(F("Enc28J60Network::setERXRDPT(void) DEBUG:Set actnextPacketPtr:")); - LogObject.uart_send_hexln(actnextPacketPtr); - #endif - // datasheet: The ENC28J60 will always write up to, but not including - writeRegPair(ERXRDPTL, actnextPacketPtr); -} - -memaddress -Enc28J60Network::blockSize(memhandle handle) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::blockSize(memhandle handle) DEBUG_V3:Function started")); - #endif - return ((handle == NOBLOCK) || (erevid==0)) ? 0 : handle == UIP_RECEIVEBUFFERHANDLE ? receivePkt.size : blocks[handle].size; -} - -bool -Enc28J60Network::sendPacket(memhandle handle) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::sendPacket(memhandle handle) INFO:Function started")); - #endif - #if defined(ESP8266) - wdt_reset(); - #endif - if (erevid==0) - { - #if ACTLOGLEVEL>=LOG_ERR - LogObject.uart_send_strln(F("Enc28J60Network::sendPacket(memhandle handle) ERROR:ENC28j50 Device not found !! Bypass sendPacket function !!")); - #endif - return false; - } - - memblock *packet = &blocks[handle]; - uint16_t start = packet->begin; // includes the UIP_SENDBUFFER_OFFSET for control byte - uint16_t end = start + packet->size - 1 - UIP_SENDBUFFER_PADDING; // end = start + size - 1 and padding for TSV is no included - - // write control-byte (if not 0 anyway) - writeByte(start, 0); - - #if ACTLOGLEVEL>=LOG_DEBUG - LogObject.uart_send_str(F("Enc28J60Network::sendPacket(memhandle handle) DEBUG:sendPacket(")); - LogObject.uart_send_dec(handle); - LogObject.uart_send_str(F(") [")); - LogObject.uart_send_hex(start); - LogObject.uart_send_str(F("-")); - LogObject.uart_send_hex(end); - LogObject.uart_send_str(F("]: ")); - for (uint16_t i=start; i<=end; i++) - { - LogObject.uart_send_hex(readByte(i)); - LogObject.uart_send_str(F(" ")); - } - LogObject.uart_send_strln(F("")); - #endif - - // TX start - writeRegPair(ETXSTL, start); - // Set the TXND pointer to correspond to the packet size given - writeRegPair(ETXNDL, end); - - bool success = false; - // See Rev. B7 Silicon Errata issues 12 and 13 - for (uint8_t retry = 0; retry < TX_COLLISION_RETRY_COUNT; retry++) - { - // Reset the transmit logic problem. Errata 12 - writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRST); - writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRST); - writeOp(ENC28J60_BIT_FIELD_CLR, EIR, EIR_TXERIF | EIR_TXIF); - - // send the contents of the transmit buffer onto the network - writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS); - - uint8_t eir; - // wait for transmission to complete or fail - while (((eir = readReg(EIR)) & (EIR_TXIF | EIR_TXERIF)) == 0); - writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS); - success = ((eir & EIR_TXERIF) == 0); - if (success) - break; // usual exit of the for(retry) loop - - // Errata 13 detection - uint8_t tsv4 = readByte(end + 4); - if (!(tsv4 & 0b00100000)) // is it "late collision" indicated in bit 29 of TSV? - break; // other fail, not the Errata 13 situation - #if ACTLOGLEVEL>=LOG_ERROR - LogObject.uart_send_strln(F("Enc28J60Network::sendPacket(memhandle handle) Errata 13 LATE COLLISION !!")); - #endif - } - - return success; -} - -uint16_t -Enc28J60Network::setReadPtr(memhandle handle, memaddress position, uint16_t len) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::setReadPtr(memhandle handle, memaddress position, uint16_t len) DEBUG_V3:Function started")); - #endif - memblock *packet = handle == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[handle]; - memaddress start = handle == UIP_RECEIVEBUFFERHANDLE && packet->begin + position > RXSTOP_INIT ? packet->begin + position-((RXSTOP_INIT + 1)-RXSTART_INIT) : packet->begin + position; - - writeRegPair(ERDPTL, start); - - if (len > packet->size - position) - len = packet->size - position; - return len; -} - -uint16_t -Enc28J60Network::readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) DEBUG_V3:Function started")); - #endif - #if defined(ESP8266) - wdt_reset(); - #endif - len = setReadPtr(handle, position, len); - readBuffer(len, buffer); - #if ACTLOGLEVEL>=LOG_DEBUG_V2 - LogObject.uart_send_str(F("Enc28J60Network::readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) DEBUG_V2: Read bytes:")); - LogObject.uart_send_dec(len); - LogObject.uart_send_str(F(" save to block(")); - LogObject.uart_send_dec(handle); - LogObject.uart_send_str(F(") [")); - LogObject.uart_send_hex(position); - LogObject.uart_send_str(F("]: ")); - for (uint16_t i=0; i=LOG_DEBUG_V3 - LogObject.uart_send_str(F("Enc28J60Network::writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) DEBUG_V3:Function started with len:")); - LogObject.uart_send_decln(len); - #endif - #if defined(ESP8266) - wdt_reset(); - #endif - memblock *packet = &blocks[handle]; - uint16_t start = packet->begin + position; - - writeRegPair(EWRPTL, start); - - if (len > packet->size - position) - len = packet->size - position; - writeBuffer(len, buffer); - #if ACTLOGLEVEL>=LOG_DEBUG_V2 - LogObject.uart_send_str(F("Enc28J60Network::writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) DEBUG_V2: Write bytes:")); - LogObject.uart_send_dec(len); - LogObject.uart_send_str(F(" save to block(")); - LogObject.uart_send_dec(handle); - LogObject.uart_send_str(F(") [")); - LogObject.uart_send_hex(start); - LogObject.uart_send_str(F("]: ")); - for (uint16_t i=0; i=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::enableBroadcast (bool temporary) DEBUG_V3:Function started")); - #endif - writeRegByte(ERXFCON, readRegByte(ERXFCON) | ERXFCON_BCEN); - if(!temporary) - broadcast_enabled = true; -} - -void Enc28J60Network::disableBroadcast (bool temporary) { - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::disableBroadcast (bool temporary) DEBUG_V3:Function started")); - #endif - if(!temporary) - broadcast_enabled = false; - if(!broadcast_enabled) - writeRegByte(ERXFCON, readRegByte(ERXFCON) & ~ERXFCON_BCEN); -} - -void Enc28J60Network::enableMulticast (void) { - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::enableMulticast (void) DEBUG_V3:Function started")); - #endif - writeRegByte(ERXFCON, readRegByte(ERXFCON) | ERXFCON_MCEN); -} - -void Enc28J60Network::disableMulticast (void) { - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::disableMulticast (void) DEBUG_V3:Function started")); - #endif - writeRegByte(ERXFCON, readRegByte(ERXFCON) & ~ERXFCON_MCEN); -} - -uint8_t Enc28J60Network::readRegByte (uint8_t address) { - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::readRegByte (uint8_t address) DEBUG_V3:Function started")); - #endif - setBank(address); - return readOp(ENC28J60_READ_CTRL_REG, address); -} - -void Enc28J60Network::writeRegByte (uint8_t address, uint8_t data) { - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::writeRegByte (uint8_t address, uint8_t data) DEBUG_V3:Function started")); - #endif - setBank(address); - writeOp(ENC28J60_WRITE_CTRL_REG, address, data); -} - - -uint8_t Enc28J60Network::readByte(uint16_t addr) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::readByte(uint16_t addr) DEBUG_V3:Function started")); - #endif - #if defined(ESP8266) - wdt_reset(); - #endif - writeRegPair(ERDPTL, addr); - - CSACTIVE; - #if ENC28J60_USE_SPILIB - // issue read command - #if defined(ARDUINO) - SPI.transfer(ENC28J60_READ_BUF_MEM); - // read data - uint8_t c = SPI.transfer(0x00); - #endif - #if defined(__MBED__) - _spi.write(ENC28J60_READ_BUF_MEM); - // read data - uint8_t c = _spi.write(0x00); - #endif - CSPASSIVE; - return (c); - #else - // issue read command - SPDR = ENC28J60_READ_BUF_MEM; - waitspi(); - // read data - SPDR = 0x00; - waitspi(); - CSPASSIVE; - return (SPDR); - #endif -} - -void Enc28J60Network::writeByte(uint16_t addr, uint8_t data) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::writeByte(uint16_t addr, uint8_t data) DEBUG_V3:Function started")); - #endif - #if defined(ESP8266) - wdt_reset(); - #endif - writeRegPair(EWRPTL, addr); - - CSACTIVE; - #if ENC28J60_USE_SPILIB - // issue write command - #if defined(ARDUINO) - SPI.transfer(ENC28J60_WRITE_BUF_MEM); - // write data - SPI.transfer(data); - #endif - #if defined(__MBED__) - _spi.write(ENC28J60_WRITE_BUF_MEM); - // write data - _spi.write(data); - #endif - #else - // issue write command - SPDR = ENC28J60_WRITE_BUF_MEM; - waitspi(); - // write data - SPDR = data; - waitspi(); - #endif - CSPASSIVE; -} - -void -Enc28J60Network::copyPacket(memhandle dest_pkt, memaddress dest_pos, memhandle src_pkt, memaddress src_pos, uint16_t len) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::copyPacket(memhandle dest_pkt, memaddress dest_pos, memhandle src_pkt, memaddress src_pos, uint16_t len) DEBUG_V3:Function started")); - #endif - memblock *dest = &blocks[dest_pkt]; - memblock *src = src_pkt == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[src_pkt]; - memaddress start = src_pkt == UIP_RECEIVEBUFFERHANDLE && src->begin + src_pos > RXSTOP_INIT ? src->begin + src_pos-((RXSTOP_INIT + 1)-RXSTART_INIT) : src->begin + src_pos; - enc28J60_mempool_block_move_callback(dest->begin+dest_pos,start,len); - // setERXRDPT(); let it to freePacket after all packets are saved -} - -void -enc28J60_mempool_block_move_callback(memaddress dest, memaddress src, memaddress len) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("enc28J60_mempool_block_move_callback(memaddress dest, memaddress src, memaddress len) DEBUG_V3:Function started")); - #endif -//void -//Enc28J60Network::memblock_mv_cb(uint16_t dest, uint16_t src, uint16_t len) -//{ - //as ENC28J60 DMA is unable to copy single bytes: - if (len == 1) - { - Enc28J60Network::writeByte(dest,Enc28J60Network::readByte(src)); - } - else - { - // calculate address of last byte - len += src - 1; - - /* 1. Appropriately program the EDMAST, EDMAND - and EDMADST register pairs. The EDMAST - registers should point to the first byte to copy - from, the EDMAND registers should point to the - last byte to copy and the EDMADST registers - should point to the first byte in the destination - range. The destination range will always be - linear, never wrapping at any values except from - 8191 to 0 (the 8-Kbyte memory boundary). - Extreme care should be taken when - programming the start and end pointers to - prevent a never ending DMA operation which - would overwrite the entire 8-Kbyte buffer. - */ - Enc28J60Network::writeRegPair(EDMASTL, src); - Enc28J60Network::writeRegPair(EDMADSTL, dest); - - if ((src <= RXSTOP_INIT)&& (len > RXSTOP_INIT))len -= ((RXSTOP_INIT + 1)-RXSTART_INIT); - Enc28J60Network::writeRegPair(EDMANDL, len); - - /* - 2. If an interrupt at the end of the copy process is - desired, set EIE.DMAIE and EIE.INTIE and - clear EIR.DMAIF. - - 3. Verify that ECON1.CSUMEN is clear. */ - Enc28J60Network::writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_CSUMEN); - - /* 4. Start the DMA copy by setting ECON1.DMAST. */ - Enc28J60Network::writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_DMAST); - - // wait until runnig DMA is completed - while (Enc28J60Network::readOp(ENC28J60_READ_CTRL_REG, ECON1) & ECON1_DMAST) - { - delay(1); - } - } -} - -void -Enc28J60Network::freePacket(void) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::freePacket(void) DEBUG_V3:Function started")); - #endif - setERXRDPT(); -} - -uint8_t -Enc28J60Network::readOp(uint8_t op, uint8_t address) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::readOp(uint8_t op, uint8_t address) DEBUG_V3:Function started")); - #endif - CSACTIVE; - // issue read command - #if ENC28J60_USE_SPILIB - #if defined(ARDUINO) - SPI.transfer(op | (address & ADDR_MASK)); - // read data - if(address & 0x80) - { - // do dummy read if needed (for mac and mii, see datasheet page 29) - SPI.transfer(0x00); - } - uint8_t c = SPI.transfer(0x00); - #endif - #if defined(__MBED__) - _spi.write(op | (address & ADDR_MASK)); - // read data - if(address & 0x80) - { - // do dummy read if needed (for mac and mii, see datasheet page 29) - _spi.write(0x00); - } - uint8_t c = _spi.write(0x00); - #endif - // release CS - CSPASSIVE; - return(c); - #else - // issue read command - SPDR = op | (address & ADDR_MASK); - waitspi(); - // read data - SPDR = 0x00; - waitspi(); - // do dummy read if needed (for mac and mii, see datasheet page 29) - if(address & 0x80) - { - SPDR = 0x00; - waitspi(); - } - // release CS - CSPASSIVE; - return(SPDR); - #endif - #if defined(ESP8266) - yield(); - #endif -} - -void -Enc28J60Network::writeOp(uint8_t op, uint8_t address, uint8_t data) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::writeOp(uint8_t op, uint8_t address, uint8_t data) DEBUG_V3:Function started")); - #endif - CSACTIVE; - // issue write command - #if ENC28J60_USE_SPILIB - #if defined(ARDUINO) - SPI.transfer(op | (address & ADDR_MASK)); - // write data - SPI.transfer(data); - #endif - #if defined(__MBED__) - _spi.write(op | (address & ADDR_MASK)); - // write data - _spi.write(data); - #endif - #else - // issue write command - SPDR = op | (address & ADDR_MASK); - waitspi(); - // write data - SPDR = data; - waitspi(); - #endif - CSPASSIVE; - #if defined(ESP8266) - yield(); - #endif -} - -void -Enc28J60Network::readBuffer(uint16_t len, uint8_t* data) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::readBuffer(uint16_t len, uint8_t* data) DEBUG_V3:Function started")); - #endif - CSACTIVE; - // issue read command - #if ENC28J60_USE_SPILIB - #if defined(ARDUINO) - SPI.transfer(ENC28J60_READ_BUF_MEM); - #endif - #if defined(__MBED__) - _spi.write(ENC28J60_READ_BUF_MEM); - #endif - #else - SPDR = ENC28J60_READ_BUF_MEM; - waitspi(); - #endif - while(len) - { - len--; - // read data - #if ENC28J60_USE_SPILIB - #if defined(ARDUINO) - *data = SPI.transfer(0x00); - #endif - #if defined(__MBED__) - *data = _spi.write(0x00); - #endif - #else - SPDR = 0x00; - waitspi(); - *data = SPDR; - #endif - data++; - } - //*data='\0'; - CSPASSIVE; -} - -void -Enc28J60Network::writeBuffer(uint16_t len, uint8_t* data) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::writeBuffer(uint16_t len, uint8_t* data) DEBUG_V3:Function started")); - #endif - CSACTIVE; - // issue write command - #if ENC28J60_USE_SPILIB - #if defined(ARDUINO) - SPI.transfer(ENC28J60_WRITE_BUF_MEM); - #endif - #if defined(__MBED__) - _spi.write(ENC28J60_WRITE_BUF_MEM); - #endif - #else - SPDR = ENC28J60_WRITE_BUF_MEM; - waitspi(); - #endif - while(len) - { - len--; - // write data - #if ENC28J60_USE_SPILIB - #if defined(ARDUINO) - SPI.transfer(*data); - #endif - #if defined(__MBED__) - _spi.write(*data); - #endif - data++; - #else - SPDR = *data; - data++; - waitspi(); - #endif - } - CSPASSIVE; -} - -void -Enc28J60Network::setBank(uint8_t address) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::setBank(uint8_t address) DEBUG_V3:Function started")); - #endif - // set the bank (if needed) - if((address & BANK_MASK) != bank) - { - // set the bank - writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1|ECON1_BSEL0)); - writeOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK)>>5); - bank = (address & BANK_MASK); - } -} - -uint8_t -Enc28J60Network::readReg(uint8_t address) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::readReg(uint8_t address) DEBUG_V3:Function started")); - #endif - // set the bank - setBank(address); - // do the read - return readOp(ENC28J60_READ_CTRL_REG, address); -} - -void -Enc28J60Network::writeReg(uint8_t address, uint8_t data) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::writeReg(uint8_t address, uint8_t data) DEBUG_V3:Function started")); - #endif - // set the bank - setBank(address); - // do the write - writeOp(ENC28J60_WRITE_CTRL_REG, address, data); -} - -void -Enc28J60Network::writeRegPair(uint8_t address, uint16_t data) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::writeRegPair(uint8_t address, uint16_t data) DEBUG_V3:Function started")); - #endif - // set the bank - setBank(address); - // do the write - writeOp(ENC28J60_WRITE_CTRL_REG, address, (data&0xFF)); - writeOp(ENC28J60_WRITE_CTRL_REG, address+1, (data) >> 8); -} - -void -Enc28J60Network::phyWrite(uint8_t address, uint16_t data) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::phyWrite(uint8_t address, uint16_t data) DEBUG_V3:Function started")); - #endif - unsigned int timeout = 15; - // set the PHY register address - writeReg(MIREGADR, address); - // write the PHY data - writeRegPair(MIWRL, data); - // wait until the PHY write completes - while (readReg(MISTAT) & MISTAT_BUSY) - { - delay(10); - #if defined(ESP8266) - wdt_reset(); - #endif - if (--timeout == 0) - { - #if ACTLOGLEVEL>=LOG_ERR - LogObject.uart_send_strln(F("Enc28J60Network::phyWrite ERROR:TIMEOUT !!")); - #endif - return; - } - } -} - -uint16_t -Enc28J60Network::phyRead(uint8_t address) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::phyRead(uint8_t address) DEBUG_V3:Function started")); - #endif - unsigned int timeout = 15; - writeReg(MIREGADR,address); - writeReg(MICMD, MICMD_MIIRD); - // wait until the PHY read completes - while(readReg(MISTAT) & MISTAT_BUSY) - { - delay(10); - #if defined(ESP8266) - wdt_reset(); - #endif - if (--timeout == 0) - { - #if ACTLOGLEVEL>=LOG_ERR - LogObject.uart_send_strln(F("Enc28J60Network::phyRead ERROR:TIMEOUT !!")); - #endif - return 0; - } - } - writeReg(MICMD, 0); - return (readReg(MIRDL) | readReg(MIRDH) << 8); -} - -void -Enc28J60Network::clkout(uint8_t clk) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::clkout(uint8_t clk) DEBUG_V3:Function started")); - #endif - //setup clkout: 2 is 12.5MHz: - writeReg(ECOCON, clk & 0x7); -} - -uint16_t -Enc28J60Network::chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len) DEBUG_V3:Function started")); - #endif - uint16_t t; - len = setReadPtr(handle, pos, len)-1; - CSACTIVE; - // issue read command - #if ENC28J60_USE_SPILIB - #if defined(ARDUINO) - SPI.transfer(ENC28J60_READ_BUF_MEM); - #endif - #if defined(__MBED__) - _spi.write(ENC28J60_READ_BUF_MEM); - #endif - #else - SPDR = ENC28J60_READ_BUF_MEM; - waitspi(); - #endif - uint16_t i; - for (i = 0; i < len; i+=2) - { - // read data - #if ENC28J60_USE_SPILIB - #if defined(ARDUINO) - t = SPI.transfer(0x00) << 8; - t += SPI.transfer(0x00); - #endif - #if defined(__MBED__) - t = _spi.write(0x00) << 8; - t += _spi.write(0x00); - #endif - #else - SPDR = 0x00; - waitspi(); - t = SPDR << 8; - SPDR = 0x00; - waitspi(); - t += SPDR; - #endif - sum += t; - if(sum < t) - { - sum++; /* carry */ - } - } - if(i == len) - { - #if ENC28J60_USE_SPILIB - #if defined(ARDUINO) - t = (SPI.transfer(0x00) << 8) + 0; - #endif - #if defined(__MBED__) - t = (_spi.write(0x00) << 8) + 0; - #endif - #else - SPDR = 0x00; - waitspi(); - t = (SPDR << 8) + 0; - #endif - sum += t; - if(sum < t) - { - sum++; /* carry */ - } - } - CSPASSIVE; - - /* Return sum in host byte order. */ - return sum; -} - -void -Enc28J60Network::powerOff(void) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::powerOff(void) DEBUG_V3:Function started")); - #endif - writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_RXEN); - delay(50); - writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_VRPS); - delay(50); - writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PWRSV); -} - -void -Enc28J60Network::powerOn(void) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::powerOn(void) DEBUG_V3:Function started")); - #endif - writeOp(ENC28J60_BIT_FIELD_CLR, ECON2, ECON2_PWRSV); - delay(50); - writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); - delay(50); -} - -// read erevid from object: -uint8_t -Enc28J60Network::geterevid(void) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_str(F("Enc28J60Network::geterevid(void) DEBUG_V3:Function started and return:")); - LogObject.uart_send_decln(erevid); - #endif - return(erevid); -} - -// read the phstat2 of the chip: -uint16_t -Enc28J60Network::PhyStatus(void) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_str(F("Enc28J60Network::PhyStatus(void) DEBUG_V3:Function started")); - LogObject.uart_send_decln(erevid); - #endif - uint16_t phstat2; - phstat2=phyRead(PHSTAT2); - if ((phstat2 & 0x20) > 0) {phstat2=phstat2 &0x100;} - phstat2=(phstat2 & 0xFF00) | erevid; - if ((phstat2 & 0x8000) > 0) {phstat2=0;} - return phstat2; -} - -bool -Enc28J60Network::linkStatus(void) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::linkStatus(void) DEBUG_V3:Function started")); - #endif - return (phyRead(PHSTAT2) & 0x0400) > 0; -} +/* + Enc28J60NetworkClass.h + UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface. + + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + based on enc28j60.c file from the AVRlib library by Pascal Stang. + For AVRlib See http://www.procyonengineering.com/ + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "Enc28J60Network.h" +#if defined(ARDUINO) + #include "Arduino.h" +#endif +#if defined(__MBED__) + #include + #include "mbed/millis.h" + #define delay(x) wait_ms(x) +#endif +#include "logging.h" + +// KH, For nRF52 +//#define ENC28J60_USE_SPILIB true + +uint8_t ENC28J60ControlCS = ENC28J60_CONTROL_CS; + +#if ENC28J60_USE_SPILIB + #if defined(ARDUINO) + #if defined(STM32F2) + #include + #elif (defined(ARDUINO_ARCH_STM32) || !defined(STM32F3)) && !defined(__STM32F4__) + #include + extern SPIClass SPI; + //#elif defined(ARDUINO_ARCH_AMEBA) + //SPIClass SPI((void *)(&spi_obj), 11, 12, 13, 10); + //SPI _spi(SPI_MOSI,SPI_MISO,SPI_SCK,ENC28J60ControlCS); + #else + #include "HardwareSPI.h" + extern HardwareSPI SPI(1); + #endif + #endif + #if defined(__MBED__) + SPI _spi(SPI_MOSI, SPI_MISO, SPI_SCK); + DigitalOut _cs(ENC28J60ControlCS); + Serial LogObject(SERIAL_TX, SERIAL_RX); + #endif +#endif + +extern "C" { +#if defined(ARDUINO_ARCH_AVR) + // AVR-specific code +#include +#elif defined(ARDUINO_ARCH_SAM) + // SAM-specific code +#elif defined(ARDUINO_ARCH_SAMD) + // SAMD-specific code +#else + // generic, non-platform specific code +#endif +#include "enc28j60.h" +#include "uip.h" +} + +#if defined(ARDUINO) + // set CS to 0 = active + #define CSACTIVE digitalWrite(ENC28J60ControlCS, LOW) + // set CS to 1 = passive + #define CSPASSIVE digitalWrite(ENC28J60ControlCS, HIGH) +#endif +#if defined(__MBED__) + // set CS to 0 = active + #define CSACTIVE _cs=0 + // set CS to 1 = passive + #define CSPASSIVE _cs=1 +#endif + +// +#if defined(ARDUINO_ARCH_AVR) + #define waitspi() while(!(SPSR&(1<=LOG_DEBUG + LogObject.uart_send_str(F("ENC28J60::init DEBUG:csPin = ")); + LogObject.uart_send_decln(ENC28J60ControlCS); + LogObject.uart_send_str(F("ENC28J60::init DEBUG:miso = ")); + LogObject.uart_send_decln(SPI_MISO); + LogObject.uart_send_str(F("ENC28J60::init DEBUG:mosi = ")); + LogObject.uart_send_decln(SPI_MOSI); + LogObject.uart_send_str(F("ENC28J60::init DEBUG:sck = ")); + LogObject.uart_send_decln(SPI_SCK); +#endif +#if ENC28J60_USE_SPILIB +#if ACTLOGLEVEL>=LOG_DEBUG + LogObject.uart_send_strln(F("ENC28J60::init DEBUG:Use SPI lib SPI.begin()")); +#endif +#if defined(ARDUINO) +#if defined(__STM32F3__) || (!defined(ARDUINO_ARCH_STM32) && defined(STM32F3)) || defined(__STM32F4__) + SPI.begin(SPI_9MHZ, MSBFIRST, 0); +#else + SPI.begin(); +#endif +#endif +#if defined(ARDUINO_ARCH_AVR) + // AVR-specific code + SPI.setClockDivider(SPI_CLOCK_DIV2); //results in 8MHZ at 16MHZ system clock. +#elif defined(ARDUINO_ARCH_SAM) + // SAM-specific code + SPI.setClockDivider(10); //defaults to 21 which results in aprox. 4MHZ. A 10 should result in a little more than 8MHZ. +#elif defined(ARDUINO_ARCH_SAMD) + // SAMD-specific code + // Should we set clock divider? + SPI.setClockDivider(10); +#elif defined(__STM32F1__) || defined(__STM32F3__) + // generic, non-platform specific code +#define USE_STM32F1_DMAC 1 //on STM32 + // BOARD_NR_SPI >= 1 BOARD_SPI1_NSS_PIN, BOARD_SPI1_SCK_PIN, BOARD_SPI1_MISO_PIN, BOARD_SPI1_MOSI_PIN + SPI.setBitOrder(MSBFIRST); + SPI.setDataMode(SPI_MODE0); + SPI.setClockDivider(SPI_CLOCK_DIV8); //value 8 the result is 9MHz at 72MHz clock. +#else +#if defined(ARDUINO) +#if !defined(__STM32F3__) && !defined(STM32F3) && !defined(__STM32F4__) + SPI.setBitOrder(MSBFIRST); +#endif + //Settings for ESP8266 + //SPI.setDataMode(SPI_MODE0); + //SPI.setClockDivider(SPI_CLOCK_DIV16); +#endif +#if defined(__MBED__) + _spi.format(8, 0); // 8bit, mode 0 + _spi.frequency(7000000); // 7MHz +#endif +#endif +#else +#if ACTLOGLEVEL>=LOG_DEBUG + LogObject.uart_send_strln(F("ENC28J60::init DEBUG:Use Native hardware SPI")); +#endif + pinMode(SPI_MOSI, OUTPUT); + pinMode(SPI_SCK, OUTPUT); + pinMode(SPI_MISO, INPUT); + //Hardware SS must be configured as OUTPUT to enable SPI-master (regardless of which pin is configured as ENC28J60ControlCS) + pinMode(SS, OUTPUT); + digitalWrite(SS, HIGH); + + digitalWrite(SPI_MOSI, LOW); + digitalWrite(SPI_SCK, LOW); + + // initialize SPI interface + // master mode and Fosc/2 clock: + SPCR = (1 << SPE) | (1 << MSTR); + SPSR |= (1 << SPI2X); +#endif + + // perform system reset + writeOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET); + delay(2); // errata B7/2 + delay(50); + // check CLKRDY bit to see if reset is complete + // The CLKRDY does not work. See Rev. B4 Silicon Errata point. Just wait. + //while(!(readReg(ESTAT) & ESTAT_CLKRDY)); + // do bank 0 stuff + // initialize receive buffer + // 16-bit transfers, must write low byte first + // set receive buffer start address +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:Before readOp(ENC28J60_READ_CTRL_REG, ESTAT)")); +#endif + nextPacketPtr = RXSTART_INIT; + + while ((!readOp(ENC28J60_READ_CTRL_REG, ESTAT) & ESTAT_CLKRDY) && (timeout > 0)) + { + timeout = timeout - 1; + delay(10); +#if defined(ESP8266) + wdt_reset(); +#endif + } + +#if ACTLOGLEVEL>=LOG_ERR + + if (timeout == 0) + { + LogObject.uart_send_strln(F("ENC28J60::init ERROR:TIMEOUT !!")); + } + +#endif +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:After readOp(ENC28J60_READ_CTRL_REG, ESTAT)")); +#endif + // Rx start + writeRegPair(ERXSTL, RXSTART_INIT); +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:After writeRegPair(ERXSTL, RXSTART_INIT)")); +#endif + // set receive pointer address + writeRegPair(ERXRDPTL, RXSTART_INIT); + // RX end + writeRegPair(ERXNDL, RXSTOP_INIT); + // TX start + //writeRegPair(ETXSTL, TXSTART_INIT); + // TX end + //writeRegPair(ETXNDL, TXSTOP_INIT); + // do bank 1 stuff, packet filter: + // For broadcast packets we allow only ARP packtets + // All other packets should be unicast only for our mac (MAADR) + // + // The pattern to match on is therefore + // Type ETH.DST + // ARP BROADCAST + // 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9 + // in binary these poitions are:11 0000 0011 1111 + // This is hex 303F->EPMM0=0x3f,EPMM1=0x30 + //TODO define specific pattern to receive dhcp-broadcast packages instead of setting ERFCON_BCEN! + // enableBroadcast(); // change to add ERXFCON_BCEN recommended by epam + writeReg(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_PMEN | ERXFCON_BCEN); +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln( + F("ENC28J60::init DEBUG_V3:After writeReg(ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN|ERXFCON_BCEN)")); +#endif +#if defined(ESP8266) + wdt_reset(); +#endif + writeRegPair(EPMM0, 0x303f); + writeRegPair(EPMCSL, 0xf7f9); + // + // + // do bank 2 stuff + // enable MAC receive + // and bring MAC out of reset (writes 0x00 to MACON2) + writeRegPair(MACON1, MACON1_MARXEN | MACON1_TXPAUS | MACON1_RXPAUS); + // enable automatic padding to 60bytes and CRC operations + writeOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN); +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln( + F("ENC28J60::init DEBUG_V3:After writeOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN)")); +#endif + // set inter-frame gap (non-back-to-back) + writeRegPair(MAIPGL, 0x0C12); + // set inter-frame gap (back-to-back) + writeReg(MABBIPG, 0x12); + // Set the maximum packet size which the controller will accept + // Do not send packets longer than MAX_FRAMELEN: + writeRegPair(MAMXFLL, MAX_FRAMELEN); + // do bank 3 stuff + // write MAC address + // NOTE: MAC address in ENC28J60 is byte-backward + writeReg(MAADR5, macaddr[0]); + writeReg(MAADR4, macaddr[1]); + writeReg(MAADR3, macaddr[2]); + writeReg(MAADR2, macaddr[3]); + writeReg(MAADR1, macaddr[4]); + writeReg(MAADR0, macaddr[5]); + // no loopback of transmitted frames +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:Before phyWrite(PHCON2, PHCON2_HDLDIS)")); +#endif + phyWrite(PHCON2, PHCON2_HDLDIS); +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:After phyWrite(PHCON2, PHCON2_HDLDIS)")); +#endif + // switch to bank 0 + setBank(ECON1); +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:After setBank(ECON1)")); +#endif + // enable interrutps + writeOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE | EIE_PKTIE); + // enable packet reception + writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); + //Configure leds + phyWrite(PHLCON, 0x476); + +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:Before readReg(EREVID);")); +#endif + erevid = readReg(EREVID); + + if (erevid == 0xFF) + { + erevid = 0; + } + + // microchip forgot to step the number on the silcon when they + // released the revision B7. 6 is now rev B7. We still have + // to see what they do when they release B8. At the moment + // there is no B8 out yet + //if (erevid > 5) ++erevid; +#if ACTLOGLEVEL>=LOG_INFO + LogObject.uart_send_str(F("ENC28J60::init INFO: Chip erevid=")); + LogObject.uart_send_dec(erevid); + LogObject.uart_send_strln(F(" initialization completed.")); +#endif + + // return Enc28J60Network::erevid; +} + +memhandle +Enc28J60Network::receivePacket(void) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::receivePacket(void) DEBUG_V3:Function started")); +#endif +#if defined(ESP8266) + wdt_reset(); +#endif + uint8_t rxstat; + uint16_t len; + // check if a packet has been received and buffered + //if( !(readReg(EIR) & EIR_PKTIF) ){ + // The above does not work. See Rev. B4 Silicon Errata point 6. +#if ACTLOGLEVEL>=LOG_ERR + + if (erevid == 0) + { + LogObject.uart_send_strln( + F("Enc28J60Network::receivePacket(void) ERROR:ENC28j50 Device not found !! Bypass receivePacket function !!")); + } + +#endif + uint8_t epktcnt = readReg(EPKTCNT); + + if ((erevid != 0) && (epktcnt != 0)) + { + uint16_t readPtr = nextPacketPtr + 6 > RXSTOP_INIT ? nextPacketPtr + 6 - ((RXSTOP_INIT + 1) - RXSTART_INIT) : + nextPacketPtr + 6; + // Set the read pointer to the start of the received packet + writeRegPair(ERDPTL, nextPacketPtr); + // read the next packet pointer + nextPacketPtr = readOp(ENC28J60_READ_BUF_MEM, 0); + nextPacketPtr |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; + // read the packet length (see datasheet page 43) + len = readOp(ENC28J60_READ_BUF_MEM, 0); + len |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; + len -= 4; //remove the CRC count + // read the receive status (see datasheet page 43) + rxstat = readOp(ENC28J60_READ_BUF_MEM, 0); + //rxstat |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; +#if ACTLOGLEVEL>=LOG_DEBUG + LogObject.uart_send_str(F("Enc28J60Network::receivePacket(void) DEBUG:receivePacket [")); + LogObject.uart_send_hex(readPtr); + LogObject.uart_send_str(F("-")); + LogObject.uart_send_hex((readPtr + len) % (RXSTOP_INIT + 1)); + LogObject.uart_send_str(F("], next: ")); + LogObject.uart_send_hex(nextPacketPtr); + LogObject.uart_send_str(F(", stat: ")); + LogObject.uart_send_hex(rxstat); + LogObject.uart_send_str(F(", Packet count: ")); + LogObject.uart_send_dec(epktcnt); + LogObject.uart_send_str(F(" -> ")); + LogObject.uart_send_strln((rxstat & 0x80) != 0 ? "OK" : "failed"); +#endif + // decrement the packet counter indicate we are done with this packet + writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC); + + // check CRC and symbol errors (see datasheet page 44, table 7-3): + // The ERXFCON.CRCEN is set by default. Normally we should not + // need to check this. + if (((rxstat & 0x80) != 0) && (nextPacketPtr <= RXSTOP_INIT)) + { + receivePkt.begin = readPtr; + receivePkt.size = len; +#if ACTLOGLEVEL>=LOG_DEBUG + LogObject.uart_send_str(F("Enc28J60Network::receivePacket(void) DEBUG: rxstat OK. receivePkt.size=")); + LogObject.uart_send_decln(len); +#endif + return UIP_RECEIVEBUFFERHANDLE; + } + + // Move the RX read pointer to the start of the next received packet + // This frees the memory we just read out + setERXRDPT(); + } + + return (NOBLOCK); +} + +void +Enc28J60Network::setERXRDPT(void) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::setERXRDPT(void) DEBUG_V3:Function started")); +#endif + // Make sure the value is odd. See Rev. B1,B4,B5,B7 Silicon Errata issues 14 + uint16_t actnextPacketPtr = nextPacketPtr == RXSTART_INIT ? RXSTOP_INIT : nextPacketPtr - 1; +#if ACTLOGLEVEL>=LOG_DEBUG + LogObject.uart_send_str(F("Enc28J60Network::setERXRDPT(void) DEBUG:Set actnextPacketPtr:")); + LogObject.uart_send_hexln(actnextPacketPtr); +#endif + // datasheet: The ENC28J60 will always write up to, but not including + writeRegPair(ERXRDPTL, actnextPacketPtr); +} + +memaddress +Enc28J60Network::blockSize(memhandle handle) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::blockSize(memhandle handle) DEBUG_V3:Function started")); +#endif + return ((handle == NOBLOCK) + || (erevid == 0)) ? 0 : handle == UIP_RECEIVEBUFFERHANDLE ? receivePkt.size : blocks[handle].size; +} + +bool +Enc28J60Network::sendPacket(memhandle handle) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::sendPacket(memhandle handle) INFO:Function started")); +#endif +#if defined(ESP8266) + wdt_reset(); +#endif + + if (erevid == 0) + { +#if ACTLOGLEVEL>=LOG_ERR + LogObject.uart_send_strln( + F("Enc28J60Network::sendPacket(memhandle handle) ERROR:ENC28j50 Device not found !! Bypass sendPacket function !!")); +#endif + return false; + } + + memblock *packet = &blocks[handle]; + uint16_t start = packet->begin; // includes the UIP_SENDBUFFER_OFFSET for control byte + uint16_t end = start + packet->size - 1 - + UIP_SENDBUFFER_PADDING; // end = start + size - 1 and padding for TSV is no included + + // write control-byte (if not 0 anyway) + writeByte(start, 0); + +#if ACTLOGLEVEL>=LOG_DEBUG + LogObject.uart_send_str(F("Enc28J60Network::sendPacket(memhandle handle) DEBUG:sendPacket(")); + LogObject.uart_send_dec(handle); + LogObject.uart_send_str(F(") [")); + LogObject.uart_send_hex(start); + LogObject.uart_send_str(F("-")); + LogObject.uart_send_hex(end); + LogObject.uart_send_str(F("]: ")); + + for (uint16_t i = start; i <= end; i++) + { + LogObject.uart_send_hex(readByte(i)); + LogObject.uart_send_str(F(" ")); + } + + LogObject.uart_send_strln(F("")); +#endif + + // TX start + writeRegPair(ETXSTL, start); + // Set the TXND pointer to correspond to the packet size given + writeRegPair(ETXNDL, end); + + bool success = false; + + // See Rev. B7 Silicon Errata issues 12 and 13 + for (uint8_t retry = 0; retry < TX_COLLISION_RETRY_COUNT; retry++) + { + // Reset the transmit logic problem. Errata 12 + writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRST); + writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRST); + writeOp(ENC28J60_BIT_FIELD_CLR, EIR, EIR_TXERIF | EIR_TXIF); + + // send the contents of the transmit buffer onto the network + writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS); + + uint8_t eir; + + // wait for transmission to complete or fail + while (((eir = readReg(EIR)) & (EIR_TXIF | EIR_TXERIF)) == 0); + + writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS); + success = ((eir & EIR_TXERIF) == 0); + + if (success) + break; // usual exit of the for(retry) loop + + // Errata 13 detection + uint8_t tsv4 = readByte(end + 4); + + if (!(tsv4 & 0b00100000)) // is it "late collision" indicated in bit 29 of TSV? + break; // other fail, not the Errata 13 situation + +#if ACTLOGLEVEL>=LOG_ERROR + LogObject.uart_send_strln(F("Enc28J60Network::sendPacket(memhandle handle) Errata 13 LATE COLLISION !!")); +#endif + } + + return success; +} + +uint16_t +Enc28J60Network::setReadPtr(memhandle handle, memaddress position, uint16_t len) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln( + F("Enc28J60Network::setReadPtr(memhandle handle, memaddress position, uint16_t len) DEBUG_V3:Function started")); +#endif + memblock *packet = handle == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[handle]; + memaddress start = handle == UIP_RECEIVEBUFFERHANDLE + && packet->begin + position > RXSTOP_INIT ? packet->begin + position - ((RXSTOP_INIT + 1) - RXSTART_INIT) : + packet->begin + position; + + writeRegPair(ERDPTL, start); + + if (len > packet->size - position) + len = packet->size - position; + + return len; +} + +uint16_t +Enc28J60Network::readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln( + F("Enc28J60Network::readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) DEBUG_V3:Function started")); +#endif +#if defined(ESP8266) + wdt_reset(); +#endif + len = setReadPtr(handle, position, len); + readBuffer(len, buffer); +#if ACTLOGLEVEL>=LOG_DEBUG_V2 + LogObject.uart_send_str( + F("Enc28J60Network::readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) DEBUG_V2: Read bytes:")); + LogObject.uart_send_dec(len); + LogObject.uart_send_str(F(" save to block(")); + LogObject.uart_send_dec(handle); + LogObject.uart_send_str(F(") [")); + LogObject.uart_send_hex(position); + LogObject.uart_send_str(F("]: ")); + + for (uint16_t i = 0; i < len; i++) + { + LogObject.uart_send_hex(buffer[i]); + LogObject.uart_send_str(F(" ")); + } + + LogObject.uart_send_strln(F("")); +#endif + return len; +} + +uint16_t +Enc28J60Network::writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_str( + F("Enc28J60Network::writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) DEBUG_V3:Function started with len:")); + LogObject.uart_send_decln(len); +#endif +#if defined(ESP8266) + wdt_reset(); +#endif + memblock *packet = &blocks[handle]; + uint16_t start = packet->begin + position; + + writeRegPair(EWRPTL, start); + + if (len > packet->size - position) + len = packet->size - position; + + writeBuffer(len, buffer); +#if ACTLOGLEVEL>=LOG_DEBUG_V2 + LogObject.uart_send_str( + F("Enc28J60Network::writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) DEBUG_V2: Write bytes:")); + LogObject.uart_send_dec(len); + LogObject.uart_send_str(F(" save to block(")); + LogObject.uart_send_dec(handle); + LogObject.uart_send_str(F(") [")); + LogObject.uart_send_hex(start); + LogObject.uart_send_str(F("]: ")); + + for (uint16_t i = 0; i < len; i++) + { + LogObject.uart_send_hex(buffer[i]); + LogObject.uart_send_str(F(" ")); + } + + LogObject.uart_send_strln(F("")); +#endif + return len; +} + + +void Enc28J60Network::enableBroadcast (bool temporary) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::enableBroadcast (bool temporary) DEBUG_V3:Function started")); +#endif + writeRegByte(ERXFCON, readRegByte(ERXFCON) | ERXFCON_BCEN); + + if (!temporary) + broadcast_enabled = true; +} + +void Enc28J60Network::disableBroadcast (bool temporary) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::disableBroadcast (bool temporary) DEBUG_V3:Function started")); +#endif + + if (!temporary) + broadcast_enabled = false; + + if (!broadcast_enabled) + writeRegByte(ERXFCON, readRegByte(ERXFCON) & ~ERXFCON_BCEN); +} + +void Enc28J60Network::enableMulticast (void) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::enableMulticast (void) DEBUG_V3:Function started")); +#endif + writeRegByte(ERXFCON, readRegByte(ERXFCON) | ERXFCON_MCEN); +} + +void Enc28J60Network::disableMulticast (void) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::disableMulticast (void) DEBUG_V3:Function started")); +#endif + writeRegByte(ERXFCON, readRegByte(ERXFCON) & ~ERXFCON_MCEN); +} + +uint8_t Enc28J60Network::readRegByte (uint8_t address) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::readRegByte (uint8_t address) DEBUG_V3:Function started")); +#endif + setBank(address); + return readOp(ENC28J60_READ_CTRL_REG, address); +} + +void Enc28J60Network::writeRegByte (uint8_t address, uint8_t data) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::writeRegByte (uint8_t address, uint8_t data) DEBUG_V3:Function started")); +#endif + setBank(address); + writeOp(ENC28J60_WRITE_CTRL_REG, address, data); +} + + +uint8_t Enc28J60Network::readByte(uint16_t addr) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::readByte(uint16_t addr) DEBUG_V3:Function started")); +#endif +#if defined(ESP8266) + wdt_reset(); +#endif + writeRegPair(ERDPTL, addr); + + CSACTIVE; +#if ENC28J60_USE_SPILIB + // issue read command +#if defined(ARDUINO) + SPI.transfer(ENC28J60_READ_BUF_MEM); + // read data + uint8_t c = SPI.transfer(0x00); +#endif +#if defined(__MBED__) + _spi.write(ENC28J60_READ_BUF_MEM); + // read data + uint8_t c = _spi.write(0x00); +#endif + CSPASSIVE; + return (c); +#else + // issue read command + SPDR = ENC28J60_READ_BUF_MEM; + waitspi(); + // read data + SPDR = 0x00; + waitspi(); + CSPASSIVE; + return (SPDR); +#endif +} + +void Enc28J60Network::writeByte(uint16_t addr, uint8_t data) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::writeByte(uint16_t addr, uint8_t data) DEBUG_V3:Function started")); +#endif +#if defined(ESP8266) + wdt_reset(); +#endif + writeRegPair(EWRPTL, addr); + + CSACTIVE; +#if ENC28J60_USE_SPILIB + // issue write command +#if defined(ARDUINO) + SPI.transfer(ENC28J60_WRITE_BUF_MEM); + // write data + SPI.transfer(data); +#endif +#if defined(__MBED__) + _spi.write(ENC28J60_WRITE_BUF_MEM); + // write data + _spi.write(data); +#endif +#else + // issue write command + SPDR = ENC28J60_WRITE_BUF_MEM; + waitspi(); + // write data + SPDR = data; + waitspi(); +#endif + CSPASSIVE; +} + +void +Enc28J60Network::copyPacket(memhandle dest_pkt, memaddress dest_pos, memhandle src_pkt, memaddress src_pos, + uint16_t len) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln( + F("Enc28J60Network::copyPacket(memhandle dest_pkt, memaddress dest_pos, memhandle src_pkt, memaddress src_pos, uint16_t len) DEBUG_V3:Function started")); +#endif + memblock *dest = &blocks[dest_pkt]; + memblock *src = src_pkt == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[src_pkt]; + memaddress start = src_pkt == UIP_RECEIVEBUFFERHANDLE + && src->begin + src_pos > RXSTOP_INIT ? src->begin + src_pos - ((RXSTOP_INIT + 1) - RXSTART_INIT) : src->begin + + src_pos; + enc28J60_mempool_block_move_callback(dest->begin + dest_pos, start, len); + // setERXRDPT(); let it to freePacket after all packets are saved +} + +void +enc28J60_mempool_block_move_callback(memaddress dest, memaddress src, memaddress len) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln( + F("enc28J60_mempool_block_move_callback(memaddress dest, memaddress src, memaddress len) DEBUG_V3:Function started")); +#endif + + //void + //Enc28J60Network::memblock_mv_cb(uint16_t dest, uint16_t src, uint16_t len) + //{ + //as ENC28J60 DMA is unable to copy single bytes: + if (len == 1) + { + Enc28J60Network::writeByte(dest, Enc28J60Network::readByte(src)); + } + else + { + // calculate address of last byte + len += src - 1; + + /* 1. Appropriately program the EDMAST, EDMAND + and EDMADST register pairs. The EDMAST + registers should point to the first byte to copy + from, the EDMAND registers should point to the + last byte to copy and the EDMADST registers + should point to the first byte in the destination + range. The destination range will always be + linear, never wrapping at any values except from + 8191 to 0 (the 8-Kbyte memory boundary). + Extreme care should be taken when + programming the start and end pointers to + prevent a never ending DMA operation which + would overwrite the entire 8-Kbyte buffer. + */ + Enc28J60Network::writeRegPair(EDMASTL, src); + Enc28J60Network::writeRegPair(EDMADSTL, dest); + + if ((src <= RXSTOP_INIT) && (len > RXSTOP_INIT)) + len -= ((RXSTOP_INIT + 1) - RXSTART_INIT); + + Enc28J60Network::writeRegPair(EDMANDL, len); + + /* + 2. If an interrupt at the end of the copy process is + desired, set EIE.DMAIE and EIE.INTIE and + clear EIR.DMAIF. + + 3. Verify that ECON1.CSUMEN is clear. */ + Enc28J60Network::writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_CSUMEN); + + /* 4. Start the DMA copy by setting ECON1.DMAST. */ + Enc28J60Network::writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_DMAST); + + // wait until runnig DMA is completed + while (Enc28J60Network::readOp(ENC28J60_READ_CTRL_REG, ECON1) & ECON1_DMAST) + { + delay(1); + } + } +} + +void +Enc28J60Network::freePacket(void) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::freePacket(void) DEBUG_V3:Function started")); +#endif + setERXRDPT(); +} + +uint8_t +Enc28J60Network::readOp(uint8_t op, uint8_t address) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::readOp(uint8_t op, uint8_t address) DEBUG_V3:Function started")); +#endif + CSACTIVE; + // issue read command +#if ENC28J60_USE_SPILIB +#if defined(ARDUINO) + SPI.transfer(op | (address & ADDR_MASK)); + + // read data + if (address & 0x80) + { + // do dummy read if needed (for mac and mii, see datasheet page 29) + SPI.transfer(0x00); + } + + uint8_t c = SPI.transfer(0x00); +#endif +#if defined(__MBED__) + _spi.write(op | (address & ADDR_MASK)); + + // read data + if (address & 0x80) + { + // do dummy read if needed (for mac and mii, see datasheet page 29) + _spi.write(0x00); + } + + uint8_t c = _spi.write(0x00); +#endif + // release CS + CSPASSIVE; + return (c); +#else + // issue read command + SPDR = op | (address & ADDR_MASK); + waitspi(); + // read data + SPDR = 0x00; + waitspi(); + + // do dummy read if needed (for mac and mii, see datasheet page 29) + if (address & 0x80) + { + SPDR = 0x00; + waitspi(); + } + + // release CS + CSPASSIVE; + return (SPDR); +#endif +#if defined(ESP8266) + yield(); +#endif +} + +void +Enc28J60Network::writeOp(uint8_t op, uint8_t address, uint8_t data) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln( + F("Enc28J60Network::writeOp(uint8_t op, uint8_t address, uint8_t data) DEBUG_V3:Function started")); +#endif + CSACTIVE; + // issue write command +#if ENC28J60_USE_SPILIB +#if defined(ARDUINO) + SPI.transfer(op | (address & ADDR_MASK)); + // write data + SPI.transfer(data); +#endif +#if defined(__MBED__) + _spi.write(op | (address & ADDR_MASK)); + // write data + _spi.write(data); +#endif +#else + // issue write command + SPDR = op | (address & ADDR_MASK); + waitspi(); + // write data + SPDR = data; + waitspi(); +#endif + CSPASSIVE; +#if defined(ESP8266) + yield(); +#endif +} + +void +Enc28J60Network::readBuffer(uint16_t len, uint8_t* data) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::readBuffer(uint16_t len, uint8_t* data) DEBUG_V3:Function started")); +#endif + CSACTIVE; + // issue read command +#if ENC28J60_USE_SPILIB +#if defined(ARDUINO) + SPI.transfer(ENC28J60_READ_BUF_MEM); +#endif +#if defined(__MBED__) + _spi.write(ENC28J60_READ_BUF_MEM); +#endif +#else + SPDR = ENC28J60_READ_BUF_MEM; + waitspi(); +#endif + + while (len) + { + len--; + // read data +#if ENC28J60_USE_SPILIB +#if defined(ARDUINO) + *data = SPI.transfer(0x00); +#endif +#if defined(__MBED__) + *data = _spi.write(0x00); +#endif +#else + SPDR = 0x00; + waitspi(); + *data = SPDR; +#endif + data++; + } + + //*data='\0'; + CSPASSIVE; +} + +void +Enc28J60Network::writeBuffer(uint16_t len, uint8_t* data) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::writeBuffer(uint16_t len, uint8_t* data) DEBUG_V3:Function started")); +#endif + CSACTIVE; + // issue write command +#if ENC28J60_USE_SPILIB +#if defined(ARDUINO) + SPI.transfer(ENC28J60_WRITE_BUF_MEM); +#endif +#if defined(__MBED__) + _spi.write(ENC28J60_WRITE_BUF_MEM); +#endif +#else + SPDR = ENC28J60_WRITE_BUF_MEM; + waitspi(); +#endif + + while (len) + { + len--; + // write data +#if ENC28J60_USE_SPILIB +#if defined(ARDUINO) + SPI.transfer(*data); +#endif +#if defined(__MBED__) + _spi.write(*data); +#endif + data++; +#else + SPDR = *data; + data++; + waitspi(); +#endif + } + + CSPASSIVE; +} + +void +Enc28J60Network::setBank(uint8_t address) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::setBank(uint8_t address) DEBUG_V3:Function started")); +#endif + + // set the bank (if needed) + if ((address & BANK_MASK) != bank) + { + // set the bank + writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1 | ECON1_BSEL0)); + writeOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK) >> 5); + bank = (address & BANK_MASK); + } +} + +uint8_t +Enc28J60Network::readReg(uint8_t address) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::readReg(uint8_t address) DEBUG_V3:Function started")); +#endif + // set the bank + setBank(address); + // do the read + return readOp(ENC28J60_READ_CTRL_REG, address); +} + +void +Enc28J60Network::writeReg(uint8_t address, uint8_t data) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::writeReg(uint8_t address, uint8_t data) DEBUG_V3:Function started")); +#endif + // set the bank + setBank(address); + // do the write + writeOp(ENC28J60_WRITE_CTRL_REG, address, data); +} + +void +Enc28J60Network::writeRegPair(uint8_t address, uint16_t data) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::writeRegPair(uint8_t address, uint16_t data) DEBUG_V3:Function started")); +#endif + // set the bank + setBank(address); + // do the write + writeOp(ENC28J60_WRITE_CTRL_REG, address, (data & 0xFF)); + writeOp(ENC28J60_WRITE_CTRL_REG, address + 1, (data) >> 8); +} + +void +Enc28J60Network::phyWrite(uint8_t address, uint16_t data) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::phyWrite(uint8_t address, uint16_t data) DEBUG_V3:Function started")); +#endif + unsigned int timeout = 15; + // set the PHY register address + writeReg(MIREGADR, address); + // write the PHY data + writeRegPair(MIWRL, data); + + // wait until the PHY write completes + while (readReg(MISTAT) & MISTAT_BUSY) + { + delay(10); +#if defined(ESP8266) + wdt_reset(); +#endif + + if (--timeout == 0) + { +#if ACTLOGLEVEL>=LOG_ERR + LogObject.uart_send_strln(F("Enc28J60Network::phyWrite ERROR:TIMEOUT !!")); +#endif + return; + } + } +} + +uint16_t +Enc28J60Network::phyRead(uint8_t address) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::phyRead(uint8_t address) DEBUG_V3:Function started")); +#endif + unsigned int timeout = 15; + writeReg(MIREGADR, address); + writeReg(MICMD, MICMD_MIIRD); + + // wait until the PHY read completes + while (readReg(MISTAT) & MISTAT_BUSY) + { + delay(10); +#if defined(ESP8266) + wdt_reset(); +#endif + + if (--timeout == 0) + { +#if ACTLOGLEVEL>=LOG_ERR + LogObject.uart_send_strln(F("Enc28J60Network::phyRead ERROR:TIMEOUT !!")); +#endif + return 0; + } + } + + writeReg(MICMD, 0); + return (readReg(MIRDL) | readReg(MIRDH) << 8); +} + +void +Enc28J60Network::clkout(uint8_t clk) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::clkout(uint8_t clk) DEBUG_V3:Function started")); +#endif + //setup clkout: 2 is 12.5MHz: + writeReg(ECOCON, clk & 0x7); +} + +uint16_t +Enc28J60Network::chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln( + F("Enc28J60Network::chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len) DEBUG_V3:Function started")); +#endif + uint16_t t; + len = setReadPtr(handle, pos, len) - 1; + CSACTIVE; + // issue read command +#if ENC28J60_USE_SPILIB +#if defined(ARDUINO) + SPI.transfer(ENC28J60_READ_BUF_MEM); +#endif +#if defined(__MBED__) + _spi.write(ENC28J60_READ_BUF_MEM); +#endif +#else + SPDR = ENC28J60_READ_BUF_MEM; + waitspi(); +#endif + uint16_t i; + + for (i = 0; i < len; i += 2) + { + // read data +#if ENC28J60_USE_SPILIB +#if defined(ARDUINO) + t = SPI.transfer(0x00) << 8; + t += SPI.transfer(0x00); +#endif +#if defined(__MBED__) + t = _spi.write(0x00) << 8; + t += _spi.write(0x00); +#endif +#else + SPDR = 0x00; + waitspi(); + t = SPDR << 8; + SPDR = 0x00; + waitspi(); + t += SPDR; +#endif + sum += t; + + if (sum < t) + { + sum++; /* carry */ + } + } + + if (i == len) + { +#if ENC28J60_USE_SPILIB +#if defined(ARDUINO) + t = (SPI.transfer(0x00) << 8) + 0; +#endif +#if defined(__MBED__) + t = (_spi.write(0x00) << 8) + 0; +#endif +#else + SPDR = 0x00; + waitspi(); + t = (SPDR << 8) + 0; +#endif + sum += t; + + if (sum < t) + { + sum++; /* carry */ + } + } + + CSPASSIVE; + + /* Return sum in host byte order. */ + return sum; +} + +void +Enc28J60Network::powerOff(void) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::powerOff(void) DEBUG_V3:Function started")); +#endif + writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_RXEN); + delay(50); + writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_VRPS); + delay(50); + writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PWRSV); +} + +void +Enc28J60Network::powerOn(void) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::powerOn(void) DEBUG_V3:Function started")); +#endif + writeOp(ENC28J60_BIT_FIELD_CLR, ECON2, ECON2_PWRSV); + delay(50); + writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); + delay(50); +} + +// read erevid from object: +uint8_t +Enc28J60Network::geterevid(void) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_str(F("Enc28J60Network::geterevid(void) DEBUG_V3:Function started and return:")); + LogObject.uart_send_decln(erevid); +#endif + return (erevid); +} + +// read the phstat2 of the chip: +uint16_t +Enc28J60Network::PhyStatus(void) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_str(F("Enc28J60Network::PhyStatus(void) DEBUG_V3:Function started")); + LogObject.uart_send_decln(erevid); +#endif + uint16_t phstat2; + phstat2 = phyRead(PHSTAT2); + + if ((phstat2 & 0x20) > 0) + { + phstat2 = phstat2 & 0x100; + } + + phstat2 = (phstat2 & 0xFF00) | erevid; + + if ((phstat2 & 0x8000) > 0) + { + phstat2 = 0; + } + + return phstat2; +} + +bool +Enc28J60Network::linkStatus(void) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::linkStatus(void) DEBUG_V3:Function started")); +#endif + return (phyRead(PHSTAT2) & 0x0400) > 0; +} diff --git a/LibraryPatches/UIPEthernet-2.0.9/utility/Enc28J60Network.h b/LibraryPatches/UIPEthernet-2.0.9/utility/Enc28J60Network.h index 5174462..6a0db89 100644 --- a/LibraryPatches/UIPEthernet-2.0.9/utility/Enc28J60Network.h +++ b/LibraryPatches/UIPEthernet-2.0.9/utility/Enc28J60Network.h @@ -1,337 +1,338 @@ -/* - Enc28J60NetworkClass.h - UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface. - - Copyright (c) 2013 Norbert Truchsess - All rights reserved. - - inspired by enc28j60.c file from the AVRlib library by Pascal Stang. - For AVRlib See http://www.procyonengineering.com/ - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -#ifndef Enc28J60Network_H_ -#define Enc28J60Network_H_ - -// KH mod -#if defined(ESP32) - //pin SS already defined in ESP32 as pin 5, don't use this as conflict with SPIFFS, EEPROM, etc. - // Use in GPIO13 - #warning ENC28J60Network.h => use ESP32, change ENC28J60_CONTROL_CS/SS_PIN_DEFAULT to GPIO13, MOSI(23), MISO(19), SCK(18) - #define ENC28J60_CONTROL_CS 13 -#endif - -// KH, For nRF52 -#if ( defined(NRF52840_FEATHER) || defined(NRF52832_FEATHER) || defined(NRF52_SERIES) || defined(ARDUINO_NRF52_ADAFRUIT) || \ - defined(NRF52840_FEATHER_SENSE) || defined(NRF52840_ITSYBITSY) || defined(NRF52840_CIRCUITPLAY) || defined(NRF52840_CLUE) || \ - defined(NRF52840_METRO) || defined(NRF52840_PCA10056) || defined(PARTICLE_XENON) || defined(NINA_B302_ublox) || defined(NINA_B112_ublox) ) - #include - #define ENC28J60_USE_SPILIB 1 - - #ifndef USE_THIS_SS_PIN - // default to pin 10 - #define ENC28J60_CONTROL_CS 10 - #else - #warning Using USE_THIS_SS_PIN in Enc28J60Network.h for nRF52 - #define ENC28J60_CONTROL_CS USE_THIS_SS_PIN - #endif -#endif - -// KH, For SAMD21/SAMD51 -#if ( defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKR1000) || defined(ARDUINO_SAMD_MKRWIFI1010) \ - || defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_SAMD_MKRFox1200) || defined(ARDUINO_SAMD_MKRWAN1300) || defined(ARDUINO_SAMD_MKRWAN1310) \ - || defined(ARDUINO_SAMD_MKRGSM1400) || defined(ARDUINO_SAMD_MKRNB1500) || defined(ARDUINO_SAMD_MKRVIDOR4000) || defined(__SAMD21G18A__) \ - || defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) || defined(__SAMD21E18A__) || defined(__SAMD51__) || defined(__SAMD51J20A__) || defined(__SAMD51J19A__) \ - || defined(__SAMD51G19A__) || defined(__SAMD51P19A__) || defined(__SAMD21G18A__) ) - #include - #define ENC28J60_USE_SPILIB 1 - - #ifndef USE_THIS_SS_PIN - // default to pin 10 - #define ENC28J60_CONTROL_CS 10 - #else - #warning Using USE_THIS_SS_PIN in Enc28J60Network.h for SAMD - #define ENC28J60_CONTROL_CS USE_THIS_SS_PIN - #endif -#endif -////// - -#include "mempool.h" -#if defined(__MBED__) - #include - //UIPEthernet(SPI_MOSI, SPI_MISO, SPI_SCK, SPI_CS); - #if defined(TARGET_LPC1768) - #define SPI_MOSI p11 - #define SPI_MISO p12 - #define SPI_SCK p13 - #define SPI_CS p8 - #elif defined(TARGET_LPC1114) - #define SPI_MOSI dp2 - #define SPI_MISO dp1 - #define SPI_SCK dp6 - #define SPI_CS dp25 - #elif defined(TARGET_LPC11U68) - #define SPI_MOSI P0_9 - #define SPI_MISO P0_8 - #define SPI_SCK P1_29 - #define SPI_CS P0_2 - #elif defined(TARGET_NUCLEO_F103RB) || defined(TARGET_NUCLEO_L152RE) || defined(TARGET_NUCLEO_F030R8) \ - || defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F302R8) || defined(TARGET_NUCLEO_L053R8) \ - || defined(TARGET_NUCLEO_F411RE) || defined(TARGET_NUCLEO_F334R8) || defined(TARGET_NUCLEO_F072RB) \ - || defined(TARGET_NUCLEO_F091RC) || defined(TARGET_NUCLEO_F303RE) || defined(TARGET_NUCLEO_F070RB) - #define SPI_MOSI D4 - #define SPI_MISO D5 - #define SPI_SCK D3 - #define SPI_CS D2 - #endif - #define ENC28J60_CONTROL_CS SPI_CS -#endif - -#if defined(STM32F3) || defined(STM32F2) //This is workaround for stm32duino STM32F2, and adafruit wiced feather STM32F2 - #define BOARD_SPI1_NSS_PIN PA4 - #define BOARD_SPI1_SCK_PIN PA5 - #define BOARD_SPI1_MISO_PIN PA6 - #define BOARD_SPI1_MOSI_PIN PA7 -#endif //This is workaround for stm32duino STM32F3, and adafruit wiced feather STM32F2 - -#if defined(BOARD_discovery_f4) - #define __STM32F4__ -#endif -#if defined(__MK20DX128__) || defined(__MKL26Z64__) - #include -#endif - -#if !defined(ENC28J60_CONTROL_CS) - #if defined(__AVR__) || defined(ESP8266) || defined(__RFduino__) - // Arduino Uno (__AVR__) SS defined to pin 10 - // Arduino Leonardo (ARDUINO_AVR_LEONARDO) SS defined to LED_BUILTIN_RX (17) - // Arduino Mega(__AVR_ATmega2560__) SS defined to pin 53 - // ESP8266 (ESP8266) SS defined to pin 15 - #if defined(ARDUINO_AVR_LEONARDO) || defined(ARDUINO_AVR_MICRO) - #define ENC28J60_CONTROL_CS PIN_A10 - #warning "Using LEONARDO borad PIN_A10 for ENC28J60_CONTROL_CS. Use UIPEthernet::init(uint8_t) to change it." - #else - #define ENC28J60_CONTROL_CS SS - #endif - #elif defined(ARDUINO_ARCH_AMEBA) //Defined SS to pin 10 - #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_SS0 - #elif defined(ARDUINO_ARCH_SAMD) - #define ENC28J60_CONTROL_CS SS - #elif defined(__ARDUINO_ARC__) //Intel ARC32 Genuino 101 - #define ENC28J60_CONTROL_CS SS - #elif defined(__RFduino__) //RFduino - #define ENC28J60_CONTROL_CS SS - #elif defined(ARDUINO_ARCH_STM32) // STM32duino core - #define ENC28J60_CONTROL_CS SS - #elif defined(ARDUINO_ARCH_ESP32) // arduino-esp32 - #define ENC28J60_CONTROL_CS SS - #elif defined(STM32_MCU_SERIES) || defined(__STM32F1__) || defined(__STM32F3__) || defined(STM32F3) || defined(__STM32F4__) || defined(STM32F2) - #if defined(BOARD_SPI1_NSS_PIN) - #define ENC28J60_CONTROL_CS BOARD_SPI1_NSS_PIN - #elif defined(ARDUINO_STM32F4_NETDUINO2PLUS) - #define ENC28J60_CONTROL_CS PC8 - #else - #define ENC28J60_CONTROL_CS SPI.nssPin() - //#define ENC28J60_CONTROL_CS PA4 - #endif - #elif defined(__MK20DX128__) || defined(__MKL26Z64__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__IMXRT1062__) - #define ENC28J60_CONTROL_CS PIN_SPI_SS - #endif -#endif -#if !defined(ENC28J60_CONTROL_CS) - #warning "Default ENC28J60_CONTROL_CS could not be defined! Use UIPEthernet::init(uint8_t) to set it." - #define ENC28J60_CONTROL_CS 0 -#endif - -extern uint8_t ENC28J60ControlCS; - -#if !defined(SPI_MOSI) - #if defined(__AVR__) || defined(ESP8266) || defined(__RFduino__) - #define SPI_MOSI MOSI - #elif defined(ARDUINO_ARCH_AMEBA) - #define SPI_MOSI 11 //PC_2 - #elif defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD) - #define SPI_MOSI PIN_SPI_MOSI - #elif defined(__ARDUINO_ARC__) //Intel ARC32 Genuino 101 - #define SPI_MOSI MOSI - #elif defined(__RFduino__) //RFduino - #define SPI_MOSI MOSI - #elif defined(ARDUINO_ARCH_STM32) // STM32duino core - #define SPI_MOSI MOSI - #elif defined(ARDUINO_ARCH_ESP32) // arduino-esp32 - #define SPI_MOSI MOSI - #elif defined(STM32_MCU_SERIES) || defined(__STM32F1__) || defined(__STM32F3__) || defined(STM32F3) || defined(__STM32F4__) || defined(STM32F2) - #if defined(BOARD_SPI1_MOSI_PIN) - #define SPI_MOSI BOARD_SPI1_MOSI_PIN - #else - #define SPI_MOSI SPI.mosiPin() - #endif - #elif defined(__MK20DX128__) || defined(__MKL26Z64__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__IMXRT1062__) - #define SPI_MOSI PIN_SPI_MOSI - #endif -#endif -#if !defined(SPI_MOSI) - // KH mod - //#error "Not defined SPI_MOSI!" - #define SPI_MOSI MOSI - ////// -#endif - -#if !defined(SPI_MISO) - #if defined(__AVR__) || defined(ESP8266) || defined(__RFduino__) - #define SPI_MISO MISO - #elif defined(ARDUINO_ARCH_AMEBA) - #define SPI_MISO 12 //PC_3 - #elif defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD) - #define SPI_MISO PIN_SPI_MISO - #elif defined(__ARDUINO_ARC__) //Intel ARC32 Genuino 101 - #define SPI_MISO MISO - #elif defined(__RFduino__) //RFduino - #define SPI_MISO MISO - #elif defined(ARDUINO_ARCH_STM32) // STM32duino core - #define SPI_MISO MISO - #elif defined(ARDUINO_ARCH_ESP32) // arduino-esp32 - #define SPI_MISO MISO - #elif defined(STM32_MCU_SERIES) || defined(__STM32F1__) || defined(__STM32F3__) || defined(STM32F3) || defined(__STM32F4__) || defined(STM32F2) - #if defined(BOARD_SPI1_MISO_PIN) - #define SPI_MISO BOARD_SPI1_MISO_PIN - #else - #define SPI_MISO SPI.misoPin() - #endif - #elif defined(__MK20DX128__) || defined(__MKL26Z64__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__IMXRT1062__) - #define SPI_MISO PIN_SPI_MISO - #endif -#endif -#if !defined(SPI_MISO) - // KH mod - //#error "Not defined SPI_MISO!" - #define SPI_MISO MISO - ////// -#endif -#if !defined(SPI_SCK) - #if defined(__AVR__) || defined(ESP8266) || defined(__RFduino__) - #define SPI_SCK SCK - #elif defined(ARDUINO_ARCH_AMEBA) - #define SPI_SCK 13 //PC_1 A4 - #elif defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD) - #define SPI_SCK PIN_SPI_SCK - #elif defined(__ARDUINO_ARC__) //Intel ARC32 Genuino 101 - #define SPI_SCK SCK - #elif defined(__RFduino__) //RFduino - #define SPI_SCK SCK - #elif defined(ARDUINO_ARCH_STM32) // STM32duino core - #define SPI_SCK SCK - #elif defined(ARDUINO_ARCH_ESP32) // arduino-esp32 - #define SPI_SCK SCK - #elif defined(STM32_MCU_SERIES) || defined(__STM32F1__) || defined(__STM32F3__) || defined(STM32F3) || defined(__STM32F4__) || defined(STM32F2) - #if defined(BOARD_SPI1_SCK_PIN) - #define SPI_SCK BOARD_SPI1_SCK_PIN - #else - #define SPI_SCK SPI.sckPin() - #endif - #elif defined(__MK20DX128__) || defined(__MKL26Z64__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__IMXRT1062__) - #define SPI_SCK PIN_SPI_SCK - #endif -#endif -#if !defined(SPI_SCK) - // KH, For nRF52 - //#error "Not defined SPI_SCK!" - #define SPI_SCK SCK - ////// -#endif - -#if defined(__MBED__) || defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD) || defined(__ARDUINO_ARC__) || defined(__STM32F1__) || defined(__STM32F3__) || defined(STM32F3) || defined(__STM32F4__) || defined(STM32F2) || defined(ESP8266) || defined(ARDUINO_ARCH_AMEBA) || defined(__MK20DX128__) || defined(__MKL26Z64__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__IMXRT1062__) || defined(__RFduino__) || defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR) - #if defined(ARDUINO) && (!defined(ARDUINO_ARCH_STM32) && defined(STM32F3)) - #include "HardwareSPI.h" - #else - #include - #endif - #define ENC28J60_USE_SPILIB 1 -#endif - -#define UIP_RECEIVEBUFFERHANDLE 0xff - -#define UIP_SENDBUFFER_PADDING 7 -#define UIP_SENDBUFFER_OFFSET 1 - -/* - * Empfangen von ip-header, arp etc... - * wenn tcp/udp -> tcp/udp-callback -> assign new packet to connection - */ - -#define TX_COLLISION_RETRY_COUNT 10 - -class Enc28J60Network : public MemoryPool -{ - -private: - static uint16_t nextPacketPtr; - static uint8_t bank; - static uint8_t erevid; - - static struct memblock receivePkt; - - static bool broadcast_enabled; //!< True if broadcasts enabled (used to allow temporary disable of broadcast for DHCP or other internal functions) - - static uint8_t readOp(uint8_t op, uint8_t address); - static void writeOp(uint8_t op, uint8_t address, uint8_t data); - static uint16_t setReadPtr(memhandle handle, memaddress position, uint16_t len); - static void setERXRDPT(void); - static void readBuffer(uint16_t len, uint8_t* data); - static void writeBuffer(uint16_t len, uint8_t* data); - static uint8_t readByte(uint16_t addr); - static void writeByte(uint16_t addr, uint8_t data); - static void setBank(uint8_t address); - static uint8_t readReg(uint8_t address); - static void writeReg(uint8_t address, uint8_t data); - static void writeRegPair(uint8_t address, uint16_t data); - static void phyWrite(uint8_t address, uint16_t data); - static uint16_t phyRead(uint8_t address); - static void clkout(uint8_t clk); - - static void enableBroadcast (bool temporary); - static void disableBroadcast (bool temporary); - static void enableMulticast (void); - static void disableMulticast (void); - - static uint8_t readRegByte (uint8_t address); - static void writeRegByte (uint8_t address, uint8_t data); - - friend void enc28J60_mempool_block_move_callback(memaddress,memaddress,memaddress); - -public: - - void powerOn(void); - void powerOff(void); - static uint8_t geterevid(void); - uint16_t PhyStatus(void); - static bool linkStatus(void); - - static void init(uint8_t* macaddr); - static memhandle receivePacket(void); - static void freePacket(void); - static memaddress blockSize(memhandle handle); - static bool sendPacket(memhandle handle); - static uint16_t readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len); - static uint16_t writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len); - static void copyPacket(memhandle dest, memaddress dest_pos, memhandle src, memaddress src_pos, uint16_t len); - static uint16_t chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len); -}; - -#endif /* Enc28J60NetworkClass_H_ */ +/* + Enc28J60NetworkClass.h + UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface. + + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + inspired by enc28j60.c file from the AVRlib library by Pascal Stang. + For AVRlib See http://www.procyonengineering.com/ + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef Enc28J60Network_H_ +#define Enc28J60Network_H_ + +// KH mod +#if defined(ESP32) + //pin SS already defined in ESP32 as pin 5, don't use this as conflict with SPIFFS, EEPROM, etc. + // Use in GPIO13 + #warning ENC28J60Network.h => use ESP32, change ENC28J60_CONTROL_CS/SS_PIN_DEFAULT to GPIO13, MOSI(23), MISO(19), SCK(18) + #define ENC28J60_CONTROL_CS 13 +#endif + +// KH, For nRF52 +#if ( defined(NRF52840_FEATHER) || defined(NRF52832_FEATHER) || defined(NRF52_SERIES) || defined(ARDUINO_NRF52_ADAFRUIT) || \ + defined(NRF52840_FEATHER_SENSE) || defined(NRF52840_ITSYBITSY) || defined(NRF52840_CIRCUITPLAY) || defined(NRF52840_CLUE) || \ + defined(NRF52840_METRO) || defined(NRF52840_PCA10056) || defined(PARTICLE_XENON) || defined(NINA_B302_ublox) || defined(NINA_B112_ublox) ) +#include +#define ENC28J60_USE_SPILIB 1 + +#ifndef USE_THIS_SS_PIN + // default to pin 10 + #define ENC28J60_CONTROL_CS 10 +#else + #warning Using USE_THIS_SS_PIN in Enc28J60Network.h for nRF52 + #define ENC28J60_CONTROL_CS USE_THIS_SS_PIN +#endif +#endif + +// KH, For SAMD21/SAMD51 +#if ( defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKR1000) || defined(ARDUINO_SAMD_MKRWIFI1010) \ + || defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_SAMD_MKRFox1200) || defined(ARDUINO_SAMD_MKRWAN1300) || defined(ARDUINO_SAMD_MKRWAN1310) \ + || defined(ARDUINO_SAMD_MKRGSM1400) || defined(ARDUINO_SAMD_MKRNB1500) || defined(ARDUINO_SAMD_MKRVIDOR4000) || defined(__SAMD21G18A__) \ + || defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) || defined(__SAMD21E18A__) || defined(__SAMD51__) || defined(__SAMD51J20A__) || defined(__SAMD51J19A__) \ + || defined(__SAMD51G19A__) || defined(__SAMD51P19A__) || defined(__SAMD21G18A__) ) +#include +#define ENC28J60_USE_SPILIB 1 + +#ifndef USE_THIS_SS_PIN + // default to pin 10 + #define ENC28J60_CONTROL_CS 10 +#else + #warning Using USE_THIS_SS_PIN in Enc28J60Network.h for SAMD + #define ENC28J60_CONTROL_CS USE_THIS_SS_PIN +#endif +#endif +////// + +#include "mempool.h" +#if defined(__MBED__) + #include + //UIPEthernet(SPI_MOSI, SPI_MISO, SPI_SCK, SPI_CS); + #if defined(TARGET_LPC1768) + #define SPI_MOSI p11 + #define SPI_MISO p12 + #define SPI_SCK p13 + #define SPI_CS p8 + #elif defined(TARGET_LPC1114) + #define SPI_MOSI dp2 + #define SPI_MISO dp1 + #define SPI_SCK dp6 + #define SPI_CS dp25 + #elif defined(TARGET_LPC11U68) + #define SPI_MOSI P0_9 + #define SPI_MISO P0_8 + #define SPI_SCK P1_29 + #define SPI_CS P0_2 + #elif defined(TARGET_NUCLEO_F103RB) || defined(TARGET_NUCLEO_L152RE) || defined(TARGET_NUCLEO_F030R8) \ + || defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F302R8) || defined(TARGET_NUCLEO_L053R8) \ + || defined(TARGET_NUCLEO_F411RE) || defined(TARGET_NUCLEO_F334R8) || defined(TARGET_NUCLEO_F072RB) \ + || defined(TARGET_NUCLEO_F091RC) || defined(TARGET_NUCLEO_F303RE) || defined(TARGET_NUCLEO_F070RB) + #define SPI_MOSI D4 + #define SPI_MISO D5 + #define SPI_SCK D3 + #define SPI_CS D2 + #endif + #define ENC28J60_CONTROL_CS SPI_CS +#endif + +#if defined(STM32F3) || defined(STM32F2) //This is workaround for stm32duino STM32F2, and adafruit wiced feather STM32F2 + #define BOARD_SPI1_NSS_PIN PA4 + #define BOARD_SPI1_SCK_PIN PA5 + #define BOARD_SPI1_MISO_PIN PA6 + #define BOARD_SPI1_MOSI_PIN PA7 +#endif //This is workaround for stm32duino STM32F3, and adafruit wiced feather STM32F2 + +#if defined(BOARD_discovery_f4) + #define __STM32F4__ +#endif +#if defined(__MK20DX128__) || defined(__MKL26Z64__) + #include +#endif + +#if !defined(ENC28J60_CONTROL_CS) + #if defined(__AVR__) || defined(ESP8266) || defined(__RFduino__) + // Arduino Uno (__AVR__) SS defined to pin 10 + // Arduino Leonardo (ARDUINO_AVR_LEONARDO) SS defined to LED_BUILTIN_RX (17) + // Arduino Mega(__AVR_ATmega2560__) SS defined to pin 53 + // ESP8266 (ESP8266) SS defined to pin 15 + #if defined(ARDUINO_AVR_LEONARDO) || defined(ARDUINO_AVR_MICRO) + #define ENC28J60_CONTROL_CS PIN_A10 + #warning "Using LEONARDO borad PIN_A10 for ENC28J60_CONTROL_CS. Use UIPEthernet::init(uint8_t) to change it." + #else + #define ENC28J60_CONTROL_CS SS + #endif + #elif defined(ARDUINO_ARCH_AMEBA) //Defined SS to pin 10 + #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_SS0 + #elif defined(ARDUINO_ARCH_SAMD) + #define ENC28J60_CONTROL_CS SS + #elif defined(__ARDUINO_ARC__) //Intel ARC32 Genuino 101 + #define ENC28J60_CONTROL_CS SS + #elif defined(__RFduino__) //RFduino + #define ENC28J60_CONTROL_CS SS + #elif defined(ARDUINO_ARCH_STM32) // STM32duino core + #define ENC28J60_CONTROL_CS SS + #elif defined(ARDUINO_ARCH_ESP32) // arduino-esp32 + #define ENC28J60_CONTROL_CS SS + #elif defined(STM32_MCU_SERIES) || defined(__STM32F1__) || defined(__STM32F3__) || defined(STM32F3) || defined(__STM32F4__) || defined(STM32F2) + #if defined(BOARD_SPI1_NSS_PIN) + #define ENC28J60_CONTROL_CS BOARD_SPI1_NSS_PIN + #elif defined(ARDUINO_STM32F4_NETDUINO2PLUS) + #define ENC28J60_CONTROL_CS PC8 + #else + #define ENC28J60_CONTROL_CS SPI.nssPin() + //#define ENC28J60_CONTROL_CS PA4 + #endif + #elif defined(__MK20DX128__) || defined(__MKL26Z64__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__IMXRT1062__) + #define ENC28J60_CONTROL_CS PIN_SPI_SS + #endif +#endif +#if !defined(ENC28J60_CONTROL_CS) + #warning "Default ENC28J60_CONTROL_CS could not be defined! Use UIPEthernet::init(uint8_t) to set it." + #define ENC28J60_CONTROL_CS 0 +#endif + +extern uint8_t ENC28J60ControlCS; + +#if !defined(SPI_MOSI) + #if defined(__AVR__) || defined(ESP8266) || defined(__RFduino__) + #define SPI_MOSI MOSI + #elif defined(ARDUINO_ARCH_AMEBA) + #define SPI_MOSI 11 //PC_2 + #elif defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD) + #define SPI_MOSI PIN_SPI_MOSI + #elif defined(__ARDUINO_ARC__) //Intel ARC32 Genuino 101 + #define SPI_MOSI MOSI + #elif defined(__RFduino__) //RFduino + #define SPI_MOSI MOSI + #elif defined(ARDUINO_ARCH_STM32) // STM32duino core + #define SPI_MOSI MOSI + #elif defined(ARDUINO_ARCH_ESP32) // arduino-esp32 + #define SPI_MOSI MOSI + #elif defined(STM32_MCU_SERIES) || defined(__STM32F1__) || defined(__STM32F3__) || defined(STM32F3) || defined(__STM32F4__) || defined(STM32F2) + #if defined(BOARD_SPI1_MOSI_PIN) + #define SPI_MOSI BOARD_SPI1_MOSI_PIN + #else + #define SPI_MOSI SPI.mosiPin() + #endif + #elif defined(__MK20DX128__) || defined(__MKL26Z64__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__IMXRT1062__) + #define SPI_MOSI PIN_SPI_MOSI + #endif +#endif +#if !defined(SPI_MOSI) + // KH mod + //#error "Not defined SPI_MOSI!" + #define SPI_MOSI MOSI + ////// +#endif + +#if !defined(SPI_MISO) + #if defined(__AVR__) || defined(ESP8266) || defined(__RFduino__) + #define SPI_MISO MISO + #elif defined(ARDUINO_ARCH_AMEBA) + #define SPI_MISO 12 //PC_3 + #elif defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD) + #define SPI_MISO PIN_SPI_MISO + #elif defined(__ARDUINO_ARC__) //Intel ARC32 Genuino 101 + #define SPI_MISO MISO + #elif defined(__RFduino__) //RFduino + #define SPI_MISO MISO + #elif defined(ARDUINO_ARCH_STM32) // STM32duino core + #define SPI_MISO MISO + #elif defined(ARDUINO_ARCH_ESP32) // arduino-esp32 + #define SPI_MISO MISO + #elif defined(STM32_MCU_SERIES) || defined(__STM32F1__) || defined(__STM32F3__) || defined(STM32F3) || defined(__STM32F4__) || defined(STM32F2) + #if defined(BOARD_SPI1_MISO_PIN) + #define SPI_MISO BOARD_SPI1_MISO_PIN + #else + #define SPI_MISO SPI.misoPin() + #endif + #elif defined(__MK20DX128__) || defined(__MKL26Z64__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__IMXRT1062__) + #define SPI_MISO PIN_SPI_MISO + #endif +#endif +#if !defined(SPI_MISO) + // KH mod + //#error "Not defined SPI_MISO!" + #define SPI_MISO MISO + ////// +#endif +#if !defined(SPI_SCK) + #if defined(__AVR__) || defined(ESP8266) || defined(__RFduino__) + #define SPI_SCK SCK + #elif defined(ARDUINO_ARCH_AMEBA) + #define SPI_SCK 13 //PC_1 A4 + #elif defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD) + #define SPI_SCK PIN_SPI_SCK + #elif defined(__ARDUINO_ARC__) //Intel ARC32 Genuino 101 + #define SPI_SCK SCK + #elif defined(__RFduino__) //RFduino + #define SPI_SCK SCK + #elif defined(ARDUINO_ARCH_STM32) // STM32duino core + #define SPI_SCK SCK + #elif defined(ARDUINO_ARCH_ESP32) // arduino-esp32 + #define SPI_SCK SCK + #elif defined(STM32_MCU_SERIES) || defined(__STM32F1__) || defined(__STM32F3__) || defined(STM32F3) || defined(__STM32F4__) || defined(STM32F2) + #if defined(BOARD_SPI1_SCK_PIN) + #define SPI_SCK BOARD_SPI1_SCK_PIN + #else + #define SPI_SCK SPI.sckPin() + #endif + #elif defined(__MK20DX128__) || defined(__MKL26Z64__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__IMXRT1062__) + #define SPI_SCK PIN_SPI_SCK + #endif +#endif +#if !defined(SPI_SCK) + // KH, For nRF52 + //#error "Not defined SPI_SCK!" + #define SPI_SCK SCK + ////// +#endif + +#if defined(__MBED__) || defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD) || defined(__ARDUINO_ARC__) || defined(__STM32F1__) || defined(__STM32F3__) || defined(STM32F3) || defined(__STM32F4__) || defined(STM32F2) || defined(ESP8266) || defined(ARDUINO_ARCH_AMEBA) || defined(__MK20DX128__) || defined(__MKL26Z64__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__IMXRT1062__) || defined(__RFduino__) || defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR) + #if defined(ARDUINO) && (!defined(ARDUINO_ARCH_STM32) && defined(STM32F3)) + #include "HardwareSPI.h" + #else + #include + #endif + #define ENC28J60_USE_SPILIB 1 +#endif + +#define UIP_RECEIVEBUFFERHANDLE 0xff + +#define UIP_SENDBUFFER_PADDING 7 +#define UIP_SENDBUFFER_OFFSET 1 + +/* + Empfangen von ip-header, arp etc... + wenn tcp/udp -> tcp/udp-callback -> assign new packet to connection +*/ + +#define TX_COLLISION_RETRY_COUNT 10 + +class Enc28J60Network : public MemoryPool +{ + + private: + static uint16_t nextPacketPtr; + static uint8_t bank; + static uint8_t erevid; + + static struct memblock receivePkt; + + static bool + broadcast_enabled; //!< True if broadcasts enabled (used to allow temporary disable of broadcast for DHCP or other internal functions) + + static uint8_t readOp(uint8_t op, uint8_t address); + static void writeOp(uint8_t op, uint8_t address, uint8_t data); + static uint16_t setReadPtr(memhandle handle, memaddress position, uint16_t len); + static void setERXRDPT(void); + static void readBuffer(uint16_t len, uint8_t* data); + static void writeBuffer(uint16_t len, uint8_t* data); + static uint8_t readByte(uint16_t addr); + static void writeByte(uint16_t addr, uint8_t data); + static void setBank(uint8_t address); + static uint8_t readReg(uint8_t address); + static void writeReg(uint8_t address, uint8_t data); + static void writeRegPair(uint8_t address, uint16_t data); + static void phyWrite(uint8_t address, uint16_t data); + static uint16_t phyRead(uint8_t address); + static void clkout(uint8_t clk); + + static void enableBroadcast (bool temporary); + static void disableBroadcast (bool temporary); + static void enableMulticast (void); + static void disableMulticast (void); + + static uint8_t readRegByte (uint8_t address); + static void writeRegByte (uint8_t address, uint8_t data); + + friend void enc28J60_mempool_block_move_callback(memaddress, memaddress, memaddress); + + public: + + void powerOn(void); + void powerOff(void); + static uint8_t geterevid(void); + uint16_t PhyStatus(void); + static bool linkStatus(void); + + static void init(uint8_t* macaddr); + static memhandle receivePacket(void); + static void freePacket(void); + static memaddress blockSize(memhandle handle); + static bool sendPacket(memhandle handle); + static uint16_t readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len); + static uint16_t writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len); + static void copyPacket(memhandle dest, memaddress dest_pos, memhandle src, memaddress src_pos, uint16_t len); + static uint16_t chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len); +}; + +#endif /* Enc28J60NetworkClass_H_ */ diff --git a/LibraryPatches/UIPEthernet/UIPEthernet.cpp b/LibraryPatches/UIPEthernet/UIPEthernet.cpp index df35732..657d2d8 100644 --- a/LibraryPatches/UIPEthernet/UIPEthernet.cpp +++ b/LibraryPatches/UIPEthernet/UIPEthernet.cpp @@ -1,641 +1,698 @@ -/* - UIPEthernet.cpp - Arduino implementation of a uIP wrapper class. - Copyright (c) 2013 Norbert Truchsess - All rights reserved. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -#if defined(ARDUINO) - #include -#endif -#if defined(__MBED__) - #include - #include "mbed/millis.h" -#endif -#include "UIPEthernet.h" -#include "utility/logging.h" -#include "utility/Enc28J60Network.h" - -#include "UIPUdp.h" - -extern "C" -{ -#include "utility/uipopt.h" -#include "utility/uip.h" -#include "utility/uip_arp.h" -#include "utility/uip_timer.h" -} - -#define ETH_HDR ((struct uip_eth_hdr *)&uip_buf[0]) - -memhandle UIPEthernetClass::in_packet(NOBLOCK); -memhandle UIPEthernetClass::uip_packet(NOBLOCK); -uint8_t UIPEthernetClass::uip_hdrlen(0); -uint8_t UIPEthernetClass::packetstate(0); - -unsigned long UIPEthernetClass::periodic_timer; - -IPAddress UIPEthernetClass::_dnsServerAddress; -#if UIP_UDP - DhcpClass* UIPEthernetClass::_dhcp(NULL); - static DhcpClass s_dhcp; // Placing this instance here is saving 40K to final *.bin (see bug below) -#endif - -// Because uIP isn't encapsulated within a class we have to use global -// variables, so we can only have one TCP/IP stack per program. - -UIPEthernetClass::UIPEthernetClass() -{ -} - -void UIPEthernetClass::init(const uint8_t pin) -{ - ENC28J60ControlCS = pin; -} - -#if UIP_UDP -int -UIPEthernetClass::begin(const uint8_t* mac) -{ - // KH mod to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ - // Now store to private var _mac_address - //uint8_t _mac_address[6] ={0,}; - memcpy(_mac_address, mac, sizeof(_mac_address)); - ////// - - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::begin(const uint8_t* mac) DEBUG_V3:Function started")); - #endif - //static DhcpClass s_dhcp; // <-- this is a bug ! - // I leave it there commented for history. It is bring all GCC "new" memory allocation code, making the *.bin almost 40K bigger. I've move it globally. - _dhcp = &s_dhcp; - // Initialise the basic info - netInit(mac); - - // Now try to get our config info from a DHCP server - int ret = _dhcp->beginWithDHCP((uint8_t*)mac); - if(ret == 1) - { - // We've successfully found a DHCP server and got our configuration info, so set things - // accordingly - configure(_dhcp->getLocalIp(),_dhcp->getDnsServerIp(),_dhcp->getGatewayIp(),_dhcp->getSubnetMask()); - } - return ret; -} -#endif - -void -UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip) -{ - // KH mod to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ - // Now store to private var _mac_address - //uint8_t _mac_address[6] ={0,}; - memcpy(_mac_address, mac, sizeof(_mac_address)); - ////// - - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip) DEBUG_V3:Function started")); - #endif - IPAddress dns = ip; - dns[3] = 1; - begin(mac, ip, dns); -} - -void -UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns) -{ - // KH mod to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ - // Now store to private var _mac_address - //uint8_t _mac_address[6] ={0,}; - memcpy(_mac_address, mac, sizeof(_mac_address)); - ////// - - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns) DEBUG_V3:Function started")); - #endif - IPAddress gateway = ip; - gateway[3] = 1; - begin(mac, ip, dns, gateway); -} - -void -UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway) -{ - // KH mod to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ - // Now store to private var _mac_address - //uint8_t _mac_address[6] ={0,}; - memcpy(_mac_address, mac, sizeof(_mac_address)); - ////// - - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway) DEBUG_V3:Function started")); - #endif - IPAddress subnet(255, 255, 255, 0); - begin(mac, ip, dns, gateway, subnet); -} - -void -UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) -{ - // KH mod to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ - // Now store to private var _mac_address - //uint8_t _mac_address[6] ={0,}; - memcpy(_mac_address, mac, sizeof(_mac_address)); - ////// - - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) DEBUG_V3:Function started")); - #endif - netInit(mac); - configure(ip,dns,gateway,subnet); -} - -int UIPEthernetClass::maintain(){ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::maintain() DEBUG_V3:Function started")); - #endif - tick(); - int rc = DHCP_CHECK_NONE; -#if UIP_UDP - if(_dhcp != NULL){ - //we have a pointer to dhcp, use it - rc = _dhcp->checkLease(); - switch ( rc ){ - case DHCP_CHECK_NONE: - //nothing done - break; - case DHCP_CHECK_RENEW_OK: - case DHCP_CHECK_REBIND_OK: - //we might have got a new IP. - configure(_dhcp->getLocalIp(),_dhcp->getDnsServerIp(),_dhcp->getGatewayIp(),_dhcp->getSubnetMask()); - break; - default: - //this is actually a error, it will retry though - break; - } - } - return rc; -#endif -} - -EthernetLinkStatus UIPEthernetClass::linkStatus() -{ - if (!Enc28J60.geterevid()) - return Unknown; - return Enc28J60.linkStatus() ? LinkON : LinkOFF; -} - -IPAddress UIPEthernetClass::localIP() -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::localIP() DEBUG_V3:Function started")); - #endif - IPAddress ret; - uip_ipaddr_t a; - uip_gethostaddr(a); - return ip_addr_uip(a); -} - -IPAddress UIPEthernetClass::subnetMask() -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::subnetMask() DEBUG_V3:Function started")); - #endif - IPAddress ret; - uip_ipaddr_t a; - uip_getnetmask(a); - return ip_addr_uip(a); -} - -IPAddress UIPEthernetClass::gatewayIP() -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::gatewayIP() DEBUG_V3:Function started")); - #endif - IPAddress ret; - uip_ipaddr_t a; - uip_getdraddr(a); - return ip_addr_uip(a); -} - -IPAddress UIPEthernetClass::dnsServerIP() -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::dnsServerIP() DEBUG_V3:Function started")); - #endif - return _dnsServerAddress; -} - -void -UIPEthernetClass::tick() -{ -#if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::tick() DEBUG_V3:Function started")); -#endif -if (Enc28J60Network::geterevid()==0) - { - #if ACTLOGLEVEL>=LOG_ERR - LogObject.uart_send_strln(F("UIPEthernetClass::tick() ERROR:EREVID=0 -> Not found ENC28j60 device !! Function ended !!")); - #endif - return; - } -#if defined(ESP8266) - wdt_reset(); -#endif - if (in_packet == NOBLOCK) - { - in_packet = Enc28J60Network::receivePacket(); - #if ACTLOGLEVEL>=LOG_DEBUG - if (in_packet != NOBLOCK) - { - LogObject.uart_send_str(F("UIPEthernetClass::tick() DEBUG:receivePacket: ")); - LogObject.uart_send_decln(in_packet); - } - #endif - } - if (in_packet != NOBLOCK) - { - packetstate = UIPETHERNET_FREEPACKET; - uip_len = Enc28J60Network::blockSize(in_packet); - if (uip_len > 0) - { - Enc28J60Network::readPacket(in_packet,0,(uint8_t*)uip_buf,UIP_BUFSIZE); - if (ETH_HDR ->type == HTONS(UIP_ETHTYPE_IP)) - { - uip_packet = in_packet; //required for upper_layer_checksum of in_packet! - #if ACTLOGLEVEL>=LOG_DEBUG - LogObject.uart_send_str(F("UIPEthernetClass::tick() DEBUG:readPacket type IP, uip_len: ")); - LogObject.uart_send_decln(uip_len); - #endif - uip_arp_ipin(); - uip_input(); - if (uip_len > 0) - { - uip_arp_out(); - network_send(); - } - } - else if (ETH_HDR ->type == HTONS(UIP_ETHTYPE_ARP)) - { - #if ACTLOGLEVEL>=LOG_DEBUG - LogObject.uart_send_str(F("UIPEthernetClass::tick() DEBUG:readPacket type ARP, uip_len: ")); - LogObject.uart_send_decln(uip_len); - #endif - uip_arp_arpin(); - if (uip_len > 0) - { - network_send(); - } - } - } - if (in_packet != NOBLOCK && (packetstate & UIPETHERNET_FREEPACKET)) - { - #if ACTLOGLEVEL>=LOG_DEBUG - LogObject.uart_send_str(F("UIPEthernetClass::tick() DEBUG:freeing packet: ")); - LogObject.uart_send_decln(in_packet); - #endif - Enc28J60Network::freePacket(); - in_packet = NOBLOCK; - } - } - - unsigned long now = millis(); - -#if UIP_CLIENT_TIMER >= 0 - bool periodic = (long)( now - periodic_timer ) >= 0; - for (int i = 0; i < UIP_CONNS; i++) - { -#else - if ((long)( now - periodic_timer ) >= 0) - { - periodic_timer = now + UIP_PERIODIC_TIMER; - - for (int i = 0; i < UIP_CONNS; i++) - { -#endif - - uip_conn = &uip_conns[i]; - -#if UIP_CLIENT_TIMER >= 0 - if (periodic) - { -#endif - - uip_process(UIP_TIMER); - -#if UIP_CLIENT_TIMER >= 0 - } - else - { - if (uip_conn!=NULL) - { - if (((uip_userdata_t*)uip_conn->appstate)!=NULL) - { - if ((long)( now - ((uip_userdata_t*)uip_conn->appstate)->timer) >= 0) - { - uip_process(UIP_POLL_REQUEST); - } - else - { - continue; - } - } - else - { - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::tick() DEBUG_V3:((uip_userdata_t*)uip_conn->appstate) is NULL")); - #endif - if ((long)( now - ((uip_userdata_t*)uip_conn)->timer) >= 0) - { - uip_process(UIP_POLL_REQUEST); - } - else - { - continue; - } - } - } - else - { - #if ACTLOGLEVEL>=LOG_ERR - LogObject.uart_send_strln(F("UIPEthernetClass::tick() ERROR:uip_conn is NULL")); - #endif - continue; - } - } -#endif - // If the above function invocation resulted in data that - // should be sent out on the Enc28J60Network, the global variable - // uip_len is set to a value > 0. - if (uip_len > 0) - { - uip_arp_out(); - network_send(); - } - } -#if UIP_CLIENT_TIMER >= 0 - if (periodic) - { - periodic_timer = now + UIP_PERIODIC_TIMER; -#endif -#if UIP_UDP - for (int i = 0; i < UIP_UDP_CONNS; i++) - { - uip_udp_periodic(i); - // If the above function invocation resulted in data that - // should be sent out on the Enc28J60Network, the global variable - // uip_len is set to a value > 0. */ - if (uip_len > 0) - { - UIPUDP::_send((uip_udp_userdata_t *)(uip_udp_conns[i].appstate)); - } - } -#endif /* UIP_UDP */ - } -} - -bool UIPEthernetClass::network_send() -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::network_send() DEBUG_V3:Function started")); - #endif - if (packetstate & UIPETHERNET_SENDPACKET) - { -#if ACTLOGLEVEL>=LOG_DEBUG - LogObject.uart_send_str(F("UIPEthernetClass::network_send() DEBUG:uip_packet: ")); - LogObject.uart_send_dec(uip_packet); - LogObject.uart_send_str(F(", hdrlen: ")); - LogObject.uart_send_decln(uip_hdrlen); -#endif - Enc28J60Network::writePacket(uip_packet,0,uip_buf,uip_hdrlen); - packetstate &= ~ UIPETHERNET_SENDPACKET; - goto sendandfree; - } - uip_packet = Enc28J60Network::allocBlock(uip_len); - if (uip_packet != NOBLOCK) - { -#if ACTLOGLEVEL>=LOG_DEBUG - LogObject.uart_send_str(F("UIPEthernetClass::network_send() DEBUG:uip_buf (uip_len): ")); - LogObject.uart_send_dec(uip_len); - LogObject.uart_send_str(F(", packet: ")); - LogObject.uart_send_decln(uip_packet); -#endif - Enc28J60Network::writePacket(uip_packet,0,uip_buf,uip_len); - goto sendandfree; - } - return false; -sendandfree: - Enc28J60Network::sendPacket(uip_packet); - Enc28J60Network::freeBlock(uip_packet); - uip_packet = NOBLOCK; - return true; -} - -void UIPEthernetClass::netInit(const uint8_t* mac) { - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::netInit(const uint8_t* mac) DEBUG_V3:Function started")); - #endif - periodic_timer = millis() + UIP_PERIODIC_TIMER; - - Enc28J60Network::init((uint8_t*)mac); - uip_seteth_addr(mac); - - uip_init(); - uip_arp_init(); -} - -void UIPEthernetClass::configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) { - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) DEBUG_V3:Function started")); - #endif - uip_ipaddr_t ipaddr; - - uip_ip_addr(ipaddr, ip); - uip_sethostaddr(ipaddr); - - uip_ip_addr(ipaddr, gateway); - uip_setdraddr(ipaddr); - - uip_ip_addr(ipaddr, subnet); - uip_setnetmask(ipaddr); - - _dnsServerAddress = dns; -} - -UIPEthernetClass UIPEthernet; - -/*---------------------------------------------------------------------------*/ -uint16_t -UIPEthernetClass::chksum(uint16_t sum, const uint8_t *data, uint16_t len) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::chksum(uint16_t sum, const uint8_t *data, uint16_t len) DEBUG_V3:Function started")); - #endif - uint16_t t; - const uint8_t *dataptr; - const uint8_t *last_byte; - - dataptr = data; - last_byte = data + len - 1; - - while(dataptr < last_byte) { /* At least two more bytes */ - t = (dataptr[0] << 8) + dataptr[1]; - sum += t; - if(sum < t) { - sum++; /* carry */ - } - dataptr += 2; - } - - if(dataptr == last_byte) { - t = (dataptr[0] << 8) + 0; - sum += t; - if(sum < t) { - sum++; /* carry */ - } - } - - /* Return sum in host byte order. */ - return sum; -} - -/*---------------------------------------------------------------------------*/ - -uint16_t -UIPEthernetClass::ipchksum(void) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("UIPEthernetClass::ipchksum(void) DEBUG_V3:Function started")); - #endif - uint16_t sum; - - sum = chksum(0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN); - return (sum == 0) ? 0xffff : htons(sum); -} - -/*---------------------------------------------------------------------------*/ -uint16_t -#if UIP_UDP -UIPEthernetClass::upper_layer_chksum(uint8_t proto) -#else -uip_tcpchksum(void) -#endif -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - #if UIP_UDP - LogObject.uart_send_strln(F("UIPEthernetClass::upper_layer_chksum(uint8_t proto) DEBUG_V3:Function started")); - #else - LogObject.uart_send_strln(F("uip_tcpchksum(void) INFO:Function started")); - #endif - #endif - uint16_t upper_layer_len; - uint16_t sum; - -#if UIP_CONF_IPV6 - upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]); -#else /* UIP_CONF_IPV6 */ - upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - UIP_IPH_LEN; -#endif /* UIP_CONF_IPV6 */ - - /* First sum pseudoheader. */ - - /* IP protocol and length fields. This addition cannot carry. */ -#if UIP_UDP - sum = upper_layer_len + proto; -#else - sum = upper_layer_len + UIP_PROTO_TCP; -#endif - /* Sum IP source and destination addresses. */ - sum = UIPEthernetClass::chksum(sum, (u8_t *)&BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t)); - - uint8_t upper_layer_memlen; -#if UIP_UDP - switch(proto) - { -// case UIP_PROTO_ICMP: -// case UIP_PROTO_ICMP6: -// upper_layer_memlen = upper_layer_len; -// break; - case UIP_PROTO_UDP: - upper_layer_memlen = UIP_UDPH_LEN; - break; - default: -// case UIP_PROTO_TCP: -#endif - upper_layer_memlen = (BUF->tcpoffset >> 4) << 2; -#if UIP_UDP - break; - } -#endif - sum = UIPEthernetClass::chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], upper_layer_memlen); -#if ACTLOGLEVEL>=LOG_DEBUG - #if UIP_UDP - LogObject.uart_send_str(F("UIPEthernetClass::upper_layer_chksum(uint8_t proto) DEBUG:uip_buf[")); - #else - LogObject.uart_send_str(F("uip_tcpchksum(void) DEBUG:uip_buf[")); - #endif - LogObject.uart_send_dec(UIP_IPH_LEN + UIP_LLH_LEN); - LogObject.uart_send_str(F("-")); - LogObject.uart_send_dec(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen); - LogObject.uart_send_str(F("]: ")); - LogObject.uart_send_hexln(htons(sum)); -#endif - if (upper_layer_memlen < upper_layer_len) - { - sum = Enc28J60Network::chksum( - sum, - UIPEthernetClass::uip_packet, - UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen, - upper_layer_len - upper_layer_memlen - ); -#if ACTLOGLEVEL>=LOG_DEBUG - #if UIP_UDP - LogObject.uart_send_str(F("UIPEthernetClass::upper_layer_chksum(uint8_t proto) DEBUG:uip_packet(")); - #else - LogObject.uart_send_str(F("uip_tcpchksum(void) DEBUG:uip_packet(")); - #endif - LogObject.uart_send_dec(UIPEthernetClass::uip_packet); - LogObject.uart_send_str(F(")[")); - LogObject.uart_send_dec(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen); - LogObject.uart_send_str(F("-")); - LogObject.uart_send_dec(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_len); - LogObject.uart_send_str(F("]: ")); - LogObject.uart_send_hexln(htons(sum)); -#endif - } - return (sum == 0) ? 0xffff : htons(sum); -} - -uint16_t -uip_ipchksum(void) -{ - return UIPEthernet.ipchksum(); -} - -#if UIP_UDP -uint16_t -uip_tcpchksum(void) -{ - uint16_t sum = UIPEthernet.upper_layer_chksum(UIP_PROTO_TCP); - return sum; -} - -uint16_t -uip_udpchksum(void) -{ - uint16_t sum = UIPEthernet.upper_layer_chksum(UIP_PROTO_UDP); - return sum; -} -#endif +/* + UIPEthernet.cpp - Arduino implementation of a uIP wrapper class. + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if defined(ARDUINO) + #include +#endif +#if defined(__MBED__) + #include + #include "mbed/millis.h" +#endif +#include "UIPEthernet.h" +#include "utility/logging.h" +#include "utility/Enc28J60Network.h" + +#include "UIPUdp.h" + +extern "C" +{ +#include "utility/uipopt.h" +#include "utility/uip.h" +#include "utility/uip_arp.h" +#include "utility/uip_timer.h" +} + +#define ETH_HDR ((struct uip_eth_hdr *)&uip_buf[0]) + +memhandle UIPEthernetClass::in_packet(NOBLOCK); +memhandle UIPEthernetClass::uip_packet(NOBLOCK); +uint8_t UIPEthernetClass::uip_hdrlen(0); +uint8_t UIPEthernetClass::packetstate(0); + +unsigned long UIPEthernetClass::periodic_timer; + +IPAddress UIPEthernetClass::_dnsServerAddress; +#if UIP_UDP + DhcpClass* UIPEthernetClass::_dhcp(NULL); + static DhcpClass s_dhcp; // Placing this instance here is saving 40K to final *.bin (see bug below) +#endif + +// Because uIP isn't encapsulated within a class we have to use global +// variables, so we can only have one TCP/IP stack per program. + +UIPEthernetClass::UIPEthernetClass() +{ +} + +void UIPEthernetClass::init(const uint8_t pin) +{ + ENC28J60ControlCS = pin; +} + +#if UIP_UDP +int +UIPEthernetClass::begin(const uint8_t* mac) +{ + // KH mod to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ + // Now store to private var _mac_address + //uint8_t _mac_address[6] ={0,}; + memcpy(_mac_address, mac, sizeof(_mac_address)); + ////// + +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("UIPEthernetClass::begin(const uint8_t* mac) DEBUG_V3:Function started")); +#endif + //static DhcpClass s_dhcp; // <-- this is a bug ! + // I leave it there commented for history. It is bring all GCC "new" memory allocation code, making the *.bin almost 40K bigger. I've move it globally. + _dhcp = &s_dhcp; + // Initialise the basic info + netInit(mac); + + // Now try to get our config info from a DHCP server + int ret = _dhcp->beginWithDHCP((uint8_t*)mac); + + if (ret == 1) + { + // We've successfully found a DHCP server and got our configuration info, so set things + // accordingly + configure(_dhcp->getLocalIp(), _dhcp->getDnsServerIp(), _dhcp->getGatewayIp(), _dhcp->getSubnetMask()); + } + + return ret; +} +#endif + +void +UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip) +{ + // KH mod to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ + // Now store to private var _mac_address + //uint8_t _mac_address[6] ={0,}; + memcpy(_mac_address, mac, sizeof(_mac_address)); + ////// + +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip) DEBUG_V3:Function started")); +#endif + IPAddress dns = ip; + dns[3] = 1; + begin(mac, ip, dns); +} + +void +UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns) +{ + // KH mod to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ + // Now store to private var _mac_address + //uint8_t _mac_address[6] ={0,}; + memcpy(_mac_address, mac, sizeof(_mac_address)); + ////// + +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln( + F("UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns) DEBUG_V3:Function started")); +#endif + IPAddress gateway = ip; + gateway[3] = 1; + begin(mac, ip, dns, gateway); +} + +void +UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway) +{ + // KH mod to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ + // Now store to private var _mac_address + //uint8_t _mac_address[6] ={0,}; + memcpy(_mac_address, mac, sizeof(_mac_address)); + ////// + +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln( + F("UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway) DEBUG_V3:Function started")); +#endif + IPAddress subnet(255, 255, 255, 0); + begin(mac, ip, dns, gateway, subnet); +} + +void +UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) +{ + // KH mod to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ + // Now store to private var _mac_address + //uint8_t _mac_address[6] ={0,}; + memcpy(_mac_address, mac, sizeof(_mac_address)); + ////// + +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln( + F("UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) DEBUG_V3:Function started")); +#endif + netInit(mac); + configure(ip, dns, gateway, subnet); +} + +int UIPEthernetClass::maintain() +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("UIPEthernetClass::maintain() DEBUG_V3:Function started")); +#endif + tick(); + int rc = DHCP_CHECK_NONE; +#if UIP_UDP + + if (_dhcp != NULL) + { + //we have a pointer to dhcp, use it + rc = _dhcp->checkLease(); + + switch ( rc ) + { + case DHCP_CHECK_NONE: + //nothing done + break; + + case DHCP_CHECK_RENEW_OK: + case DHCP_CHECK_REBIND_OK: + //we might have got a new IP. + configure(_dhcp->getLocalIp(), _dhcp->getDnsServerIp(), _dhcp->getGatewayIp(), _dhcp->getSubnetMask()); + break; + + default: + //this is actually a error, it will retry though + break; + } + } + + return rc; +#endif +} + +EthernetLinkStatus UIPEthernetClass::linkStatus() +{ + if (!Enc28J60.geterevid()) + return Unknown; + + return Enc28J60.linkStatus() ? LinkON : LinkOFF; +} + +IPAddress UIPEthernetClass::localIP() +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("UIPEthernetClass::localIP() DEBUG_V3:Function started")); +#endif + IPAddress ret; + uip_ipaddr_t a; + uip_gethostaddr(a); + return ip_addr_uip(a); +} + +IPAddress UIPEthernetClass::subnetMask() +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("UIPEthernetClass::subnetMask() DEBUG_V3:Function started")); +#endif + IPAddress ret; + uip_ipaddr_t a; + uip_getnetmask(a); + return ip_addr_uip(a); +} + +IPAddress UIPEthernetClass::gatewayIP() +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("UIPEthernetClass::gatewayIP() DEBUG_V3:Function started")); +#endif + IPAddress ret; + uip_ipaddr_t a; + uip_getdraddr(a); + return ip_addr_uip(a); +} + +IPAddress UIPEthernetClass::dnsServerIP() +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("UIPEthernetClass::dnsServerIP() DEBUG_V3:Function started")); +#endif + return _dnsServerAddress; +} + +void +UIPEthernetClass::tick() +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("UIPEthernetClass::tick() DEBUG_V3:Function started")); +#endif + + if (Enc28J60Network::geterevid() == 0) + { +#if ACTLOGLEVEL>=LOG_ERR + LogObject.uart_send_strln( + F("UIPEthernetClass::tick() ERROR:EREVID=0 -> Not found ENC28j60 device !! Function ended !!")); +#endif + return; + } + +#if defined(ESP8266) + wdt_reset(); +#endif + + if (in_packet == NOBLOCK) + { + in_packet = Enc28J60Network::receivePacket(); +#if ACTLOGLEVEL>=LOG_DEBUG + + if (in_packet != NOBLOCK) + { + LogObject.uart_send_str(F("UIPEthernetClass::tick() DEBUG:receivePacket: ")); + LogObject.uart_send_decln(in_packet); + } + +#endif + } + + if (in_packet != NOBLOCK) + { + packetstate = UIPETHERNET_FREEPACKET; + uip_len = Enc28J60Network::blockSize(in_packet); + + if (uip_len > 0) + { + Enc28J60Network::readPacket(in_packet, 0, (uint8_t*)uip_buf, UIP_BUFSIZE); + + if (ETH_HDR ->type == HTONS(UIP_ETHTYPE_IP)) + { + uip_packet = in_packet; //required for upper_layer_checksum of in_packet! +#if ACTLOGLEVEL>=LOG_DEBUG + LogObject.uart_send_str(F("UIPEthernetClass::tick() DEBUG:readPacket type IP, uip_len: ")); + LogObject.uart_send_decln(uip_len); +#endif + uip_arp_ipin(); + uip_input(); + + if (uip_len > 0) + { + uip_arp_out(); + network_send(); + } + } + else if (ETH_HDR ->type == HTONS(UIP_ETHTYPE_ARP)) + { +#if ACTLOGLEVEL>=LOG_DEBUG + LogObject.uart_send_str(F("UIPEthernetClass::tick() DEBUG:readPacket type ARP, uip_len: ")); + LogObject.uart_send_decln(uip_len); +#endif + uip_arp_arpin(); + + if (uip_len > 0) + { + network_send(); + } + } + } + + if (in_packet != NOBLOCK && (packetstate & UIPETHERNET_FREEPACKET)) + { +#if ACTLOGLEVEL>=LOG_DEBUG + LogObject.uart_send_str(F("UIPEthernetClass::tick() DEBUG:freeing packet: ")); + LogObject.uart_send_decln(in_packet); +#endif + Enc28J60Network::freePacket(); + in_packet = NOBLOCK; + } + } + + unsigned long now = millis(); + +#if UIP_CLIENT_TIMER >= 0 + bool periodic = (long)( now - periodic_timer ) >= 0; + + for (int i = 0; i < UIP_CONNS; i++) + { +#else + + if ((long)( now - periodic_timer ) >= 0) + { + periodic_timer = now + UIP_PERIODIC_TIMER; + + for (int i = 0; i < UIP_CONNS; i++) + { +#endif + + uip_conn = &uip_conns[i]; + +#if UIP_CLIENT_TIMER >= 0 + + if (periodic) + { +#endif + + uip_process(UIP_TIMER); + +#if UIP_CLIENT_TIMER >= 0 + } + else + { + if (uip_conn != NULL) + { + if (((uip_userdata_t*)uip_conn->appstate) != NULL) + { + if ((long)( now - ((uip_userdata_t*)uip_conn->appstate)->timer) >= 0) + { + uip_process(UIP_POLL_REQUEST); + } + else + { + continue; + } + } + else + { +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("UIPEthernetClass::tick() DEBUG_V3:((uip_userdata_t*)uip_conn->appstate) is NULL")); +#endif + + if ((long)( now - ((uip_userdata_t*)uip_conn)->timer) >= 0) + { + uip_process(UIP_POLL_REQUEST); + } + else + { + continue; + } + } + } + else + { +#if ACTLOGLEVEL>=LOG_ERR + LogObject.uart_send_strln(F("UIPEthernetClass::tick() ERROR:uip_conn is NULL")); +#endif + continue; + } + } + +#endif + + // If the above function invocation resulted in data that + // should be sent out on the Enc28J60Network, the global variable + // uip_len is set to a value > 0. + if (uip_len > 0) + { + uip_arp_out(); + network_send(); + } + } + +#if UIP_CLIENT_TIMER >= 0 + + if (periodic) + { + periodic_timer = now + UIP_PERIODIC_TIMER; +#endif +#if UIP_UDP + + for (int i = 0; i < UIP_UDP_CONNS; i++) + { + uip_udp_periodic(i); + + // If the above function invocation resulted in data that + // should be sent out on the Enc28J60Network, the global variable + // uip_len is set to a value > 0. */ + if (uip_len > 0) + { + UIPUDP::_send((uip_udp_userdata_t *)(uip_udp_conns[i].appstate)); + } + } + +#endif /* UIP_UDP */ + } +} + +bool UIPEthernetClass::network_send() +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("UIPEthernetClass::network_send() DEBUG_V3:Function started")); +#endif + + if (packetstate & UIPETHERNET_SENDPACKET) + { +#if ACTLOGLEVEL>=LOG_DEBUG + LogObject.uart_send_str(F("UIPEthernetClass::network_send() DEBUG:uip_packet: ")); + LogObject.uart_send_dec(uip_packet); + LogObject.uart_send_str(F(", hdrlen: ")); + LogObject.uart_send_decln(uip_hdrlen); +#endif + Enc28J60Network::writePacket(uip_packet, 0, uip_buf, uip_hdrlen); + packetstate &= ~ UIPETHERNET_SENDPACKET; + goto sendandfree; + } + + uip_packet = Enc28J60Network::allocBlock(uip_len); + + if (uip_packet != NOBLOCK) + { +#if ACTLOGLEVEL>=LOG_DEBUG + LogObject.uart_send_str(F("UIPEthernetClass::network_send() DEBUG:uip_buf (uip_len): ")); + LogObject.uart_send_dec(uip_len); + LogObject.uart_send_str(F(", packet: ")); + LogObject.uart_send_decln(uip_packet); +#endif + Enc28J60Network::writePacket(uip_packet, 0, uip_buf, uip_len); + goto sendandfree; + } + + return false; +sendandfree: + Enc28J60Network::sendPacket(uip_packet); + Enc28J60Network::freeBlock(uip_packet); + uip_packet = NOBLOCK; + return true; +} + +void UIPEthernetClass::netInit(const uint8_t* mac) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("UIPEthernetClass::netInit(const uint8_t* mac) DEBUG_V3:Function started")); +#endif + periodic_timer = millis() + UIP_PERIODIC_TIMER; + + Enc28J60Network::init((uint8_t*)mac); + uip_seteth_addr(mac); + + uip_init(); + uip_arp_init(); +} + +void UIPEthernetClass::configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln( + F("UIPEthernetClass::configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) DEBUG_V3:Function started")); +#endif + uip_ipaddr_t ipaddr; + + uip_ip_addr(ipaddr, ip); + uip_sethostaddr(ipaddr); + + uip_ip_addr(ipaddr, gateway); + uip_setdraddr(ipaddr); + + uip_ip_addr(ipaddr, subnet); + uip_setnetmask(ipaddr); + + _dnsServerAddress = dns; +} + +UIPEthernetClass UIPEthernet; + +/*---------------------------------------------------------------------------*/ +uint16_t +UIPEthernetClass::chksum(uint16_t sum, const uint8_t *data, uint16_t len) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln( + F("UIPEthernetClass::chksum(uint16_t sum, const uint8_t *data, uint16_t len) DEBUG_V3:Function started")); +#endif + uint16_t t; + const uint8_t *dataptr; + const uint8_t *last_byte; + + dataptr = data; + last_byte = data + len - 1; + + while (dataptr < last_byte) /* At least two more bytes */ + { + t = (dataptr[0] << 8) + dataptr[1]; + sum += t; + + if (sum < t) + { + sum++; /* carry */ + } + + dataptr += 2; + } + + if (dataptr == last_byte) + { + t = (dataptr[0] << 8) + 0; + sum += t; + + if (sum < t) + { + sum++; /* carry */ + } + } + + /* Return sum in host byte order. */ + return sum; +} + +/*---------------------------------------------------------------------------*/ + +uint16_t +UIPEthernetClass::ipchksum(void) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("UIPEthernetClass::ipchksum(void) DEBUG_V3:Function started")); +#endif + uint16_t sum; + + sum = chksum(0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN); + return (sum == 0) ? 0xffff : htons(sum); +} + +/*---------------------------------------------------------------------------*/ +uint16_t +#if UIP_UDP +UIPEthernetClass::upper_layer_chksum(uint8_t proto) +#else +uip_tcpchksum(void) +#endif +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 +#if UIP_UDP + LogObject.uart_send_strln(F("UIPEthernetClass::upper_layer_chksum(uint8_t proto) DEBUG_V3:Function started")); +#else + LogObject.uart_send_strln(F("uip_tcpchksum(void) INFO:Function started")); +#endif +#endif + uint16_t upper_layer_len; + uint16_t sum; + +#if UIP_CONF_IPV6 + upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]); +#else /* UIP_CONF_IPV6 */ + upper_layer_len = (((u16_t)(BUF->len[0]) << 8) + BUF->len[1]) - UIP_IPH_LEN; +#endif /* UIP_CONF_IPV6 */ + + /* First sum pseudoheader. */ + + /* IP protocol and length fields. This addition cannot carry. */ +#if UIP_UDP + sum = upper_layer_len + proto; +#else + sum = upper_layer_len + UIP_PROTO_TCP; +#endif + /* Sum IP source and destination addresses. */ + sum = UIPEthernetClass::chksum(sum, (u8_t *)&BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t)); + + uint8_t upper_layer_memlen; +#if UIP_UDP + + switch (proto) + { + // case UIP_PROTO_ICMP: + // case UIP_PROTO_ICMP6: + // upper_layer_memlen = upper_layer_len; + // break; + case UIP_PROTO_UDP: + upper_layer_memlen = UIP_UDPH_LEN; + break; + + default: + // case UIP_PROTO_TCP: +#endif + upper_layer_memlen = (BUF->tcpoffset >> 4) << 2; +#if UIP_UDP + break; + } + +#endif + sum = UIPEthernetClass::chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], upper_layer_memlen); +#if ACTLOGLEVEL>=LOG_DEBUG +#if UIP_UDP + LogObject.uart_send_str(F("UIPEthernetClass::upper_layer_chksum(uint8_t proto) DEBUG:uip_buf[")); +#else + LogObject.uart_send_str(F("uip_tcpchksum(void) DEBUG:uip_buf[")); +#endif + LogObject.uart_send_dec(UIP_IPH_LEN + UIP_LLH_LEN); + LogObject.uart_send_str(F("-")); + LogObject.uart_send_dec(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen); + LogObject.uart_send_str(F("]: ")); + LogObject.uart_send_hexln(htons(sum)); +#endif + + if (upper_layer_memlen < upper_layer_len) + { + sum = Enc28J60Network::chksum( + sum, + UIPEthernetClass::uip_packet, + UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen, + upper_layer_len - upper_layer_memlen + ); +#if ACTLOGLEVEL>=LOG_DEBUG +#if UIP_UDP + LogObject.uart_send_str(F("UIPEthernetClass::upper_layer_chksum(uint8_t proto) DEBUG:uip_packet(")); +#else + LogObject.uart_send_str(F("uip_tcpchksum(void) DEBUG:uip_packet(")); +#endif + LogObject.uart_send_dec(UIPEthernetClass::uip_packet); + LogObject.uart_send_str(F(")[")); + LogObject.uart_send_dec(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen); + LogObject.uart_send_str(F("-")); + LogObject.uart_send_dec(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_len); + LogObject.uart_send_str(F("]: ")); + LogObject.uart_send_hexln(htons(sum)); +#endif + } + + return (sum == 0) ? 0xffff : htons(sum); +} + +uint16_t +uip_ipchksum(void) +{ + return UIPEthernet.ipchksum(); +} + +#if UIP_UDP +uint16_t +uip_tcpchksum(void) +{ + uint16_t sum = UIPEthernet.upper_layer_chksum(UIP_PROTO_TCP); + return sum; +} + +uint16_t +uip_udpchksum(void) +{ + uint16_t sum = UIPEthernet.upper_layer_chksum(UIP_PROTO_UDP); + return sum; +} +#endif diff --git a/LibraryPatches/UIPEthernet/UIPEthernet.h b/LibraryPatches/UIPEthernet/UIPEthernet.h index d02e538..62dc44c 100644 --- a/LibraryPatches/UIPEthernet/UIPEthernet.h +++ b/LibraryPatches/UIPEthernet/UIPEthernet.h @@ -1,158 +1,159 @@ -/* - UIPEthernet.h - Arduino implementation of a uIP wrapper class. - Copyright (c) 2013 Norbert Truchsess - All rights reserved. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -#ifndef UIPETHERNET_H -#define UIPETHERNET_H - -#include "ethernet_comp.h" -#if defined(__MBED__) - #include -#endif -#if defined(ARDUINO) - #include - #if defined(__STM32F3__) || defined(STM32F3) || defined(__RFduino__) - #include "mbed/IPAddress.h" - #else - #include "IPAddress.h" - #endif -#endif -#include "utility/Enc28J60Network.h" -#include "utility/uipopt.h" -#include "Dhcp.h" -#if UIP_UDP - #include "UIPUdp.h" -#endif -#include "UIPClient.h" -#include "UIPServer.h" - -extern "C" -{ -#include "utility/uip_timer.h" -#include "utility/uip.h" -} - -#define UIPETHERNET_FREEPACKET 1 -#define UIPETHERNET_SENDPACKET 2 -#define UIPETHERNET_BUFFERREAD 4 - -#define uip_ip_addr(addr, ip) do { \ - ((u16_t *)(addr))[0] = HTONS(((ip[0]) << 8) | (ip[1])); \ - ((u16_t *)(addr))[1] = HTONS(((ip[2]) << 8) | (ip[3])); \ - } while(0) - -#define ip_addr_uip(a) IPAddress(a[0] & 0xFF, a[0] >> 8 , a[1] & 0xFF, a[1] >> 8) //TODO this is not IPV6 capable - -#define uip_seteth_addr(eaddr) do {uip_ethaddr.addr[0] = eaddr[0]; \ - uip_ethaddr.addr[1] = eaddr[1];\ - uip_ethaddr.addr[2] = eaddr[2];\ - uip_ethaddr.addr[3] = eaddr[3];\ - uip_ethaddr.addr[4] = eaddr[4];\ - uip_ethaddr.addr[5] = eaddr[5];} while(0) - -#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) - -enum EthernetLinkStatus { - Unknown, - LinkON, - LinkOFF -}; - -class UIPEthernetClass -{ -public: - UIPEthernetClass(); - - void init(const uint8_t pin); - - int begin(const uint8_t* mac); - void begin(const uint8_t* mac, IPAddress ip); - void begin(const uint8_t* mac, IPAddress ip, IPAddress dns); - void begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway); - void begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet); - - // maintain() must be called at regular intervals to process the incoming serial - // data and issue IP events to the sketch. It does not return until all IP - // events have been processed. Renews dhcp-lease if required. - int maintain(); - - EthernetLinkStatus linkStatus(); - - // KH add to have similar function to Ethernet lib - // Certainly we can use void macAddress(uint8_t mac[]) to read from W5x00. - void MACAddress(uint8_t *mac_address) - { - memcpy(mac_address, _mac_address, sizeof(_mac_address)); - } - ////// - - IPAddress localIP(); - IPAddress subnetMask(); - IPAddress gatewayIP(); - IPAddress dnsServerIP(); - -private: - - // KH add to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ - uint8_t _mac_address[6] ={0,}; - ////// - - static memhandle in_packet; - static memhandle uip_packet; - static uint8_t uip_hdrlen; - static uint8_t packetstate; - - static IPAddress _dnsServerAddress; - #if UIP_UDP - static DhcpClass* _dhcp; - #endif - static unsigned long periodic_timer; - - static void netInit(const uint8_t* mac); - static void configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet); - - static void tick(); - - static bool network_send(); - - friend class UIPServer; - - friend class UIPClient; - - friend class UIPUDP; - - static uint16_t chksum(uint16_t sum, const uint8_t* data, uint16_t len); - static uint16_t ipchksum(void); -#if UIP_UDP - static uint16_t upper_layer_chksum(uint8_t proto); -#endif - friend uint16_t uip_ipchksum(void); - friend uint16_t uip_tcpchksum(void); - friend uint16_t uip_udpchksum(void); - - friend void uipclient_appcall(void); - friend void uipudp_appcall(void); - -#if UIP_CONF_IPV6 - uint16_t uip_icmp6chksum(void); -#endif /* UIP_CONF_IPV6 */ -}; - -extern UIPEthernetClass UIPEthernet; - -#endif +/* + UIPEthernet.h - Arduino implementation of a uIP wrapper class. + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef UIPETHERNET_H +#define UIPETHERNET_H + +#include "ethernet_comp.h" +#if defined(__MBED__) + #include +#endif +#if defined(ARDUINO) + #include + #if defined(__STM32F3__) || defined(STM32F3) || defined(__RFduino__) + #include "mbed/IPAddress.h" + #else + #include "IPAddress.h" + #endif +#endif +#include "utility/Enc28J60Network.h" +#include "utility/uipopt.h" +#include "Dhcp.h" +#if UIP_UDP + #include "UIPUdp.h" +#endif +#include "UIPClient.h" +#include "UIPServer.h" + +extern "C" +{ +#include "utility/uip_timer.h" +#include "utility/uip.h" +} + +#define UIPETHERNET_FREEPACKET 1 +#define UIPETHERNET_SENDPACKET 2 +#define UIPETHERNET_BUFFERREAD 4 + +#define uip_ip_addr(addr, ip) do { \ + ((u16_t *)(addr))[0] = HTONS(((ip[0]) << 8) | (ip[1])); \ + ((u16_t *)(addr))[1] = HTONS(((ip[2]) << 8) | (ip[3])); \ + } while(0) + +#define ip_addr_uip(a) IPAddress(a[0] & 0xFF, a[0] >> 8 , a[1] & 0xFF, a[1] >> 8) //TODO this is not IPV6 capable + +#define uip_seteth_addr(eaddr) do {uip_ethaddr.addr[0] = eaddr[0]; \ + uip_ethaddr.addr[1] = eaddr[1];\ + uip_ethaddr.addr[2] = eaddr[2];\ + uip_ethaddr.addr[3] = eaddr[3];\ + uip_ethaddr.addr[4] = eaddr[4];\ + uip_ethaddr.addr[5] = eaddr[5];} while(0) + +#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) + +enum EthernetLinkStatus +{ + Unknown, + LinkON, + LinkOFF +}; + +class UIPEthernetClass +{ + public: + UIPEthernetClass(); + + void init(const uint8_t pin); + + int begin(const uint8_t* mac); + void begin(const uint8_t* mac, IPAddress ip); + void begin(const uint8_t* mac, IPAddress ip, IPAddress dns); + void begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway); + void begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet); + + // maintain() must be called at regular intervals to process the incoming serial + // data and issue IP events to the sketch. It does not return until all IP + // events have been processed. Renews dhcp-lease if required. + int maintain(); + + EthernetLinkStatus linkStatus(); + + // KH add to have similar function to Ethernet lib + // Certainly we can use void macAddress(uint8_t mac[]) to read from W5x00. + void MACAddress(uint8_t *mac_address) + { + memcpy(mac_address, _mac_address, sizeof(_mac_address)); + } + ////// + + IPAddress localIP(); + IPAddress subnetMask(); + IPAddress gatewayIP(); + IPAddress dnsServerIP(); + + private: + + // KH add to work with new func void MACAddress(uint8_t *mac_address); and SinricPro v2.5.1+ + uint8_t _mac_address[6] = {0,}; + ////// + + static memhandle in_packet; + static memhandle uip_packet; + static uint8_t uip_hdrlen; + static uint8_t packetstate; + + static IPAddress _dnsServerAddress; +#if UIP_UDP + static DhcpClass* _dhcp; +#endif + static unsigned long periodic_timer; + + static void netInit(const uint8_t* mac); + static void configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet); + + static void tick(); + + static bool network_send(); + + friend class UIPServer; + + friend class UIPClient; + + friend class UIPUDP; + + static uint16_t chksum(uint16_t sum, const uint8_t* data, uint16_t len); + static uint16_t ipchksum(void); +#if UIP_UDP + static uint16_t upper_layer_chksum(uint8_t proto); +#endif + friend uint16_t uip_ipchksum(void); + friend uint16_t uip_tcpchksum(void); + friend uint16_t uip_udpchksum(void); + + friend void uipclient_appcall(void); + friend void uipudp_appcall(void); + +#if UIP_CONF_IPV6 + uint16_t uip_icmp6chksum(void); +#endif /* UIP_CONF_IPV6 */ +}; + +extern UIPEthernetClass UIPEthernet; + +#endif diff --git a/LibraryPatches/UIPEthernet/utility/Enc28J60Network.cpp b/LibraryPatches/UIPEthernet/utility/Enc28J60Network.cpp index a280225..a4d5d1b 100644 --- a/LibraryPatches/UIPEthernet/utility/Enc28J60Network.cpp +++ b/LibraryPatches/UIPEthernet/utility/Enc28J60Network.cpp @@ -1,1244 +1,1336 @@ -/* - Enc28J60NetworkClass.h - UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface. - - Copyright (c) 2013 Norbert Truchsess - All rights reserved. - - based on enc28j60.c file from the AVRlib library by Pascal Stang. - For AVRlib See http://www.procyonengineering.com/ - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - - -#include "Enc28J60Network.h" -#if defined(ARDUINO) - #include "Arduino.h" -#endif -#if defined(__MBED__) - #include - #include "mbed/millis.h" - #define delay(x) wait_ms(x) -#endif -#include "logging.h" - -// KH, For nRF52 -//#define ENC28J60_USE_SPILIB true - -uint8_t ENC28J60ControlCS = ENC28J60_CONTROL_CS; - -#if ENC28J60_USE_SPILIB - #if defined(ARDUINO) - #if defined(STM32F2) - #include - #elif !defined(STM32F3) && !defined(__STM32F4__) - #include - extern SPIClass SPI; - //#elif defined(ARDUINO_ARCH_AMEBA) - //SPIClass SPI((void *)(&spi_obj), 11, 12, 13, 10); - //SPI _spi(SPI_MOSI,SPI_MISO,SPI_SCK,ENC28J60ControlCS); - #else - #include "HardwareSPI.h" - extern HardwareSPI SPI(1); - #endif - #endif - #if defined(__MBED__) - SPI _spi(SPI_MOSI,SPI_MISO,SPI_SCK); - DigitalOut _cs(ENC28J60ControlCS); - Serial LogObject(SERIAL_TX,SERIAL_RX); - #endif -#endif - -extern "C" { - #if defined(ARDUINO_ARCH_AVR) - // AVR-specific code - #include - #elif defined(ARDUINO_ARCH_SAM) - // SAM-specific code - #elif defined(ARDUINO_ARCH_SAMD) - // SAMD-specific code - #else - // generic, non-platform specific code - #endif -#include "enc28j60.h" -#include "uip.h" -} - -#if defined(ARDUINO) - // set CS to 0 = active - #define CSACTIVE digitalWrite(ENC28J60ControlCS, LOW) - // set CS to 1 = passive - #define CSPASSIVE digitalWrite(ENC28J60ControlCS, HIGH) -#endif -#if defined(__MBED__) - // set CS to 0 = active - #define CSACTIVE _cs=0 - // set CS to 1 = passive - #define CSPASSIVE _cs=1 -#endif - -// -#if defined(ARDUINO_ARCH_AVR) -#define waitspi() while(!(SPSR&(1<=LOG_DEBUG - LogObject.uart_send_str(F("ENC28J60::init DEBUG:csPin = ")); - LogObject.uart_send_decln(ENC28J60ControlCS); - LogObject.uart_send_str(F("ENC28J60::init DEBUG:miso = ")); - LogObject.uart_send_decln(SPI_MISO); - LogObject.uart_send_str(F("ENC28J60::init DEBUG:mosi = ")); - LogObject.uart_send_decln(SPI_MOSI); - LogObject.uart_send_str(F("ENC28J60::init DEBUG:sck = ")); - LogObject.uart_send_decln(SPI_SCK); - #endif -#if ENC28J60_USE_SPILIB - #if ACTLOGLEVEL>=LOG_DEBUG - LogObject.uart_send_strln(F("ENC28J60::init DEBUG:Use SPI lib SPI.begin()")); - #endif - #if defined(ARDUINO) - #if defined(__STM32F3__) || defined(STM32F3) || defined(__STM32F4__) - SPI.begin(SPI_9MHZ, MSBFIRST, 0); - #else - SPI.begin(); - #endif - #endif - #if defined(ARDUINO_ARCH_AVR) - // AVR-specific code - SPI.setClockDivider(SPI_CLOCK_DIV2); //results in 8MHZ at 16MHZ system clock. - #elif defined(ARDUINO_ARCH_SAM) - // SAM-specific code - SPI.setClockDivider(10); //defaults to 21 which results in aprox. 4MHZ. A 10 should result in a little more than 8MHZ. - #elif defined(ARDUINO_ARCH_SAMD) - // SAMD-specific code - // Should we set clock divider? - SPI.setClockDivider(10); - #elif defined(__STM32F1__) || defined(__STM32F3__) - // generic, non-platform specific code - #define USE_STM32F1_DMAC 1 //on STM32 - // BOARD_NR_SPI >= 1 BOARD_SPI1_NSS_PIN, BOARD_SPI1_SCK_PIN, BOARD_SPI1_MISO_PIN, BOARD_SPI1_MOSI_PIN - SPI.setBitOrder(MSBFIRST); - SPI.setDataMode(SPI_MODE0); - SPI.setClockDivider(SPI_CLOCK_DIV8); //value 8 the result is 9MHz at 72MHz clock. - #else - #if defined(ARDUINO) - #if !defined(__STM32F3__) && !defined(STM32F3) && !defined(__STM32F4__) - SPI.setBitOrder(MSBFIRST); - #endif - //Settings for ESP8266 - //SPI.setDataMode(SPI_MODE0); - //SPI.setClockDivider(SPI_CLOCK_DIV16); - #endif - #if defined(__MBED__) - _spi.format(8, 0); // 8bit, mode 0 - _spi.frequency(7000000); // 7MHz - #endif - #endif -#else - #if ACTLOGLEVEL>=LOG_DEBUG - LogObject.uart_send_strln(F("ENC28J60::init DEBUG:Use Native hardware SPI")); - #endif - pinMode(SPI_MOSI, OUTPUT); - pinMode(SPI_SCK, OUTPUT); - pinMode(SPI_MISO, INPUT); - //Hardware SS must be configured as OUTPUT to enable SPI-master (regardless of which pin is configured as ENC28J60ControlCS) - pinMode(SS, OUTPUT); - digitalWrite(SS,HIGH); - - digitalWrite(SPI_MOSI, LOW); - digitalWrite(SPI_SCK, LOW); - - // initialize SPI interface - // master mode and Fosc/2 clock: - SPCR = (1<=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:Before readOp(ENC28J60_READ_CTRL_REG, ESTAT)")); - #endif - nextPacketPtr = RXSTART_INIT; - while ((!readOp(ENC28J60_READ_CTRL_REG, ESTAT) & ESTAT_CLKRDY) && (timeout>0)) - { - timeout=timeout-1; - delay(10); - #if defined(ESP8266) - wdt_reset(); - #endif - } - #if ACTLOGLEVEL>=LOG_ERR - if (timeout==0) {LogObject.uart_send_strln(F("ENC28J60::init ERROR:TIMEOUT !!"));} - #endif - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:After readOp(ENC28J60_READ_CTRL_REG, ESTAT)")); - #endif - // Rx start - writeRegPair(ERXSTL, RXSTART_INIT); - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:After writeRegPair(ERXSTL, RXSTART_INIT)")); - #endif - // set receive pointer address - writeRegPair(ERXRDPTL, RXSTART_INIT); - // RX end - writeRegPair(ERXNDL, RXSTOP_INIT); - // TX start - //writeRegPair(ETXSTL, TXSTART_INIT); - // TX end - //writeRegPair(ETXNDL, TXSTOP_INIT); - // do bank 1 stuff, packet filter: - // For broadcast packets we allow only ARP packtets - // All other packets should be unicast only for our mac (MAADR) - // - // The pattern to match on is therefore - // Type ETH.DST - // ARP BROADCAST - // 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9 - // in binary these poitions are:11 0000 0011 1111 - // This is hex 303F->EPMM0=0x3f,EPMM1=0x30 - //TODO define specific pattern to receive dhcp-broadcast packages instead of setting ERFCON_BCEN! -// enableBroadcast(); // change to add ERXFCON_BCEN recommended by epam - writeReg(ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN|ERXFCON_BCEN); - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:After writeReg(ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN|ERXFCON_BCEN)")); - #endif - #if defined(ESP8266) - wdt_reset(); - #endif - writeRegPair(EPMM0, 0x303f); - writeRegPair(EPMCSL, 0xf7f9); - // - // - // do bank 2 stuff - // enable MAC receive - // and bring MAC out of reset (writes 0x00 to MACON2) - writeRegPair(MACON1, MACON1_MARXEN|MACON1_TXPAUS|MACON1_RXPAUS); - // enable automatic padding to 60bytes and CRC operations - writeOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN); - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:After writeOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN)")); - #endif - // set inter-frame gap (non-back-to-back) - writeRegPair(MAIPGL, 0x0C12); - // set inter-frame gap (back-to-back) - writeReg(MABBIPG, 0x12); - // Set the maximum packet size which the controller will accept - // Do not send packets longer than MAX_FRAMELEN: - writeRegPair(MAMXFLL, MAX_FRAMELEN); - // do bank 3 stuff - // write MAC address - // NOTE: MAC address in ENC28J60 is byte-backward - writeReg(MAADR5, macaddr[0]); - writeReg(MAADR4, macaddr[1]); - writeReg(MAADR3, macaddr[2]); - writeReg(MAADR2, macaddr[3]); - writeReg(MAADR1, macaddr[4]); - writeReg(MAADR0, macaddr[5]); - // no loopback of transmitted frames - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:Before phyWrite(PHCON2, PHCON2_HDLDIS)")); - #endif - phyWrite(PHCON2, PHCON2_HDLDIS); - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:After phyWrite(PHCON2, PHCON2_HDLDIS)")); - #endif - // switch to bank 0 - setBank(ECON1); - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:After setBank(ECON1)")); - #endif - // enable interrutps - writeOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE); - // enable packet reception - writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); - //Configure leds - phyWrite(PHLCON,0x476); - - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:Before readReg(EREVID);")); - #endif - erevid=readReg(EREVID); - if (erevid==0xFF) {erevid=0;} - // microchip forgot to step the number on the silcon when they - // released the revision B7. 6 is now rev B7. We still have - // to see what they do when they release B8. At the moment - // there is no B8 out yet - //if (erevid > 5) ++erevid; - #if ACTLOGLEVEL>=LOG_INFO - LogObject.uart_send_str(F("ENC28J60::init INFO: Chip erevid=")); - LogObject.uart_send_dec(erevid); - LogObject.uart_send_strln(F(" initialization completed.")); - #endif - -// return Enc28J60Network::erevid; -} - -memhandle -Enc28J60Network::receivePacket(void) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::receivePacket(void) DEBUG_V3:Function started")); - #endif - #if defined(ESP8266) - wdt_reset(); - #endif - uint8_t rxstat; - uint16_t len; - // check if a packet has been received and buffered - //if( !(readReg(EIR) & EIR_PKTIF) ){ - // The above does not work. See Rev. B4 Silicon Errata point 6. - #if ACTLOGLEVEL>=LOG_ERR - if (erevid==0) - { - LogObject.uart_send_strln(F("Enc28J60Network::receivePacket(void) ERROR:ENC28j50 Device not found !! Bypass receivePacket function !!")); - } - #endif - uint8_t epktcnt=readReg(EPKTCNT); - if ((erevid!=0) && (epktcnt!=0)) - { - uint16_t readPtr = nextPacketPtr+6 > RXSTOP_INIT ? nextPacketPtr+6-RXSTOP_INIT+RXSTART_INIT : nextPacketPtr+6; - // Set the read pointer to the start of the received packet - writeRegPair(ERDPTL, nextPacketPtr); - // read the next packet pointer - nextPacketPtr = readOp(ENC28J60_READ_BUF_MEM, 0); - nextPacketPtr |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; - // read the packet length (see datasheet page 43) - len = readOp(ENC28J60_READ_BUF_MEM, 0); - len |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; - len -= 4; //remove the CRC count - // read the receive status (see datasheet page 43) - rxstat = readOp(ENC28J60_READ_BUF_MEM, 0); - //rxstat |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; - #if ACTLOGLEVEL>=LOG_DEBUG - LogObject.uart_send_str(F("Enc28J60Network::receivePacket(void) DEBUG:receivePacket [")); - LogObject.uart_send_hex(readPtr); - LogObject.uart_send_str(F("-")); - LogObject.uart_send_hex((readPtr+len) % (RXSTOP_INIT+1)); - LogObject.uart_send_str(F("], next: ")); - LogObject.uart_send_hex(nextPacketPtr); - LogObject.uart_send_str(F(", stat: ")); - LogObject.uart_send_hex(rxstat); - LogObject.uart_send_str(F(", Packet count: ")); - LogObject.uart_send_dec(epktcnt); - LogObject.uart_send_str(F(" -> ")); - LogObject.uart_send_strln((rxstat & 0x80)!=0 ? "OK" : "failed"); - #endif - // decrement the packet counter indicate we are done with this packet - writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC); - // check CRC and symbol errors (see datasheet page 44, table 7-3): - // The ERXFCON.CRCEN is set by default. Normally we should not - // need to check this. - if (((rxstat & 0x80) != 0) && (nextPacketPtr<=RXSTOP_INIT)) - { - receivePkt.begin = readPtr; - receivePkt.size = len; - #if ACTLOGLEVEL>=LOG_DEBUG - LogObject.uart_send_str(F("Enc28J60Network::receivePacket(void) DEBUG: rxstat OK. receivePkt.size=")); - LogObject.uart_send_decln(len); - #endif - return UIP_RECEIVEBUFFERHANDLE; - } - // Move the RX read pointer to the start of the next received packet - // This frees the memory we just read out - setERXRDPT(); - } - return (NOBLOCK); -} - -void -Enc28J60Network::setERXRDPT(void) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::setERXRDPT(void) DEBUG_V3:Function started")); - #endif - // Make sure the value is odd. See Rev. B1,B4,B5,B7 Silicon Errata issues 14 - uint16_t actnextPacketPtr = nextPacketPtr == RXSTART_INIT ? RXSTOP_INIT : nextPacketPtr-1; - #if ACTLOGLEVEL>=LOG_DEBUG - LogObject.uart_send_str(F("Enc28J60Network::setERXRDPT(void) DEBUG:Set actnextPacketPtr:")); - LogObject.uart_send_hexln(actnextPacketPtr); - #endif - // datasheet: The ENC28J60 will always write up to, but not including - writeRegPair(ERXRDPTL, actnextPacketPtr); -} - -memaddress -Enc28J60Network::blockSize(memhandle handle) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::blockSize(memhandle handle) DEBUG_V3:Function started")); - #endif - return ((handle == NOBLOCK) || (erevid==0)) ? 0 : handle == UIP_RECEIVEBUFFERHANDLE ? receivePkt.size : blocks[handle].size; -} - -void -Enc28J60Network::sendPacket(memhandle handle) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::sendPacket(memhandle handle) INFO:Function started")); - #endif - #if defined(ESP8266) - wdt_reset(); - #endif - if (erevid==0) - { - #if ACTLOGLEVEL>=LOG_ERR - LogObject.uart_send_strln(F("Enc28J60Network::sendPacket(memhandle handle) ERROR:ENC28j50 Device not found !! Bypass sendPacket function !!")); - #endif - return; - } - - memblock *packet = &blocks[handle]; - uint16_t start = packet->begin-1; - uint16_t end = start + packet->size; - - // backup data at control-byte position - uint8_t data = readByte(start); - // write control-byte (if not 0 anyway) - if (data) - writeByte(start, 0); - - #if ACTLOGLEVEL>=LOG_DEBUG - LogObject.uart_send_str(F("Enc28J60Network::sendPacket(memhandle handle) DEBUG:sendPacket(")); - LogObject.uart_send_dec(handle); - LogObject.uart_send_str(F(") [")); - LogObject.uart_send_hex(start); - LogObject.uart_send_str(F("-")); - LogObject.uart_send_hex(end); - LogObject.uart_send_str(F("]: ")); - for (uint16_t i=start; i<=end; i++) - { - LogObject.uart_send_hex(readByte(i)); - LogObject.uart_send_str(F(" ")); - } - LogObject.uart_send_strln(F("")); - #endif - - // TX start - writeRegPair(ETXSTL, start); - // Set the TXND pointer to correspond to the packet size given - writeRegPair(ETXNDL, end); - // send the contents of the transmit buffer onto the network - - unsigned int retry = TX_COLLISION_RETRY_COUNT; - unsigned int timeout = 100; - do - { - // seydamir added - // Reset the transmit logic problem. See Rev. B7 Silicon Errata issues 12 and 13 - writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRST); - writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRST); - writeOp(ENC28J60_BIT_FIELD_CLR, EIR, EIR_TXERIF | EIR_TXIF); - // end - - writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS); - // Reset the transmit logic problem. See Rev. B4 Silicon Errata point 12. - //if( (readReg(EIR) & EIR_TXERIF) ) - // { - // writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS); - // } - - timeout = 100; - while (((readReg(EIR) & (EIR_TXIF | EIR_TXERIF)) == 0) && (timeout>0)) - { - timeout=timeout-1; - delay(10); - #if defined(ESP8266) - wdt_reset(); - #endif - } - if (timeout==0) - { - /* Transmit hardware probably hung, try again later. */ - /* Shouldn't happen according to errata 12 and 13. */ - writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS); - #if ACTLOGLEVEL>=LOG_WARN - LogObject.uart_send_strln(F("Enc28J60Network::sendPacket(memhandle handle) WARNING:Collision")); - #endif - retry=retry-1; - } - } while ((timeout == 0) && (retry != 0)); - - //restore data on control-byte position - if (data) - writeByte(start, data); - - if (retry == 0) - { - #if ACTLOGLEVEL>=LOG_ERROR - LogObject.uart_send_strln(F("Enc28J60Network::sendPacket(memhandle handle) ERROR:COLLISION !!")); - #endif - return; - } -} - -uint16_t -Enc28J60Network::setReadPtr(memhandle handle, memaddress position, uint16_t len) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::setReadPtr(memhandle handle, memaddress position, uint16_t len) DEBUG_V3:Function started")); - #endif - memblock *packet = handle == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[handle]; - memaddress start = handle == UIP_RECEIVEBUFFERHANDLE && packet->begin + position > RXSTOP_INIT ? packet->begin + position-RXSTOP_INIT+RXSTART_INIT : packet->begin + position; - - writeRegPair(ERDPTL, start); - - if (len > packet->size - position) - len = packet->size - position; - return len; -} - -uint16_t -Enc28J60Network::readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) DEBUG_V3:Function started")); - #endif - #if defined(ESP8266) - wdt_reset(); - #endif - len = setReadPtr(handle, position, len); - readBuffer(len, buffer); - #if ACTLOGLEVEL>=LOG_DEBUG_V2 - LogObject.uart_send_str(F("Enc28J60Network::readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) DEBUG_V2: Read bytes:")); - LogObject.uart_send_dec(len); - LogObject.uart_send_str(F(" save to block(")); - LogObject.uart_send_dec(handle); - LogObject.uart_send_str(F(") [")); - LogObject.uart_send_hex(position); - LogObject.uart_send_str(F("]: ")); - for (uint16_t i=0; i=LOG_DEBUG_V3 - LogObject.uart_send_str(F("Enc28J60Network::writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) DEBUG_V3:Function started with len:")); - LogObject.uart_send_decln(len); - #endif - #if defined(ESP8266) - wdt_reset(); - #endif - memblock *packet = &blocks[handle]; - uint16_t start = packet->begin + position; - - writeRegPair(EWRPTL, start); - - if (len > packet->size - position) - len = packet->size - position; - writeBuffer(len, buffer); - #if ACTLOGLEVEL>=LOG_DEBUG_V2 - LogObject.uart_send_str(F("Enc28J60Network::writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) DEBUG_V2: Write bytes:")); - LogObject.uart_send_dec(len); - LogObject.uart_send_str(F(" save to block(")); - LogObject.uart_send_dec(handle); - LogObject.uart_send_str(F(") [")); - LogObject.uart_send_hex(start); - LogObject.uart_send_str(F("]: ")); - for (uint16_t i=0; i=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::enableBroadcast (bool temporary) DEBUG_V3:Function started")); - #endif - writeRegByte(ERXFCON, readRegByte(ERXFCON) | ERXFCON_BCEN); - if(!temporary) - broadcast_enabled = true; -} - -void Enc28J60Network::disableBroadcast (bool temporary) { - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::disableBroadcast (bool temporary) DEBUG_V3:Function started")); - #endif - if(!temporary) - broadcast_enabled = false; - if(!broadcast_enabled) - writeRegByte(ERXFCON, readRegByte(ERXFCON) & ~ERXFCON_BCEN); -} - -void Enc28J60Network::enableMulticast (void) { - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::enableMulticast (void) DEBUG_V3:Function started")); - #endif - writeRegByte(ERXFCON, readRegByte(ERXFCON) | ERXFCON_MCEN); -} - -void Enc28J60Network::disableMulticast (void) { - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::disableMulticast (void) DEBUG_V3:Function started")); - #endif - writeRegByte(ERXFCON, readRegByte(ERXFCON) & ~ERXFCON_MCEN); -} - -uint8_t Enc28J60Network::readRegByte (uint8_t address) { - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::readRegByte (uint8_t address) DEBUG_V3:Function started")); - #endif - setBank(address); - return readOp(ENC28J60_READ_CTRL_REG, address); -} - -void Enc28J60Network::writeRegByte (uint8_t address, uint8_t data) { - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::writeRegByte (uint8_t address, uint8_t data) DEBUG_V3:Function started")); - #endif - setBank(address); - writeOp(ENC28J60_WRITE_CTRL_REG, address, data); -} - - -uint8_t Enc28J60Network::readByte(uint16_t addr) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::readByte(uint16_t addr) DEBUG_V3:Function started")); - #endif - #if defined(ESP8266) - wdt_reset(); - #endif - writeRegPair(ERDPTL, addr); - - CSACTIVE; - #if ENC28J60_USE_SPILIB - // issue read command - #if defined(ARDUINO) - SPI.transfer(ENC28J60_READ_BUF_MEM); - // read data - uint8_t c = SPI.transfer(0x00); - #endif - #if defined(__MBED__) - _spi.write(ENC28J60_READ_BUF_MEM); - // read data - uint8_t c = _spi.write(0x00); - #endif - CSPASSIVE; - return (c); - #else - // issue read command - SPDR = ENC28J60_READ_BUF_MEM; - waitspi(); - // read data - SPDR = 0x00; - waitspi(); - CSPASSIVE; - return (SPDR); - #endif -} - -void Enc28J60Network::writeByte(uint16_t addr, uint8_t data) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::writeByte(uint16_t addr, uint8_t data) DEBUG_V3:Function started")); - #endif - #if defined(ESP8266) - wdt_reset(); - #endif - writeRegPair(EWRPTL, addr); - - CSACTIVE; - #if ENC28J60_USE_SPILIB - // issue write command - #if defined(ARDUINO) - SPI.transfer(ENC28J60_WRITE_BUF_MEM); - // write data - SPI.transfer(data); - #endif - #if defined(__MBED__) - _spi.write(ENC28J60_WRITE_BUF_MEM); - // write data - _spi.write(data); - #endif - #else - // issue write command - SPDR = ENC28J60_WRITE_BUF_MEM; - waitspi(); - // write data - SPDR = data; - waitspi(); - #endif - CSPASSIVE; -} - -void -Enc28J60Network::copyPacket(memhandle dest_pkt, memaddress dest_pos, memhandle src_pkt, memaddress src_pos, uint16_t len) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::copyPacket(memhandle dest_pkt, memaddress dest_pos, memhandle src_pkt, memaddress src_pos, uint16_t len) DEBUG_V3:Function started")); - #endif - memblock *dest = &blocks[dest_pkt]; - memblock *src = src_pkt == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[src_pkt]; - memaddress start = src_pkt == UIP_RECEIVEBUFFERHANDLE && src->begin + src_pos > RXSTOP_INIT ? src->begin + src_pos-RXSTOP_INIT+RXSTART_INIT : src->begin + src_pos; - enc28J60_mempool_block_move_callback(dest->begin+dest_pos,start,len); - // setERXRDPT(); let it to freePacket after all packets are saved -} - -void -enc28J60_mempool_block_move_callback(memaddress dest, memaddress src, memaddress len) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("enc28J60_mempool_block_move_callback(memaddress dest, memaddress src, memaddress len) DEBUG_V3:Function started")); - #endif -//void -//Enc28J60Network::memblock_mv_cb(uint16_t dest, uint16_t src, uint16_t len) -//{ - //as ENC28J60 DMA is unable to copy single bytes: - if (len == 1) - { - Enc28J60Network::writeByte(dest,Enc28J60Network::readByte(src)); - } - else - { - // calculate address of last byte - len += src - 1; - - /* 1. Appropriately program the EDMAST, EDMAND - and EDMADST register pairs. The EDMAST - registers should point to the first byte to copy - from, the EDMAND registers should point to the - last byte to copy and the EDMADST registers - should point to the first byte in the destination - range. The destination range will always be - linear, never wrapping at any values except from - 8191 to 0 (the 8-Kbyte memory boundary). - Extreme care should be taken when - programming the start and end pointers to - prevent a never ending DMA operation which - would overwrite the entire 8-Kbyte buffer. - */ - Enc28J60Network::writeRegPair(EDMASTL, src); - Enc28J60Network::writeRegPair(EDMADSTL, dest); - - if ((src <= RXSTOP_INIT)&& (len > RXSTOP_INIT))len -= ((RXSTOP_INIT + 1)-RXSTART_INIT); - Enc28J60Network::writeRegPair(EDMANDL, len); - - /* - 2. If an interrupt at the end of the copy process is - desired, set EIE.DMAIE and EIE.INTIE and - clear EIR.DMAIF. - - 3. Verify that ECON1.CSUMEN is clear. */ - Enc28J60Network::writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_CSUMEN); - - /* 4. Start the DMA copy by setting ECON1.DMAST. */ - Enc28J60Network::writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_DMAST); - - // wait until runnig DMA is completed - while (Enc28J60Network::readOp(ENC28J60_READ_CTRL_REG, ECON1) & ECON1_DMAST) - { - delay(1); - } - } -} - -void -Enc28J60Network::freePacket(void) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::freePacket(void) DEBUG_V3:Function started")); - #endif - setERXRDPT(); -} - -uint8_t -Enc28J60Network::readOp(uint8_t op, uint8_t address) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::readOp(uint8_t op, uint8_t address) DEBUG_V3:Function started")); - #endif - CSACTIVE; - // issue read command - #if ENC28J60_USE_SPILIB - #if defined(ARDUINO) - SPI.transfer(op | (address & ADDR_MASK)); - // read data - if(address & 0x80) - { - // do dummy read if needed (for mac and mii, see datasheet page 29) - SPI.transfer(0x00); - } - uint8_t c = SPI.transfer(0x00); - #endif - #if defined(__MBED__) - _spi.write(op | (address & ADDR_MASK)); - // read data - if(address & 0x80) - { - // do dummy read if needed (for mac and mii, see datasheet page 29) - _spi.write(0x00); - } - uint8_t c = _spi.write(0x00); - #endif - // release CS - CSPASSIVE; - return(c); - #else - // issue read command - SPDR = op | (address & ADDR_MASK); - waitspi(); - // read data - SPDR = 0x00; - waitspi(); - // do dummy read if needed (for mac and mii, see datasheet page 29) - if(address & 0x80) - { - SPDR = 0x00; - waitspi(); - } - // release CS - CSPASSIVE; - return(SPDR); - #endif - #if defined(ESP8266) - yield(); - #endif -} - -void -Enc28J60Network::writeOp(uint8_t op, uint8_t address, uint8_t data) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::writeOp(uint8_t op, uint8_t address, uint8_t data) DEBUG_V3:Function started")); - #endif - CSACTIVE; - // issue write command - #if ENC28J60_USE_SPILIB - #if defined(ARDUINO) - SPI.transfer(op | (address & ADDR_MASK)); - // write data - SPI.transfer(data); - #endif - #if defined(__MBED__) - _spi.write(op | (address & ADDR_MASK)); - // write data - _spi.write(data); - #endif - #else - // issue write command - SPDR = op | (address & ADDR_MASK); - waitspi(); - // write data - SPDR = data; - waitspi(); - #endif - CSPASSIVE; - #if defined(ESP8266) - yield(); - #endif -} - -void -Enc28J60Network::readBuffer(uint16_t len, uint8_t* data) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::readBuffer(uint16_t len, uint8_t* data) DEBUG_V3:Function started")); - #endif - CSACTIVE; - // issue read command - #if ENC28J60_USE_SPILIB - #if defined(ARDUINO) - SPI.transfer(ENC28J60_READ_BUF_MEM); - #endif - #if defined(__MBED__) - _spi.write(ENC28J60_READ_BUF_MEM); - #endif - #else - SPDR = ENC28J60_READ_BUF_MEM; - waitspi(); - #endif - while(len) - { - len--; - // read data - #if ENC28J60_USE_SPILIB - #if defined(ARDUINO) - *data = SPI.transfer(0x00); - #endif - #if defined(__MBED__) - *data = _spi.write(0x00); - #endif - #else - SPDR = 0x00; - waitspi(); - *data = SPDR; - #endif - data++; - } - //*data='\0'; - CSPASSIVE; -} - -void -Enc28J60Network::writeBuffer(uint16_t len, uint8_t* data) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::writeBuffer(uint16_t len, uint8_t* data) DEBUG_V3:Function started")); - #endif - CSACTIVE; - // issue write command - #if ENC28J60_USE_SPILIB - #if defined(ARDUINO) - SPI.transfer(ENC28J60_WRITE_BUF_MEM); - #endif - #if defined(__MBED__) - _spi.write(ENC28J60_WRITE_BUF_MEM); - #endif - #else - SPDR = ENC28J60_WRITE_BUF_MEM; - waitspi(); - #endif - while(len) - { - len--; - // write data - #if ENC28J60_USE_SPILIB - #if defined(ARDUINO) - SPI.transfer(*data); - #endif - #if defined(__MBED__) - _spi.write(*data); - #endif - data++; - #else - SPDR = *data; - data++; - waitspi(); - #endif - } - CSPASSIVE; -} - -void -Enc28J60Network::setBank(uint8_t address) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::setBank(uint8_t address) DEBUG_V3:Function started")); - #endif - // set the bank (if needed) - if((address & BANK_MASK) != bank) - { - // set the bank - writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1|ECON1_BSEL0)); - writeOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK)>>5); - bank = (address & BANK_MASK); - } -} - -uint8_t -Enc28J60Network::readReg(uint8_t address) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::readReg(uint8_t address) DEBUG_V3:Function started")); - #endif - // set the bank - setBank(address); - // do the read - return readOp(ENC28J60_READ_CTRL_REG, address); -} - -void -Enc28J60Network::writeReg(uint8_t address, uint8_t data) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::writeReg(uint8_t address, uint8_t data) DEBUG_V3:Function started")); - #endif - // set the bank - setBank(address); - // do the write - writeOp(ENC28J60_WRITE_CTRL_REG, address, data); -} - -void -Enc28J60Network::writeRegPair(uint8_t address, uint16_t data) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::writeRegPair(uint8_t address, uint16_t data) DEBUG_V3:Function started")); - #endif - // set the bank - setBank(address); - // do the write - writeOp(ENC28J60_WRITE_CTRL_REG, address, (data&0xFF)); - writeOp(ENC28J60_WRITE_CTRL_REG, address+1, (data) >> 8); -} - -void -Enc28J60Network::phyWrite(uint8_t address, uint16_t data) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::phyWrite(uint8_t address, uint16_t data) DEBUG_V3:Function started")); - #endif - unsigned int timeout = 15; - // set the PHY register address - writeReg(MIREGADR, address); - // write the PHY data - writeRegPair(MIWRL, data); - // wait until the PHY write completes - while (readReg(MISTAT) & MISTAT_BUSY) - { - delay(10); - #if defined(ESP8266) - wdt_reset(); - #endif - if (--timeout == 0) - { - #if ACTLOGLEVEL>=LOG_ERR - LogObject.uart_send_strln(F("Enc28J60Network::phyWrite ERROR:TIMEOUT !!")); - #endif - return; - } - } -} - -uint16_t -Enc28J60Network::phyRead(uint8_t address) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::phyRead(uint8_t address) DEBUG_V3:Function started")); - #endif - unsigned int timeout = 15; - writeReg(MIREGADR,address); - writeReg(MICMD, MICMD_MIIRD); - // wait until the PHY read completes - while(readReg(MISTAT) & MISTAT_BUSY) - { - delay(10); - #if defined(ESP8266) - wdt_reset(); - #endif - if (--timeout == 0) - { - #if ACTLOGLEVEL>=LOG_ERR - LogObject.uart_send_strln(F("Enc28J60Network::phyRead ERROR:TIMEOUT !!")); - #endif - return 0; - } - } - writeReg(MICMD, 0); - return (readReg(MIRDL) | readReg(MIRDH) << 8); -} - -void -Enc28J60Network::clkout(uint8_t clk) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::clkout(uint8_t clk) DEBUG_V3:Function started")); - #endif - //setup clkout: 2 is 12.5MHz: - writeReg(ECOCON, clk & 0x7); -} - -uint16_t -Enc28J60Network::chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len) DEBUG_V3:Function started")); - #endif - uint16_t t; - len = setReadPtr(handle, pos, len)-1; - CSACTIVE; - // issue read command - #if ENC28J60_USE_SPILIB - #if defined(ARDUINO) - SPI.transfer(ENC28J60_READ_BUF_MEM); - #endif - #if defined(__MBED__) - _spi.write(ENC28J60_READ_BUF_MEM); - #endif - #else - SPDR = ENC28J60_READ_BUF_MEM; - waitspi(); - #endif - uint16_t i; - for (i = 0; i < len; i+=2) - { - // read data - #if ENC28J60_USE_SPILIB - #if defined(ARDUINO) - t = SPI.transfer(0x00) << 8; - t += SPI.transfer(0x00); - #endif - #if defined(__MBED__) - t = _spi.write(0x00) << 8; - t += _spi.write(0x00); - #endif - #else - SPDR = 0x00; - waitspi(); - t = SPDR << 8; - SPDR = 0x00; - waitspi(); - t += SPDR; - #endif - sum += t; - if(sum < t) - { - sum++; /* carry */ - } - } - if(i == len) - { - #if ENC28J60_USE_SPILIB - #if defined(ARDUINO) - t = (SPI.transfer(0x00) << 8) + 0; - #endif - #if defined(__MBED__) - t = (_spi.write(0x00) << 8) + 0; - #endif - #else - SPDR = 0x00; - waitspi(); - t = (SPDR << 8) + 0; - #endif - sum += t; - if(sum < t) - { - sum++; /* carry */ - } - } - CSPASSIVE; - - /* Return sum in host byte order. */ - return sum; -} - -void -Enc28J60Network::powerOff(void) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::powerOff(void) DEBUG_V3:Function started")); - #endif - writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_RXEN); - delay(50); - writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_VRPS); - delay(50); - writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PWRSV); -} - -void -Enc28J60Network::powerOn(void) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::powerOn(void) DEBUG_V3:Function started")); - #endif - writeOp(ENC28J60_BIT_FIELD_CLR, ECON2, ECON2_PWRSV); - delay(50); - writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); - delay(50); -} - -// read erevid from object: -uint8_t -Enc28J60Network::geterevid(void) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_str(F("Enc28J60Network::geterevid(void) DEBUG_V3:Function started and return:")); - LogObject.uart_send_decln(erevid); - #endif - return(erevid); -} - -// read the phstat2 of the chip: -uint16_t -Enc28J60Network::PhyStatus(void) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_str(F("Enc28J60Network::PhyStatus(void) DEBUG_V3:Function started")); - LogObject.uart_send_decln(erevid); - #endif - uint16_t phstat2; - phstat2=phyRead(PHSTAT2); - if ((phstat2 & 0x20) > 0) {phstat2=phstat2 &0x100;} - phstat2=(phstat2 & 0xFF00) | erevid; - if ((phstat2 & 0x8000) > 0) {phstat2=0;} - return phstat2; -} - -bool -Enc28J60Network::linkStatus(void) -{ - #if ACTLOGLEVEL>=LOG_DEBUG_V3 - LogObject.uart_send_strln(F("Enc28J60Network::linkStatus(void) DEBUG_V3:Function started")); - #endif - return (phyRead(PHSTAT2) & 0x0400) > 0; -} - -Enc28J60Network Enc28J60; +/* + Enc28J60NetworkClass.h + UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface. + + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + based on enc28j60.c file from the AVRlib library by Pascal Stang. + For AVRlib See http://www.procyonengineering.com/ + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + +#include "Enc28J60Network.h" +#if defined(ARDUINO) + #include "Arduino.h" +#endif +#if defined(__MBED__) + #include + #include "mbed/millis.h" + #define delay(x) wait_ms(x) +#endif +#include "logging.h" + +// KH, For nRF52 +//#define ENC28J60_USE_SPILIB true + +uint8_t ENC28J60ControlCS = ENC28J60_CONTROL_CS; + +#if ENC28J60_USE_SPILIB + #if defined(ARDUINO) + #if defined(STM32F2) + #include + #elif !defined(STM32F3) && !defined(__STM32F4__) + #include + extern SPIClass SPI; + //#elif defined(ARDUINO_ARCH_AMEBA) + //SPIClass SPI((void *)(&spi_obj), 11, 12, 13, 10); + //SPI _spi(SPI_MOSI,SPI_MISO,SPI_SCK,ENC28J60ControlCS); + #else + #include "HardwareSPI.h" + extern HardwareSPI SPI(1); + #endif + #endif + #if defined(__MBED__) + SPI _spi(SPI_MOSI, SPI_MISO, SPI_SCK); + DigitalOut _cs(ENC28J60ControlCS); + Serial LogObject(SERIAL_TX, SERIAL_RX); + #endif +#endif + +extern "C" { +#if defined(ARDUINO_ARCH_AVR) + // AVR-specific code +#include +#elif defined(ARDUINO_ARCH_SAM) + // SAM-specific code +#elif defined(ARDUINO_ARCH_SAMD) + // SAMD-specific code +#else + // generic, non-platform specific code +#endif +#include "enc28j60.h" +#include "uip.h" +} + +#if defined(ARDUINO) + // set CS to 0 = active + #define CSACTIVE digitalWrite(ENC28J60ControlCS, LOW) + // set CS to 1 = passive + #define CSPASSIVE digitalWrite(ENC28J60ControlCS, HIGH) +#endif +#if defined(__MBED__) + // set CS to 0 = active + #define CSACTIVE _cs=0 + // set CS to 1 = passive + #define CSPASSIVE _cs=1 +#endif + +// +#if defined(ARDUINO_ARCH_AVR) + #define waitspi() while(!(SPSR&(1<=LOG_DEBUG + LogObject.uart_send_str(F("ENC28J60::init DEBUG:csPin = ")); + LogObject.uart_send_decln(ENC28J60ControlCS); + LogObject.uart_send_str(F("ENC28J60::init DEBUG:miso = ")); + LogObject.uart_send_decln(SPI_MISO); + LogObject.uart_send_str(F("ENC28J60::init DEBUG:mosi = ")); + LogObject.uart_send_decln(SPI_MOSI); + LogObject.uart_send_str(F("ENC28J60::init DEBUG:sck = ")); + LogObject.uart_send_decln(SPI_SCK); +#endif +#if ENC28J60_USE_SPILIB +#if ACTLOGLEVEL>=LOG_DEBUG + LogObject.uart_send_strln(F("ENC28J60::init DEBUG:Use SPI lib SPI.begin()")); +#endif +#if defined(ARDUINO) +#if defined(__STM32F3__) || defined(STM32F3) || defined(__STM32F4__) + SPI.begin(SPI_9MHZ, MSBFIRST, 0); +#else + SPI.begin(); +#endif +#endif +#if defined(ARDUINO_ARCH_AVR) + // AVR-specific code + SPI.setClockDivider(SPI_CLOCK_DIV2); //results in 8MHZ at 16MHZ system clock. +#elif defined(ARDUINO_ARCH_SAM) + // SAM-specific code + SPI.setClockDivider(10); //defaults to 21 which results in aprox. 4MHZ. A 10 should result in a little more than 8MHZ. +#elif defined(ARDUINO_ARCH_SAMD) + // SAMD-specific code + // Should we set clock divider? + SPI.setClockDivider(10); +#elif defined(__STM32F1__) || defined(__STM32F3__) + // generic, non-platform specific code +#define USE_STM32F1_DMAC 1 //on STM32 + // BOARD_NR_SPI >= 1 BOARD_SPI1_NSS_PIN, BOARD_SPI1_SCK_PIN, BOARD_SPI1_MISO_PIN, BOARD_SPI1_MOSI_PIN + SPI.setBitOrder(MSBFIRST); + SPI.setDataMode(SPI_MODE0); + SPI.setClockDivider(SPI_CLOCK_DIV8); //value 8 the result is 9MHz at 72MHz clock. +#else +#if defined(ARDUINO) +#if !defined(__STM32F3__) && !defined(STM32F3) && !defined(__STM32F4__) + SPI.setBitOrder(MSBFIRST); +#endif + //Settings for ESP8266 + //SPI.setDataMode(SPI_MODE0); + //SPI.setClockDivider(SPI_CLOCK_DIV16); +#endif +#if defined(__MBED__) + _spi.format(8, 0); // 8bit, mode 0 + _spi.frequency(7000000); // 7MHz +#endif +#endif +#else +#if ACTLOGLEVEL>=LOG_DEBUG + LogObject.uart_send_strln(F("ENC28J60::init DEBUG:Use Native hardware SPI")); +#endif + pinMode(SPI_MOSI, OUTPUT); + pinMode(SPI_SCK, OUTPUT); + pinMode(SPI_MISO, INPUT); + //Hardware SS must be configured as OUTPUT to enable SPI-master (regardless of which pin is configured as ENC28J60ControlCS) + pinMode(SS, OUTPUT); + digitalWrite(SS, HIGH); + + digitalWrite(SPI_MOSI, LOW); + digitalWrite(SPI_SCK, LOW); + + // initialize SPI interface + // master mode and Fosc/2 clock: + SPCR = (1 << SPE) | (1 << MSTR); + SPSR |= (1 << SPI2X); +#endif + + // perform system reset + writeOp(ENC28J60_SOFT_RESET, 0, ENC28J60_SOFT_RESET); + delay(2); // errata B7/2 + delay(50); + // check CLKRDY bit to see if reset is complete + // The CLKRDY does not work. See Rev. B4 Silicon Errata point. Just wait. + //while(!(readReg(ESTAT) & ESTAT_CLKRDY)); + // do bank 0 stuff + // initialize receive buffer + // 16-bit transfers, must write low byte first + // set receive buffer start address +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:Before readOp(ENC28J60_READ_CTRL_REG, ESTAT)")); +#endif + nextPacketPtr = RXSTART_INIT; + + while ((!readOp(ENC28J60_READ_CTRL_REG, ESTAT) & ESTAT_CLKRDY) && (timeout > 0)) + { + timeout = timeout - 1; + delay(10); +#if defined(ESP8266) + wdt_reset(); +#endif + } + +#if ACTLOGLEVEL>=LOG_ERR + + if (timeout == 0) + { + LogObject.uart_send_strln(F("ENC28J60::init ERROR:TIMEOUT !!")); + } + +#endif +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:After readOp(ENC28J60_READ_CTRL_REG, ESTAT)")); +#endif + // Rx start + writeRegPair(ERXSTL, RXSTART_INIT); +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:After writeRegPair(ERXSTL, RXSTART_INIT)")); +#endif + // set receive pointer address + writeRegPair(ERXRDPTL, RXSTART_INIT); + // RX end + writeRegPair(ERXNDL, RXSTOP_INIT); + // TX start + //writeRegPair(ETXSTL, TXSTART_INIT); + // TX end + //writeRegPair(ETXNDL, TXSTOP_INIT); + // do bank 1 stuff, packet filter: + // For broadcast packets we allow only ARP packtets + // All other packets should be unicast only for our mac (MAADR) + // + // The pattern to match on is therefore + // Type ETH.DST + // ARP BROADCAST + // 06 08 -- ff ff ff ff ff ff -> ip checksum for theses bytes=f7f9 + // in binary these poitions are:11 0000 0011 1111 + // This is hex 303F->EPMM0=0x3f,EPMM1=0x30 + //TODO define specific pattern to receive dhcp-broadcast packages instead of setting ERFCON_BCEN! + // enableBroadcast(); // change to add ERXFCON_BCEN recommended by epam + writeReg(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_PMEN | ERXFCON_BCEN); +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln( + F("ENC28J60::init DEBUG_V3:After writeReg(ERXFCON, ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN|ERXFCON_BCEN)")); +#endif +#if defined(ESP8266) + wdt_reset(); +#endif + writeRegPair(EPMM0, 0x303f); + writeRegPair(EPMCSL, 0xf7f9); + // + // + // do bank 2 stuff + // enable MAC receive + // and bring MAC out of reset (writes 0x00 to MACON2) + writeRegPair(MACON1, MACON1_MARXEN | MACON1_TXPAUS | MACON1_RXPAUS); + // enable automatic padding to 60bytes and CRC operations + writeOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN); +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln( + F("ENC28J60::init DEBUG_V3:After writeOp(ENC28J60_BIT_FIELD_SET, MACON3, MACON3_PADCFG0|MACON3_TXCRCEN|MACON3_FRMLNEN)")); +#endif + // set inter-frame gap (non-back-to-back) + writeRegPair(MAIPGL, 0x0C12); + // set inter-frame gap (back-to-back) + writeReg(MABBIPG, 0x12); + // Set the maximum packet size which the controller will accept + // Do not send packets longer than MAX_FRAMELEN: + writeRegPair(MAMXFLL, MAX_FRAMELEN); + // do bank 3 stuff + // write MAC address + // NOTE: MAC address in ENC28J60 is byte-backward + writeReg(MAADR5, macaddr[0]); + writeReg(MAADR4, macaddr[1]); + writeReg(MAADR3, macaddr[2]); + writeReg(MAADR2, macaddr[3]); + writeReg(MAADR1, macaddr[4]); + writeReg(MAADR0, macaddr[5]); + // no loopback of transmitted frames +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:Before phyWrite(PHCON2, PHCON2_HDLDIS)")); +#endif + phyWrite(PHCON2, PHCON2_HDLDIS); +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:After phyWrite(PHCON2, PHCON2_HDLDIS)")); +#endif + // switch to bank 0 + setBank(ECON1); +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:After setBank(ECON1)")); +#endif + // enable interrutps + writeOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE | EIE_PKTIE); + // enable packet reception + writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); + //Configure leds + phyWrite(PHLCON, 0x476); + +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("ENC28J60::init DEBUG_V3:Before readReg(EREVID);")); +#endif + erevid = readReg(EREVID); + + if (erevid == 0xFF) + { + erevid = 0; + } + + // microchip forgot to step the number on the silcon when they + // released the revision B7. 6 is now rev B7. We still have + // to see what they do when they release B8. At the moment + // there is no B8 out yet + //if (erevid > 5) ++erevid; +#if ACTLOGLEVEL>=LOG_INFO + LogObject.uart_send_str(F("ENC28J60::init INFO: Chip erevid=")); + LogObject.uart_send_dec(erevid); + LogObject.uart_send_strln(F(" initialization completed.")); +#endif + + // return Enc28J60Network::erevid; +} + +memhandle +Enc28J60Network::receivePacket(void) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::receivePacket(void) DEBUG_V3:Function started")); +#endif +#if defined(ESP8266) + wdt_reset(); +#endif + uint8_t rxstat; + uint16_t len; + // check if a packet has been received and buffered + //if( !(readReg(EIR) & EIR_PKTIF) ){ + // The above does not work. See Rev. B4 Silicon Errata point 6. +#if ACTLOGLEVEL>=LOG_ERR + + if (erevid == 0) + { + LogObject.uart_send_strln( + F("Enc28J60Network::receivePacket(void) ERROR:ENC28j50 Device not found !! Bypass receivePacket function !!")); + } + +#endif + uint8_t epktcnt = readReg(EPKTCNT); + + if ((erevid != 0) && (epktcnt != 0)) + { + uint16_t readPtr = nextPacketPtr + 6 > RXSTOP_INIT ? nextPacketPtr + 6 - RXSTOP_INIT + RXSTART_INIT : nextPacketPtr + 6; + // Set the read pointer to the start of the received packet + writeRegPair(ERDPTL, nextPacketPtr); + // read the next packet pointer + nextPacketPtr = readOp(ENC28J60_READ_BUF_MEM, 0); + nextPacketPtr |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; + // read the packet length (see datasheet page 43) + len = readOp(ENC28J60_READ_BUF_MEM, 0); + len |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; + len -= 4; //remove the CRC count + // read the receive status (see datasheet page 43) + rxstat = readOp(ENC28J60_READ_BUF_MEM, 0); + //rxstat |= readOp(ENC28J60_READ_BUF_MEM, 0) << 8; +#if ACTLOGLEVEL>=LOG_DEBUG + LogObject.uart_send_str(F("Enc28J60Network::receivePacket(void) DEBUG:receivePacket [")); + LogObject.uart_send_hex(readPtr); + LogObject.uart_send_str(F("-")); + LogObject.uart_send_hex((readPtr + len) % (RXSTOP_INIT + 1)); + LogObject.uart_send_str(F("], next: ")); + LogObject.uart_send_hex(nextPacketPtr); + LogObject.uart_send_str(F(", stat: ")); + LogObject.uart_send_hex(rxstat); + LogObject.uart_send_str(F(", Packet count: ")); + LogObject.uart_send_dec(epktcnt); + LogObject.uart_send_str(F(" -> ")); + LogObject.uart_send_strln((rxstat & 0x80) != 0 ? "OK" : "failed"); +#endif + // decrement the packet counter indicate we are done with this packet + writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PKTDEC); + + // check CRC and symbol errors (see datasheet page 44, table 7-3): + // The ERXFCON.CRCEN is set by default. Normally we should not + // need to check this. + if (((rxstat & 0x80) != 0) && (nextPacketPtr <= RXSTOP_INIT)) + { + receivePkt.begin = readPtr; + receivePkt.size = len; +#if ACTLOGLEVEL>=LOG_DEBUG + LogObject.uart_send_str(F("Enc28J60Network::receivePacket(void) DEBUG: rxstat OK. receivePkt.size=")); + LogObject.uart_send_decln(len); +#endif + return UIP_RECEIVEBUFFERHANDLE; + } + + // Move the RX read pointer to the start of the next received packet + // This frees the memory we just read out + setERXRDPT(); + } + + return (NOBLOCK); +} + +void +Enc28J60Network::setERXRDPT(void) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::setERXRDPT(void) DEBUG_V3:Function started")); +#endif + // Make sure the value is odd. See Rev. B1,B4,B5,B7 Silicon Errata issues 14 + uint16_t actnextPacketPtr = nextPacketPtr == RXSTART_INIT ? RXSTOP_INIT : nextPacketPtr - 1; +#if ACTLOGLEVEL>=LOG_DEBUG + LogObject.uart_send_str(F("Enc28J60Network::setERXRDPT(void) DEBUG:Set actnextPacketPtr:")); + LogObject.uart_send_hexln(actnextPacketPtr); +#endif + // datasheet: The ENC28J60 will always write up to, but not including + writeRegPair(ERXRDPTL, actnextPacketPtr); +} + +memaddress +Enc28J60Network::blockSize(memhandle handle) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::blockSize(memhandle handle) DEBUG_V3:Function started")); +#endif + return ((handle == NOBLOCK) + || (erevid == 0)) ? 0 : handle == UIP_RECEIVEBUFFERHANDLE ? receivePkt.size : blocks[handle].size; +} + +void +Enc28J60Network::sendPacket(memhandle handle) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::sendPacket(memhandle handle) INFO:Function started")); +#endif +#if defined(ESP8266) + wdt_reset(); +#endif + + if (erevid == 0) + { +#if ACTLOGLEVEL>=LOG_ERR + LogObject.uart_send_strln( + F("Enc28J60Network::sendPacket(memhandle handle) ERROR:ENC28j50 Device not found !! Bypass sendPacket function !!")); +#endif + return; + } + + memblock *packet = &blocks[handle]; + uint16_t start = packet->begin - 1; + uint16_t end = start + packet->size; + + // backup data at control-byte position + uint8_t data = readByte(start); + + // write control-byte (if not 0 anyway) + if (data) + writeByte(start, 0); + +#if ACTLOGLEVEL>=LOG_DEBUG + LogObject.uart_send_str(F("Enc28J60Network::sendPacket(memhandle handle) DEBUG:sendPacket(")); + LogObject.uart_send_dec(handle); + LogObject.uart_send_str(F(") [")); + LogObject.uart_send_hex(start); + LogObject.uart_send_str(F("-")); + LogObject.uart_send_hex(end); + LogObject.uart_send_str(F("]: ")); + + for (uint16_t i = start; i <= end; i++) + { + LogObject.uart_send_hex(readByte(i)); + LogObject.uart_send_str(F(" ")); + } + + LogObject.uart_send_strln(F("")); +#endif + + // TX start + writeRegPair(ETXSTL, start); + // Set the TXND pointer to correspond to the packet size given + writeRegPair(ETXNDL, end); + // send the contents of the transmit buffer onto the network + + unsigned int retry = TX_COLLISION_RETRY_COUNT; + unsigned int timeout = 100; + + do + { + // seydamir added + // Reset the transmit logic problem. See Rev. B7 Silicon Errata issues 12 and 13 + writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRST); + writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRST); + writeOp(ENC28J60_BIT_FIELD_CLR, EIR, EIR_TXERIF | EIR_TXIF); + // end + + writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_TXRTS); + // Reset the transmit logic problem. See Rev. B4 Silicon Errata point 12. + //if( (readReg(EIR) & EIR_TXERIF) ) + // { + // writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS); + // } + + timeout = 100; + + while (((readReg(EIR) & (EIR_TXIF | EIR_TXERIF)) == 0) && (timeout > 0)) + { + timeout = timeout - 1; + delay(10); +#if defined(ESP8266) + wdt_reset(); +#endif + } + + if (timeout == 0) + { + /* Transmit hardware probably hung, try again later. */ + /* Shouldn't happen according to errata 12 and 13. */ + writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_TXRTS); +#if ACTLOGLEVEL>=LOG_WARN + LogObject.uart_send_strln(F("Enc28J60Network::sendPacket(memhandle handle) WARNING:Collision")); +#endif + retry = retry - 1; + } + } while ((timeout == 0) && (retry != 0)); + + //restore data on control-byte position + if (data) + writeByte(start, data); + + if (retry == 0) + { +#if ACTLOGLEVEL>=LOG_ERROR + LogObject.uart_send_strln(F("Enc28J60Network::sendPacket(memhandle handle) ERROR:COLLISION !!")); +#endif + return; + } +} + +uint16_t +Enc28J60Network::setReadPtr(memhandle handle, memaddress position, uint16_t len) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln( + F("Enc28J60Network::setReadPtr(memhandle handle, memaddress position, uint16_t len) DEBUG_V3:Function started")); +#endif + memblock *packet = handle == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[handle]; + memaddress start = handle == UIP_RECEIVEBUFFERHANDLE + && packet->begin + position > RXSTOP_INIT ? packet->begin + position - RXSTOP_INIT + RXSTART_INIT : packet->begin + + position; + + writeRegPair(ERDPTL, start); + + if (len > packet->size - position) + len = packet->size - position; + + return len; +} + +uint16_t +Enc28J60Network::readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln( + F("Enc28J60Network::readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) DEBUG_V3:Function started")); +#endif +#if defined(ESP8266) + wdt_reset(); +#endif + len = setReadPtr(handle, position, len); + readBuffer(len, buffer); +#if ACTLOGLEVEL>=LOG_DEBUG_V2 + LogObject.uart_send_str( + F("Enc28J60Network::readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) DEBUG_V2: Read bytes:")); + LogObject.uart_send_dec(len); + LogObject.uart_send_str(F(" save to block(")); + LogObject.uart_send_dec(handle); + LogObject.uart_send_str(F(") [")); + LogObject.uart_send_hex(position); + LogObject.uart_send_str(F("]: ")); + + for (uint16_t i = 0; i < len; i++) + { + LogObject.uart_send_hex(buffer[i]); + LogObject.uart_send_str(F(" ")); + } + + LogObject.uart_send_strln(F("")); +#endif + return len; +} + +uint16_t +Enc28J60Network::writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_str( + F("Enc28J60Network::writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) DEBUG_V3:Function started with len:")); + LogObject.uart_send_decln(len); +#endif +#if defined(ESP8266) + wdt_reset(); +#endif + memblock *packet = &blocks[handle]; + uint16_t start = packet->begin + position; + + writeRegPair(EWRPTL, start); + + if (len > packet->size - position) + len = packet->size - position; + + writeBuffer(len, buffer); +#if ACTLOGLEVEL>=LOG_DEBUG_V2 + LogObject.uart_send_str( + F("Enc28J60Network::writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len) DEBUG_V2: Write bytes:")); + LogObject.uart_send_dec(len); + LogObject.uart_send_str(F(" save to block(")); + LogObject.uart_send_dec(handle); + LogObject.uart_send_str(F(") [")); + LogObject.uart_send_hex(start); + LogObject.uart_send_str(F("]: ")); + + for (uint16_t i = 0; i < len; i++) + { + LogObject.uart_send_hex(buffer[i]); + LogObject.uart_send_str(F(" ")); + } + + LogObject.uart_send_strln(F("")); +#endif + return len; +} + + +void Enc28J60Network::enableBroadcast (bool temporary) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::enableBroadcast (bool temporary) DEBUG_V3:Function started")); +#endif + writeRegByte(ERXFCON, readRegByte(ERXFCON) | ERXFCON_BCEN); + + if (!temporary) + broadcast_enabled = true; +} + +void Enc28J60Network::disableBroadcast (bool temporary) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::disableBroadcast (bool temporary) DEBUG_V3:Function started")); +#endif + + if (!temporary) + broadcast_enabled = false; + + if (!broadcast_enabled) + writeRegByte(ERXFCON, readRegByte(ERXFCON) & ~ERXFCON_BCEN); +} + +void Enc28J60Network::enableMulticast (void) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::enableMulticast (void) DEBUG_V3:Function started")); +#endif + writeRegByte(ERXFCON, readRegByte(ERXFCON) | ERXFCON_MCEN); +} + +void Enc28J60Network::disableMulticast (void) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::disableMulticast (void) DEBUG_V3:Function started")); +#endif + writeRegByte(ERXFCON, readRegByte(ERXFCON) & ~ERXFCON_MCEN); +} + +uint8_t Enc28J60Network::readRegByte (uint8_t address) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::readRegByte (uint8_t address) DEBUG_V3:Function started")); +#endif + setBank(address); + return readOp(ENC28J60_READ_CTRL_REG, address); +} + +void Enc28J60Network::writeRegByte (uint8_t address, uint8_t data) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::writeRegByte (uint8_t address, uint8_t data) DEBUG_V3:Function started")); +#endif + setBank(address); + writeOp(ENC28J60_WRITE_CTRL_REG, address, data); +} + + +uint8_t Enc28J60Network::readByte(uint16_t addr) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::readByte(uint16_t addr) DEBUG_V3:Function started")); +#endif +#if defined(ESP8266) + wdt_reset(); +#endif + writeRegPair(ERDPTL, addr); + + CSACTIVE; +#if ENC28J60_USE_SPILIB + // issue read command +#if defined(ARDUINO) + SPI.transfer(ENC28J60_READ_BUF_MEM); + // read data + uint8_t c = SPI.transfer(0x00); +#endif +#if defined(__MBED__) + _spi.write(ENC28J60_READ_BUF_MEM); + // read data + uint8_t c = _spi.write(0x00); +#endif + CSPASSIVE; + return (c); +#else + // issue read command + SPDR = ENC28J60_READ_BUF_MEM; + waitspi(); + // read data + SPDR = 0x00; + waitspi(); + CSPASSIVE; + return (SPDR); +#endif +} + +void Enc28J60Network::writeByte(uint16_t addr, uint8_t data) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::writeByte(uint16_t addr, uint8_t data) DEBUG_V3:Function started")); +#endif +#if defined(ESP8266) + wdt_reset(); +#endif + writeRegPair(EWRPTL, addr); + + CSACTIVE; +#if ENC28J60_USE_SPILIB + // issue write command +#if defined(ARDUINO) + SPI.transfer(ENC28J60_WRITE_BUF_MEM); + // write data + SPI.transfer(data); +#endif +#if defined(__MBED__) + _spi.write(ENC28J60_WRITE_BUF_MEM); + // write data + _spi.write(data); +#endif +#else + // issue write command + SPDR = ENC28J60_WRITE_BUF_MEM; + waitspi(); + // write data + SPDR = data; + waitspi(); +#endif + CSPASSIVE; +} + +void +Enc28J60Network::copyPacket(memhandle dest_pkt, memaddress dest_pos, memhandle src_pkt, memaddress src_pos, + uint16_t len) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln( + F("Enc28J60Network::copyPacket(memhandle dest_pkt, memaddress dest_pos, memhandle src_pkt, memaddress src_pos, uint16_t len) DEBUG_V3:Function started")); +#endif + memblock *dest = &blocks[dest_pkt]; + memblock *src = src_pkt == UIP_RECEIVEBUFFERHANDLE ? &receivePkt : &blocks[src_pkt]; + memaddress start = src_pkt == UIP_RECEIVEBUFFERHANDLE + && src->begin + src_pos > RXSTOP_INIT ? src->begin + src_pos - RXSTOP_INIT + RXSTART_INIT : src->begin + src_pos; + enc28J60_mempool_block_move_callback(dest->begin + dest_pos, start, len); + // setERXRDPT(); let it to freePacket after all packets are saved +} + +void +enc28J60_mempool_block_move_callback(memaddress dest, memaddress src, memaddress len) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln( + F("enc28J60_mempool_block_move_callback(memaddress dest, memaddress src, memaddress len) DEBUG_V3:Function started")); +#endif + + //void + //Enc28J60Network::memblock_mv_cb(uint16_t dest, uint16_t src, uint16_t len) + //{ + //as ENC28J60 DMA is unable to copy single bytes: + if (len == 1) + { + Enc28J60Network::writeByte(dest, Enc28J60Network::readByte(src)); + } + else + { + // calculate address of last byte + len += src - 1; + + /* 1. Appropriately program the EDMAST, EDMAND + and EDMADST register pairs. The EDMAST + registers should point to the first byte to copy + from, the EDMAND registers should point to the + last byte to copy and the EDMADST registers + should point to the first byte in the destination + range. The destination range will always be + linear, never wrapping at any values except from + 8191 to 0 (the 8-Kbyte memory boundary). + Extreme care should be taken when + programming the start and end pointers to + prevent a never ending DMA operation which + would overwrite the entire 8-Kbyte buffer. + */ + Enc28J60Network::writeRegPair(EDMASTL, src); + Enc28J60Network::writeRegPair(EDMADSTL, dest); + + if ((src <= RXSTOP_INIT) && (len > RXSTOP_INIT)) + len -= ((RXSTOP_INIT + 1) - RXSTART_INIT); + + Enc28J60Network::writeRegPair(EDMANDL, len); + + /* + 2. If an interrupt at the end of the copy process is + desired, set EIE.DMAIE and EIE.INTIE and + clear EIR.DMAIF. + + 3. Verify that ECON1.CSUMEN is clear. */ + Enc28J60Network::writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_CSUMEN); + + /* 4. Start the DMA copy by setting ECON1.DMAST. */ + Enc28J60Network::writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_DMAST); + + // wait until runnig DMA is completed + while (Enc28J60Network::readOp(ENC28J60_READ_CTRL_REG, ECON1) & ECON1_DMAST) + { + delay(1); + } + } +} + +void +Enc28J60Network::freePacket(void) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::freePacket(void) DEBUG_V3:Function started")); +#endif + setERXRDPT(); +} + +uint8_t +Enc28J60Network::readOp(uint8_t op, uint8_t address) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::readOp(uint8_t op, uint8_t address) DEBUG_V3:Function started")); +#endif + CSACTIVE; + // issue read command +#if ENC28J60_USE_SPILIB +#if defined(ARDUINO) + SPI.transfer(op | (address & ADDR_MASK)); + + // read data + if (address & 0x80) + { + // do dummy read if needed (for mac and mii, see datasheet page 29) + SPI.transfer(0x00); + } + + uint8_t c = SPI.transfer(0x00); +#endif +#if defined(__MBED__) + _spi.write(op | (address & ADDR_MASK)); + + // read data + if (address & 0x80) + { + // do dummy read if needed (for mac and mii, see datasheet page 29) + _spi.write(0x00); + } + + uint8_t c = _spi.write(0x00); +#endif + // release CS + CSPASSIVE; + return (c); +#else + // issue read command + SPDR = op | (address & ADDR_MASK); + waitspi(); + // read data + SPDR = 0x00; + waitspi(); + + // do dummy read if needed (for mac and mii, see datasheet page 29) + if (address & 0x80) + { + SPDR = 0x00; + waitspi(); + } + + // release CS + CSPASSIVE; + return (SPDR); +#endif +#if defined(ESP8266) + yield(); +#endif +} + +void +Enc28J60Network::writeOp(uint8_t op, uint8_t address, uint8_t data) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln( + F("Enc28J60Network::writeOp(uint8_t op, uint8_t address, uint8_t data) DEBUG_V3:Function started")); +#endif + CSACTIVE; + // issue write command +#if ENC28J60_USE_SPILIB +#if defined(ARDUINO) + SPI.transfer(op | (address & ADDR_MASK)); + // write data + SPI.transfer(data); +#endif +#if defined(__MBED__) + _spi.write(op | (address & ADDR_MASK)); + // write data + _spi.write(data); +#endif +#else + // issue write command + SPDR = op | (address & ADDR_MASK); + waitspi(); + // write data + SPDR = data; + waitspi(); +#endif + CSPASSIVE; +#if defined(ESP8266) + yield(); +#endif +} + +void +Enc28J60Network::readBuffer(uint16_t len, uint8_t* data) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::readBuffer(uint16_t len, uint8_t* data) DEBUG_V3:Function started")); +#endif + CSACTIVE; + // issue read command +#if ENC28J60_USE_SPILIB +#if defined(ARDUINO) + SPI.transfer(ENC28J60_READ_BUF_MEM); +#endif +#if defined(__MBED__) + _spi.write(ENC28J60_READ_BUF_MEM); +#endif +#else + SPDR = ENC28J60_READ_BUF_MEM; + waitspi(); +#endif + + while (len) + { + len--; + // read data +#if ENC28J60_USE_SPILIB +#if defined(ARDUINO) + *data = SPI.transfer(0x00); +#endif +#if defined(__MBED__) + *data = _spi.write(0x00); +#endif +#else + SPDR = 0x00; + waitspi(); + *data = SPDR; +#endif + data++; + } + + //*data='\0'; + CSPASSIVE; +} + +void +Enc28J60Network::writeBuffer(uint16_t len, uint8_t* data) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::writeBuffer(uint16_t len, uint8_t* data) DEBUG_V3:Function started")); +#endif + CSACTIVE; + // issue write command +#if ENC28J60_USE_SPILIB +#if defined(ARDUINO) + SPI.transfer(ENC28J60_WRITE_BUF_MEM); +#endif +#if defined(__MBED__) + _spi.write(ENC28J60_WRITE_BUF_MEM); +#endif +#else + SPDR = ENC28J60_WRITE_BUF_MEM; + waitspi(); +#endif + + while (len) + { + len--; + // write data +#if ENC28J60_USE_SPILIB +#if defined(ARDUINO) + SPI.transfer(*data); +#endif +#if defined(__MBED__) + _spi.write(*data); +#endif + data++; +#else + SPDR = *data; + data++; + waitspi(); +#endif + } + + CSPASSIVE; +} + +void +Enc28J60Network::setBank(uint8_t address) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::setBank(uint8_t address) DEBUG_V3:Function started")); +#endif + + // set the bank (if needed) + if ((address & BANK_MASK) != bank) + { + // set the bank + writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, (ECON1_BSEL1 | ECON1_BSEL0)); + writeOp(ENC28J60_BIT_FIELD_SET, ECON1, (address & BANK_MASK) >> 5); + bank = (address & BANK_MASK); + } +} + +uint8_t +Enc28J60Network::readReg(uint8_t address) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::readReg(uint8_t address) DEBUG_V3:Function started")); +#endif + // set the bank + setBank(address); + // do the read + return readOp(ENC28J60_READ_CTRL_REG, address); +} + +void +Enc28J60Network::writeReg(uint8_t address, uint8_t data) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::writeReg(uint8_t address, uint8_t data) DEBUG_V3:Function started")); +#endif + // set the bank + setBank(address); + // do the write + writeOp(ENC28J60_WRITE_CTRL_REG, address, data); +} + +void +Enc28J60Network::writeRegPair(uint8_t address, uint16_t data) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::writeRegPair(uint8_t address, uint16_t data) DEBUG_V3:Function started")); +#endif + // set the bank + setBank(address); + // do the write + writeOp(ENC28J60_WRITE_CTRL_REG, address, (data & 0xFF)); + writeOp(ENC28J60_WRITE_CTRL_REG, address + 1, (data) >> 8); +} + +void +Enc28J60Network::phyWrite(uint8_t address, uint16_t data) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::phyWrite(uint8_t address, uint16_t data) DEBUG_V3:Function started")); +#endif + unsigned int timeout = 15; + // set the PHY register address + writeReg(MIREGADR, address); + // write the PHY data + writeRegPair(MIWRL, data); + + // wait until the PHY write completes + while (readReg(MISTAT) & MISTAT_BUSY) + { + delay(10); +#if defined(ESP8266) + wdt_reset(); +#endif + + if (--timeout == 0) + { +#if ACTLOGLEVEL>=LOG_ERR + LogObject.uart_send_strln(F("Enc28J60Network::phyWrite ERROR:TIMEOUT !!")); +#endif + return; + } + } +} + +uint16_t +Enc28J60Network::phyRead(uint8_t address) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::phyRead(uint8_t address) DEBUG_V3:Function started")); +#endif + unsigned int timeout = 15; + writeReg(MIREGADR, address); + writeReg(MICMD, MICMD_MIIRD); + + // wait until the PHY read completes + while (readReg(MISTAT) & MISTAT_BUSY) + { + delay(10); +#if defined(ESP8266) + wdt_reset(); +#endif + + if (--timeout == 0) + { +#if ACTLOGLEVEL>=LOG_ERR + LogObject.uart_send_strln(F("Enc28J60Network::phyRead ERROR:TIMEOUT !!")); +#endif + return 0; + } + } + + writeReg(MICMD, 0); + return (readReg(MIRDL) | readReg(MIRDH) << 8); +} + +void +Enc28J60Network::clkout(uint8_t clk) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::clkout(uint8_t clk) DEBUG_V3:Function started")); +#endif + //setup clkout: 2 is 12.5MHz: + writeReg(ECOCON, clk & 0x7); +} + +uint16_t +Enc28J60Network::chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln( + F("Enc28J60Network::chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len) DEBUG_V3:Function started")); +#endif + uint16_t t; + len = setReadPtr(handle, pos, len) - 1; + CSACTIVE; + // issue read command +#if ENC28J60_USE_SPILIB +#if defined(ARDUINO) + SPI.transfer(ENC28J60_READ_BUF_MEM); +#endif +#if defined(__MBED__) + _spi.write(ENC28J60_READ_BUF_MEM); +#endif +#else + SPDR = ENC28J60_READ_BUF_MEM; + waitspi(); +#endif + uint16_t i; + + for (i = 0; i < len; i += 2) + { + // read data +#if ENC28J60_USE_SPILIB +#if defined(ARDUINO) + t = SPI.transfer(0x00) << 8; + t += SPI.transfer(0x00); +#endif +#if defined(__MBED__) + t = _spi.write(0x00) << 8; + t += _spi.write(0x00); +#endif +#else + SPDR = 0x00; + waitspi(); + t = SPDR << 8; + SPDR = 0x00; + waitspi(); + t += SPDR; +#endif + sum += t; + + if (sum < t) + { + sum++; /* carry */ + } + } + + if (i == len) + { +#if ENC28J60_USE_SPILIB +#if defined(ARDUINO) + t = (SPI.transfer(0x00) << 8) + 0; +#endif +#if defined(__MBED__) + t = (_spi.write(0x00) << 8) + 0; +#endif +#else + SPDR = 0x00; + waitspi(); + t = (SPDR << 8) + 0; +#endif + sum += t; + + if (sum < t) + { + sum++; /* carry */ + } + } + + CSPASSIVE; + + /* Return sum in host byte order. */ + return sum; +} + +void +Enc28J60Network::powerOff(void) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::powerOff(void) DEBUG_V3:Function started")); +#endif + writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_RXEN); + delay(50); + writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_VRPS); + delay(50); + writeOp(ENC28J60_BIT_FIELD_SET, ECON2, ECON2_PWRSV); +} + +void +Enc28J60Network::powerOn(void) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::powerOn(void) DEBUG_V3:Function started")); +#endif + writeOp(ENC28J60_BIT_FIELD_CLR, ECON2, ECON2_PWRSV); + delay(50); + writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN); + delay(50); +} + +// read erevid from object: +uint8_t +Enc28J60Network::geterevid(void) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_str(F("Enc28J60Network::geterevid(void) DEBUG_V3:Function started and return:")); + LogObject.uart_send_decln(erevid); +#endif + return (erevid); +} + +// read the phstat2 of the chip: +uint16_t +Enc28J60Network::PhyStatus(void) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_str(F("Enc28J60Network::PhyStatus(void) DEBUG_V3:Function started")); + LogObject.uart_send_decln(erevid); +#endif + uint16_t phstat2; + phstat2 = phyRead(PHSTAT2); + + if ((phstat2 & 0x20) > 0) + { + phstat2 = phstat2 & 0x100; + } + + phstat2 = (phstat2 & 0xFF00) | erevid; + + if ((phstat2 & 0x8000) > 0) + { + phstat2 = 0; + } + + return phstat2; +} + +bool +Enc28J60Network::linkStatus(void) +{ +#if ACTLOGLEVEL>=LOG_DEBUG_V3 + LogObject.uart_send_strln(F("Enc28J60Network::linkStatus(void) DEBUG_V3:Function started")); +#endif + return (phyRead(PHSTAT2) & 0x0400) > 0; +} + +Enc28J60Network Enc28J60; diff --git a/LibraryPatches/UIPEthernet/utility/Enc28J60Network.h b/LibraryPatches/UIPEthernet/utility/Enc28J60Network.h index 8f5e446..3af4355 100644 --- a/LibraryPatches/UIPEthernet/utility/Enc28J60Network.h +++ b/LibraryPatches/UIPEthernet/utility/Enc28J60Network.h @@ -1,331 +1,332 @@ -/* - Enc28J60NetworkClass.h - UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface. - - Copyright (c) 2013 Norbert Truchsess - All rights reserved. - - inspired by enc28j60.c file from the AVRlib library by Pascal Stang. - For AVRlib See http://www.procyonengineering.com/ - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ - -#ifndef Enc28J60Network_H_ -#define Enc28J60Network_H_ - -#if defined(ESP32) - //pin SS already defined in ESP32 as pin 5, don't use this as conflict with SPIFFS, EEPROM, etc. - // Use in GPIO13 - #warning ENC28J60Network.h => use ESP32, change ENC28J60_CONTROL_CS/SS_PIN_DEFAULT to GPIO13, MOSI(23), MISO(19), SCK(18) - #define ENC28J60_CONTROL_CS 13 -#endif - -// KH, For nRF52 -#if ( defined(NRF52840_FEATHER) || defined(NRF52832_FEATHER) || defined(NRF52_SERIES) || defined(ARDUINO_NRF52_ADAFRUIT) || \ - defined(NRF52840_FEATHER_SENSE) || defined(NRF52840_ITSYBITSY) || defined(NRF52840_CIRCUITPLAY) || defined(NRF52840_CLUE) || \ - defined(NRF52840_METRO) || defined(NRF52840_PCA10056) || defined(PARTICLE_XENON) || defined(NINA_B302_ublox) || defined(NINA_B112_ublox) ) - #include - #define ENC28J60_USE_SPILIB 1 - - #ifndef USE_THIS_SS_PIN - // default to pin 10 - #define ENC28J60_CONTROL_CS 10 - #else - #warning Using USE_THIS_SS_PIN in Enc28J60Network.h for nRF52 - #define ENC28J60_CONTROL_CS USE_THIS_SS_PIN - #endif -#endif - -// KH, For SAMD21/SAMD51 -#if ( defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKR1000) || defined(ARDUINO_SAMD_MKRWIFI1010) \ - || defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_SAMD_MKRFox1200) || defined(ARDUINO_SAMD_MKRWAN1300) || defined(ARDUINO_SAMD_MKRWAN1310) \ - || defined(ARDUINO_SAMD_MKRGSM1400) || defined(ARDUINO_SAMD_MKRNB1500) || defined(ARDUINO_SAMD_MKRVIDOR4000) || defined(__SAMD21G18A__) \ - || defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) || defined(__SAMD21E18A__) || defined(__SAMD51__) || defined(__SAMD51J20A__) || defined(__SAMD51J19A__) \ - || defined(__SAMD51G19A__) || defined(__SAMD51P19A__) || defined(__SAMD21G18A__) ) - #include - #define ENC28J60_USE_SPILIB 1 - - #ifndef USE_THIS_SS_PIN - // default to pin 10 - #define ENC28J60_CONTROL_CS 10 - #else - #warning Using USE_THIS_SS_PIN in Enc28J60Network.h for SAMD - #define ENC28J60_CONTROL_CS USE_THIS_SS_PIN - #endif -#endif - -#include "mempool.h" -#if defined(__MBED__) - #include - //UIPEthernet(SPI_MOSI, SPI_MISO, SPI_SCK, SPI_CS); - #if defined(TARGET_LPC1768) - #define SPI_MOSI p11 - #define SPI_MISO p12 - #define SPI_SCK p13 - #define SPI_CS p8 - #elif defined(TARGET_LPC1114) - #define SPI_MOSI dp2 - #define SPI_MISO dp1 - #define SPI_SCK dp6 - #define SPI_CS dp25 - #elif defined(TARGET_LPC11U68) - #define SPI_MOSI P0_9 - #define SPI_MISO P0_8 - #define SPI_SCK P1_29 - #define SPI_CS P0_2 - #elif defined(TARGET_NUCLEO_F103RB) || defined(TARGET_NUCLEO_L152RE) || defined(TARGET_NUCLEO_F030R8) \ - || defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F302R8) || defined(TARGET_NUCLEO_L053R8) \ - || defined(TARGET_NUCLEO_F411RE) || defined(TARGET_NUCLEO_F334R8) || defined(TARGET_NUCLEO_F072RB) \ - || defined(TARGET_NUCLEO_F091RC) || defined(TARGET_NUCLEO_F303RE) || defined(TARGET_NUCLEO_F070RB) - #define SPI_MOSI D4 - #define SPI_MISO D5 - #define SPI_SCK D3 - #define SPI_CS D2 - #endif - #define ENC28J60_CONTROL_CS SPI_CS -#endif - -#if defined(STM32F3) || defined(STM32F2) //This is workaround for stm32duino STM32F2, and adafruit wiced feather STM32F2 - #define BOARD_SPI1_NSS_PIN PA4 - #define BOARD_SPI1_SCK_PIN PA5 - #define BOARD_SPI1_MISO_PIN PA6 - #define BOARD_SPI1_MOSI_PIN PA7 -#endif //This is workaround for stm32duino STM32F3, and adafruit wiced feather STM32F2 - -#if defined(BOARD_discovery_f4) - #define __STM32F4__ -#endif -#if defined(__MK20DX128__) || defined(__MKL26Z64__) - #include -#endif - -#if !defined(ENC28J60_CONTROL_CS) - #if defined(__AVR__) || defined(ESP8266) || defined(__RFduino__) - // Arduino Uno (__AVR__) SS defined to pin 10 - // Arduino Leonardo (ARDUINO_AVR_LEONARDO) SS defined to LED_BUILTIN_RX (17) - // Arduino Mega(__AVR_ATmega2560__) SS defined to pin 53 - // ESP8266 (ESP8266) SS defined to pin 15 - #if defined(ARDUINO_AVR_LEONARDO) || defined(ARDUINO_AVR_MICRO) - #define ENC28J60_CONTROL_CS PIN_A10 - #warning "Using LEONARDO borad PIN_A10 for ENC28J60_CONTROL_CS. Use UIPEthernet::init(uint8_t) to change it." - #else - #define ENC28J60_CONTROL_CS SS - #endif - #elif defined(ARDUINO_ARCH_AMEBA) //Defined SS to pin 10 - #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_SS0 - #elif defined(ARDUINO_ARCH_SAMD) - #define ENC28J60_CONTROL_CS SS - #elif defined(__ARDUINO_ARC__) //Intel ARC32 Genuino 101 - #define ENC28J60_CONTROL_CS SS - #elif defined(__RFduino__) //RFduino - #define ENC28J60_CONTROL_CS SS - #elif defined(ARDUINO_ARCH_STM32) // STM32duino core - #define ENC28J60_CONTROL_CS SS - #elif defined(ARDUINO_ARCH_ESP32) // arduino-esp32 - #define ENC28J60_CONTROL_CS SS - #elif defined(STM32_MCU_SERIES) || defined(__STM32F1__) || defined(__STM32F3__) || defined(STM32F3) || defined(__STM32F4__) || defined(STM32F2) - #if defined(BOARD_SPI1_NSS_PIN) - #define ENC28J60_CONTROL_CS BOARD_SPI1_NSS_PIN - #elif defined(ARDUINO_STM32F4_NETDUINO2PLUS) - #define ENC28J60_CONTROL_CS PC8 - #else - #define ENC28J60_CONTROL_CS SPI.nssPin() - //#define ENC28J60_CONTROL_CS PA4 - #endif - #elif defined(__MK20DX128__) || defined(__MKL26Z64__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__IMXRT1062__) - #define ENC28J60_CONTROL_CS PIN_SPI_SS - #endif -#endif -#if !defined(ENC28J60_CONTROL_CS) - #warning "Default ENC28J60_CONTROL_CS could not be defined! Use UIPEthernet::init(uint8_t) to set it." - #define ENC28J60_CONTROL_CS 0 -#endif - -extern uint8_t ENC28J60ControlCS; - -#if !defined(SPI_MOSI) - #if defined(__AVR__) || defined(ESP8266) || defined(__RFduino__) - #define SPI_MOSI MOSI - #elif defined(ARDUINO_ARCH_AMEBA) - #define SPI_MOSI 11 //PC_2 - #elif defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD) - #define SPI_MOSI PIN_SPI_MOSI - #elif defined(__ARDUINO_ARC__) //Intel ARC32 Genuino 101 - #define SPI_MOSI MOSI - #elif defined(__RFduino__) //RFduino - #define SPI_MOSI MOSI - #elif defined(ARDUINO_ARCH_STM32) // STM32duino core - #define SPI_MOSI MOSI - #elif defined(ARDUINO_ARCH_ESP32) // arduino-esp32 - #define SPI_MOSI MOSI - #elif defined(STM32_MCU_SERIES) || defined(__STM32F1__) || defined(__STM32F3__) || defined(STM32F3) || defined(__STM32F4__) || defined(STM32F2) - #if defined(BOARD_SPI1_MOSI_PIN) - #define SPI_MOSI BOARD_SPI1_MOSI_PIN - #else - #define SPI_MOSI SPI.mosiPin() - #endif - #elif defined(__MK20DX128__) || defined(__MKL26Z64__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__IMXRT1062__) - #define SPI_MOSI PIN_SPI_MOSI - #endif -#endif -#if !defined(SPI_MOSI) - //#error "Not defined SPI_MOSI!" - #define SPI_MOSI MOSI -#endif - -#if !defined(SPI_MISO) - #if defined(__AVR__) || defined(ESP8266) || defined(__RFduino__) - #define SPI_MISO MISO - #elif defined(ARDUINO_ARCH_AMEBA) - #define SPI_MISO 12 //PC_3 - #elif defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD) - #define SPI_MISO PIN_SPI_MISO - #elif defined(__ARDUINO_ARC__) //Intel ARC32 Genuino 101 - #define SPI_MISO MISO - #elif defined(__RFduino__) //RFduino - #define SPI_MISO MISO - #elif defined(ARDUINO_ARCH_STM32) // STM32duino core - #define SPI_MISO MISO - #elif defined(ARDUINO_ARCH_ESP32) // arduino-esp32 - #define SPI_MISO MISO - #elif defined(STM32_MCU_SERIES) || defined(__STM32F1__) || defined(__STM32F3__) || defined(STM32F3) || defined(__STM32F4__) || defined(STM32F2) - #if defined(BOARD_SPI1_MISO_PIN) - #define SPI_MISO BOARD_SPI1_MISO_PIN - #else - #define SPI_MISO SPI.misoPin() - #endif - #elif defined(__MK20DX128__) || defined(__MKL26Z64__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__IMXRT1062__) - #define SPI_MISO PIN_SPI_MISO - #endif -#endif -#if !defined(SPI_MISO) - //#error "Not defined SPI_MISO!" - #define SPI_MISO MISO -#endif -#if !defined(SPI_SCK) - #if defined(__AVR__) || defined(ESP8266) || defined(__RFduino__) - #define SPI_SCK SCK - #elif defined(ARDUINO_ARCH_AMEBA) - #define SPI_SCK 13 //PC_1 A4 - #elif defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD) - #define SPI_SCK PIN_SPI_SCK - #elif defined(__ARDUINO_ARC__) //Intel ARC32 Genuino 101 - #define SPI_SCK SCK - #elif defined(__RFduino__) //RFduino - #define SPI_SCK SCK - #elif defined(ARDUINO_ARCH_STM32) // STM32duino core - #define SPI_SCK SCK - #elif defined(ARDUINO_ARCH_ESP32) // arduino-esp32 - #define SPI_SCK SCK - #elif defined(STM32_MCU_SERIES) || defined(__STM32F1__) || defined(__STM32F3__) || defined(STM32F3) || defined(__STM32F4__) || defined(STM32F2) - #if defined(BOARD_SPI1_SCK_PIN) - #define SPI_SCK BOARD_SPI1_SCK_PIN - #else - #define SPI_SCK SPI.sckPin() - #endif - #elif defined(__MK20DX128__) || defined(__MKL26Z64__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__IMXRT1062__) - #define SPI_SCK PIN_SPI_SCK - #endif -#endif - -#if !defined(SPI_SCK) - // For nRF52 - //#error "Not defined SPI_SCK!" - #define SPI_SCK SCK -#endif - -#if defined(__MBED__) || defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD) || defined(__ARDUINO_ARC__) || defined(__STM32F1__) || defined(__STM32F3__) || defined(STM32F3) || defined(__STM32F4__) || defined(STM32F2) || defined(ESP8266) || defined(ARDUINO_ARCH_AMEBA) || defined(__MK20DX128__) || defined(__MKL26Z64__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__IMXRT1062__) || defined(__RFduino__) || defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR) - #if defined(ARDUINO) && defined(STM32F3) - #include "HardwareSPI.h" - #else - #include - #endif - #define ENC28J60_USE_SPILIB 1 -#endif - - - -#define UIP_RECEIVEBUFFERHANDLE 0xff - -/* - * Empfangen von ip-header, arp etc... - * wenn tcp/udp -> tcp/udp-callback -> assign new packet to connection - */ - -#define TX_COLLISION_RETRY_COUNT 10 - -class Enc28J60Network : public MemoryPool -{ - -private: - static uint16_t nextPacketPtr; - static uint8_t bank; - static uint8_t erevid; - - static struct memblock receivePkt; - - static bool broadcast_enabled; //!< True if broadcasts enabled (used to allow temporary disable of broadcast for DHCP or other internal functions) - - static uint8_t readOp(uint8_t op, uint8_t address); - static void writeOp(uint8_t op, uint8_t address, uint8_t data); - static uint16_t setReadPtr(memhandle handle, memaddress position, uint16_t len); - static void setERXRDPT(void); - static void readBuffer(uint16_t len, uint8_t* data); - static void writeBuffer(uint16_t len, uint8_t* data); - static uint8_t readByte(uint16_t addr); - static void writeByte(uint16_t addr, uint8_t data); - static void setBank(uint8_t address); - static uint8_t readReg(uint8_t address); - static void writeReg(uint8_t address, uint8_t data); - static void writeRegPair(uint8_t address, uint16_t data); - static void phyWrite(uint8_t address, uint16_t data); - static uint16_t phyRead(uint8_t address); - static void clkout(uint8_t clk); - - static void enableBroadcast (bool temporary); - static void disableBroadcast (bool temporary); - static void enableMulticast (void); - static void disableMulticast (void); - - static uint8_t readRegByte (uint8_t address); - static void writeRegByte (uint8_t address, uint8_t data); - - friend void enc28J60_mempool_block_move_callback(memaddress,memaddress,memaddress); - -public: - - void powerOn(void); - void powerOff(void); - static uint8_t geterevid(void); - uint16_t PhyStatus(void); - static bool linkStatus(void); - - static void init(uint8_t* macaddr); - static memhandle receivePacket(void); - static void freePacket(void); - static memaddress blockSize(memhandle handle); - static void sendPacket(memhandle handle); - static uint16_t readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len); - static uint16_t writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len); - static void copyPacket(memhandle dest, memaddress dest_pos, memhandle src, memaddress src_pos, uint16_t len); - static uint16_t chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len); -}; - -extern Enc28J60Network Enc28J60; -#endif /* Enc28J60NetworkClass_H_ */ +/* + Enc28J60NetworkClass.h + UIPEthernet network driver for Microchip ENC28J60 Ethernet Interface. + + Copyright (c) 2013 Norbert Truchsess + All rights reserved. + + inspired by enc28j60.c file from the AVRlib library by Pascal Stang. + For AVRlib See http://www.procyonengineering.com/ + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef Enc28J60Network_H_ +#define Enc28J60Network_H_ + +#if defined(ESP32) + //pin SS already defined in ESP32 as pin 5, don't use this as conflict with SPIFFS, EEPROM, etc. + // Use in GPIO13 + #warning ENC28J60Network.h => use ESP32, change ENC28J60_CONTROL_CS/SS_PIN_DEFAULT to GPIO13, MOSI(23), MISO(19), SCK(18) + #define ENC28J60_CONTROL_CS 13 +#endif + +// KH, For nRF52 +#if ( defined(NRF52840_FEATHER) || defined(NRF52832_FEATHER) || defined(NRF52_SERIES) || defined(ARDUINO_NRF52_ADAFRUIT) || \ + defined(NRF52840_FEATHER_SENSE) || defined(NRF52840_ITSYBITSY) || defined(NRF52840_CIRCUITPLAY) || defined(NRF52840_CLUE) || \ + defined(NRF52840_METRO) || defined(NRF52840_PCA10056) || defined(PARTICLE_XENON) || defined(NINA_B302_ublox) || defined(NINA_B112_ublox) ) +#include +#define ENC28J60_USE_SPILIB 1 + +#ifndef USE_THIS_SS_PIN + // default to pin 10 + #define ENC28J60_CONTROL_CS 10 +#else + #warning Using USE_THIS_SS_PIN in Enc28J60Network.h for nRF52 + #define ENC28J60_CONTROL_CS USE_THIS_SS_PIN +#endif +#endif + +// KH, For SAMD21/SAMD51 +#if ( defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKR1000) || defined(ARDUINO_SAMD_MKRWIFI1010) \ + || defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_SAMD_MKRFox1200) || defined(ARDUINO_SAMD_MKRWAN1300) || defined(ARDUINO_SAMD_MKRWAN1310) \ + || defined(ARDUINO_SAMD_MKRGSM1400) || defined(ARDUINO_SAMD_MKRNB1500) || defined(ARDUINO_SAMD_MKRVIDOR4000) || defined(__SAMD21G18A__) \ + || defined(ARDUINO_SAMD_CIRCUITPLAYGROUND_EXPRESS) || defined(__SAMD21E18A__) || defined(__SAMD51__) || defined(__SAMD51J20A__) || defined(__SAMD51J19A__) \ + || defined(__SAMD51G19A__) || defined(__SAMD51P19A__) || defined(__SAMD21G18A__) ) +#include +#define ENC28J60_USE_SPILIB 1 + +#ifndef USE_THIS_SS_PIN + // default to pin 10 + #define ENC28J60_CONTROL_CS 10 +#else + #warning Using USE_THIS_SS_PIN in Enc28J60Network.h for SAMD + #define ENC28J60_CONTROL_CS USE_THIS_SS_PIN +#endif +#endif + +#include "mempool.h" +#if defined(__MBED__) + #include + //UIPEthernet(SPI_MOSI, SPI_MISO, SPI_SCK, SPI_CS); + #if defined(TARGET_LPC1768) + #define SPI_MOSI p11 + #define SPI_MISO p12 + #define SPI_SCK p13 + #define SPI_CS p8 + #elif defined(TARGET_LPC1114) + #define SPI_MOSI dp2 + #define SPI_MISO dp1 + #define SPI_SCK dp6 + #define SPI_CS dp25 + #elif defined(TARGET_LPC11U68) + #define SPI_MOSI P0_9 + #define SPI_MISO P0_8 + #define SPI_SCK P1_29 + #define SPI_CS P0_2 + #elif defined(TARGET_NUCLEO_F103RB) || defined(TARGET_NUCLEO_L152RE) || defined(TARGET_NUCLEO_F030R8) \ + || defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F302R8) || defined(TARGET_NUCLEO_L053R8) \ + || defined(TARGET_NUCLEO_F411RE) || defined(TARGET_NUCLEO_F334R8) || defined(TARGET_NUCLEO_F072RB) \ + || defined(TARGET_NUCLEO_F091RC) || defined(TARGET_NUCLEO_F303RE) || defined(TARGET_NUCLEO_F070RB) + #define SPI_MOSI D4 + #define SPI_MISO D5 + #define SPI_SCK D3 + #define SPI_CS D2 + #endif + #define ENC28J60_CONTROL_CS SPI_CS +#endif + +#if defined(STM32F3) || defined(STM32F2) //This is workaround for stm32duino STM32F2, and adafruit wiced feather STM32F2 + #define BOARD_SPI1_NSS_PIN PA4 + #define BOARD_SPI1_SCK_PIN PA5 + #define BOARD_SPI1_MISO_PIN PA6 + #define BOARD_SPI1_MOSI_PIN PA7 +#endif //This is workaround for stm32duino STM32F3, and adafruit wiced feather STM32F2 + +#if defined(BOARD_discovery_f4) + #define __STM32F4__ +#endif +#if defined(__MK20DX128__) || defined(__MKL26Z64__) + #include +#endif + +#if !defined(ENC28J60_CONTROL_CS) + #if defined(__AVR__) || defined(ESP8266) || defined(__RFduino__) + // Arduino Uno (__AVR__) SS defined to pin 10 + // Arduino Leonardo (ARDUINO_AVR_LEONARDO) SS defined to LED_BUILTIN_RX (17) + // Arduino Mega(__AVR_ATmega2560__) SS defined to pin 53 + // ESP8266 (ESP8266) SS defined to pin 15 + #if defined(ARDUINO_AVR_LEONARDO) || defined(ARDUINO_AVR_MICRO) + #define ENC28J60_CONTROL_CS PIN_A10 + #warning "Using LEONARDO borad PIN_A10 for ENC28J60_CONTROL_CS. Use UIPEthernet::init(uint8_t) to change it." + #else + #define ENC28J60_CONTROL_CS SS + #endif + #elif defined(ARDUINO_ARCH_AMEBA) //Defined SS to pin 10 + #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_SS0 + #elif defined(ARDUINO_ARCH_SAMD) + #define ENC28J60_CONTROL_CS SS + #elif defined(__ARDUINO_ARC__) //Intel ARC32 Genuino 101 + #define ENC28J60_CONTROL_CS SS + #elif defined(__RFduino__) //RFduino + #define ENC28J60_CONTROL_CS SS + #elif defined(ARDUINO_ARCH_STM32) // STM32duino core + #define ENC28J60_CONTROL_CS SS + #elif defined(ARDUINO_ARCH_ESP32) // arduino-esp32 + #define ENC28J60_CONTROL_CS SS + #elif defined(STM32_MCU_SERIES) || defined(__STM32F1__) || defined(__STM32F3__) || defined(STM32F3) || defined(__STM32F4__) || defined(STM32F2) + #if defined(BOARD_SPI1_NSS_PIN) + #define ENC28J60_CONTROL_CS BOARD_SPI1_NSS_PIN + #elif defined(ARDUINO_STM32F4_NETDUINO2PLUS) + #define ENC28J60_CONTROL_CS PC8 + #else + #define ENC28J60_CONTROL_CS SPI.nssPin() + //#define ENC28J60_CONTROL_CS PA4 + #endif + #elif defined(__MK20DX128__) || defined(__MKL26Z64__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__IMXRT1062__) + #define ENC28J60_CONTROL_CS PIN_SPI_SS + #endif +#endif +#if !defined(ENC28J60_CONTROL_CS) + #warning "Default ENC28J60_CONTROL_CS could not be defined! Use UIPEthernet::init(uint8_t) to set it." + #define ENC28J60_CONTROL_CS 0 +#endif + +extern uint8_t ENC28J60ControlCS; + +#if !defined(SPI_MOSI) + #if defined(__AVR__) || defined(ESP8266) || defined(__RFduino__) + #define SPI_MOSI MOSI + #elif defined(ARDUINO_ARCH_AMEBA) + #define SPI_MOSI 11 //PC_2 + #elif defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD) + #define SPI_MOSI PIN_SPI_MOSI + #elif defined(__ARDUINO_ARC__) //Intel ARC32 Genuino 101 + #define SPI_MOSI MOSI + #elif defined(__RFduino__) //RFduino + #define SPI_MOSI MOSI + #elif defined(ARDUINO_ARCH_STM32) // STM32duino core + #define SPI_MOSI MOSI + #elif defined(ARDUINO_ARCH_ESP32) // arduino-esp32 + #define SPI_MOSI MOSI + #elif defined(STM32_MCU_SERIES) || defined(__STM32F1__) || defined(__STM32F3__) || defined(STM32F3) || defined(__STM32F4__) || defined(STM32F2) + #if defined(BOARD_SPI1_MOSI_PIN) + #define SPI_MOSI BOARD_SPI1_MOSI_PIN + #else + #define SPI_MOSI SPI.mosiPin() + #endif + #elif defined(__MK20DX128__) || defined(__MKL26Z64__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__IMXRT1062__) + #define SPI_MOSI PIN_SPI_MOSI + #endif +#endif +#if !defined(SPI_MOSI) + //#error "Not defined SPI_MOSI!" + #define SPI_MOSI MOSI +#endif + +#if !defined(SPI_MISO) + #if defined(__AVR__) || defined(ESP8266) || defined(__RFduino__) + #define SPI_MISO MISO + #elif defined(ARDUINO_ARCH_AMEBA) + #define SPI_MISO 12 //PC_3 + #elif defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD) + #define SPI_MISO PIN_SPI_MISO + #elif defined(__ARDUINO_ARC__) //Intel ARC32 Genuino 101 + #define SPI_MISO MISO + #elif defined(__RFduino__) //RFduino + #define SPI_MISO MISO + #elif defined(ARDUINO_ARCH_STM32) // STM32duino core + #define SPI_MISO MISO + #elif defined(ARDUINO_ARCH_ESP32) // arduino-esp32 + #define SPI_MISO MISO + #elif defined(STM32_MCU_SERIES) || defined(__STM32F1__) || defined(__STM32F3__) || defined(STM32F3) || defined(__STM32F4__) || defined(STM32F2) + #if defined(BOARD_SPI1_MISO_PIN) + #define SPI_MISO BOARD_SPI1_MISO_PIN + #else + #define SPI_MISO SPI.misoPin() + #endif + #elif defined(__MK20DX128__) || defined(__MKL26Z64__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__IMXRT1062__) + #define SPI_MISO PIN_SPI_MISO + #endif +#endif +#if !defined(SPI_MISO) + //#error "Not defined SPI_MISO!" + #define SPI_MISO MISO +#endif +#if !defined(SPI_SCK) + #if defined(__AVR__) || defined(ESP8266) || defined(__RFduino__) + #define SPI_SCK SCK + #elif defined(ARDUINO_ARCH_AMEBA) + #define SPI_SCK 13 //PC_1 A4 + #elif defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD) + #define SPI_SCK PIN_SPI_SCK + #elif defined(__ARDUINO_ARC__) //Intel ARC32 Genuino 101 + #define SPI_SCK SCK + #elif defined(__RFduino__) //RFduino + #define SPI_SCK SCK + #elif defined(ARDUINO_ARCH_STM32) // STM32duino core + #define SPI_SCK SCK + #elif defined(ARDUINO_ARCH_ESP32) // arduino-esp32 + #define SPI_SCK SCK + #elif defined(STM32_MCU_SERIES) || defined(__STM32F1__) || defined(__STM32F3__) || defined(STM32F3) || defined(__STM32F4__) || defined(STM32F2) + #if defined(BOARD_SPI1_SCK_PIN) + #define SPI_SCK BOARD_SPI1_SCK_PIN + #else + #define SPI_SCK SPI.sckPin() + #endif + #elif defined(__MK20DX128__) || defined(__MKL26Z64__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__IMXRT1062__) + #define SPI_SCK PIN_SPI_SCK + #endif +#endif + +#if !defined(SPI_SCK) + // For nRF52 + //#error "Not defined SPI_SCK!" + #define SPI_SCK SCK +#endif + +#if defined(__MBED__) || defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD) || defined(__ARDUINO_ARC__) || defined(__STM32F1__) || defined(__STM32F3__) || defined(STM32F3) || defined(__STM32F4__) || defined(STM32F2) || defined(ESP8266) || defined(ARDUINO_ARCH_AMEBA) || defined(__MK20DX128__) || defined(__MKL26Z64__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__IMXRT1062__) || defined(__RFduino__) || defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR) + #if defined(ARDUINO) && defined(STM32F3) + #include "HardwareSPI.h" + #else + #include + #endif + #define ENC28J60_USE_SPILIB 1 +#endif + + + +#define UIP_RECEIVEBUFFERHANDLE 0xff + +/* + Empfangen von ip-header, arp etc... + wenn tcp/udp -> tcp/udp-callback -> assign new packet to connection +*/ + +#define TX_COLLISION_RETRY_COUNT 10 + +class Enc28J60Network : public MemoryPool +{ + + private: + static uint16_t nextPacketPtr; + static uint8_t bank; + static uint8_t erevid; + + static struct memblock receivePkt; + + static bool + broadcast_enabled; //!< True if broadcasts enabled (used to allow temporary disable of broadcast for DHCP or other internal functions) + + static uint8_t readOp(uint8_t op, uint8_t address); + static void writeOp(uint8_t op, uint8_t address, uint8_t data); + static uint16_t setReadPtr(memhandle handle, memaddress position, uint16_t len); + static void setERXRDPT(void); + static void readBuffer(uint16_t len, uint8_t* data); + static void writeBuffer(uint16_t len, uint8_t* data); + static uint8_t readByte(uint16_t addr); + static void writeByte(uint16_t addr, uint8_t data); + static void setBank(uint8_t address); + static uint8_t readReg(uint8_t address); + static void writeReg(uint8_t address, uint8_t data); + static void writeRegPair(uint8_t address, uint16_t data); + static void phyWrite(uint8_t address, uint16_t data); + static uint16_t phyRead(uint8_t address); + static void clkout(uint8_t clk); + + static void enableBroadcast (bool temporary); + static void disableBroadcast (bool temporary); + static void enableMulticast (void); + static void disableMulticast (void); + + static uint8_t readRegByte (uint8_t address); + static void writeRegByte (uint8_t address, uint8_t data); + + friend void enc28J60_mempool_block_move_callback(memaddress, memaddress, memaddress); + + public: + + void powerOn(void); + void powerOff(void); + static uint8_t geterevid(void); + uint16_t PhyStatus(void); + static bool linkStatus(void); + + static void init(uint8_t* macaddr); + static memhandle receivePacket(void); + static void freePacket(void); + static memaddress blockSize(memhandle handle); + static void sendPacket(memhandle handle); + static uint16_t readPacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len); + static uint16_t writePacket(memhandle handle, memaddress position, uint8_t* buffer, uint16_t len); + static void copyPacket(memhandle dest, memaddress dest_pos, memhandle src, memaddress src_pos, uint16_t len); + static uint16_t chksum(uint16_t sum, memhandle handle, memaddress pos, uint16_t len); +}; + +extern Enc28J60Network Enc28J60; +#endif /* Enc28J60NetworkClass_H_ */ diff --git a/LibraryPatches/esp32/cores/esp32/Server.h b/LibraryPatches/esp32/cores/esp32/Server.h index e1e299d..2a677df 100644 --- a/LibraryPatches/esp32/cores/esp32/Server.h +++ b/LibraryPatches/esp32/cores/esp32/Server.h @@ -1,21 +1,21 @@ /* - Server.h - Base class that provides Server - Copyright (c) 2011 Adrian McEwen. All right reserved. + Server.h - Base class that provides Server + Copyright (c) 2011 Adrian McEwen. 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 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. + 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 - */ + 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 server_h #define server_h @@ -24,7 +24,7 @@ class Server: public Print { -public: + public: // KH, change to fix compiler error for EthernetWebServer // error: cannot declare field 'EthernetWebServer::_server' to be of abstract type 'EthernetServer' // virtual void begin(uint16_t port=0) =0;