Mbed library for ENC28J60 Ethernet modules. Full support for TCP/IP and UDP Server, Client and HTTP server (webserver). DHCP and DNS is included.

Dependents:   mBuino_ENC28_MQTT Nucleo_Web_ENC28J60 Nucleo_Web_ENC28J60_ADC Serial_over_Ethernet ... more

Library for ENC28J60 Ethernet modules.

/media/uploads/hudakz/enc28j60_module01.jpg

Ported to mbed from Norbert Truchsess's UIPEthernet library for Arduino. Thank you Norbert!

  • Full support for persistent (streaming) TCP/IP and UDP connections Client and Server each, ARP, ICMP, DHCP and DNS.
  • Works with both Mbed OS 2 and Mbed OS 5.

Usage:

  • Import the library into your project.
  • Add #include "UipEthernet.h" to main.cpp
  • Create one instance of the UipEthernet class initialized with the MAC address you'd like to use and SPI pins of the connected Mbed board.

Example programs:

Import programWebSwitch_ENC28J60

HTTP Server serving a simple webpage which enables to remotely turn a digital output on/off. Compile, download, run and type 'IP_address/secret/' (don't forget the last '/') into your web browser and hit ENTER.

Import programHTTPServer_Echo_ENC28J60

A simple HTTP server echoing received requests. Ethernet connection is over an ENC28J60 board. Usage: Type the server's IP address into you web browser and hit <ENTER>.

Import programTcpServer_ENC28J60

Simple TCP/IP Server using the UIPEthernet library for ENC28J60 Ethernet boards.

Import programTcpClient_ENC28J60

Simple TCP/IP Client using the UIPEthernet library for ENC28J60 Ethernet boards.

Import programUdpServer_ENC28J60

Simple UDP Server using the UIPEthernet library for ENC28J60 Ethernet boards.

Import programUdpClient_ENC28J60

Simple UDP Client using the UIPEthernet library for ENC28J60 Ethernet boards.

Import programMQTT_Hello_ENC28J60

MQTT Client example program. Ethernet connection is via an ENC28J60 module.

Revision:
8:4acb22344932
Parent:
4:d774541a34da
--- a/UIPEthernet.cpp	Tue Apr 26 18:37:14 2016 +0000
+++ b/UIPEthernet.cpp	Fri Jun 30 19:51:28 2017 +0000
@@ -1,5 +1,5 @@
 /*
- UIPEthernet.cpp - Arduino implementation of a uIP wrapper class.
+ UIPEthernet.cpp - Arduino implementation of a UIP wrapper class.
  Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de>
  All rights reserved.
 
@@ -18,13 +18,9 @@
  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
   */
-#include <mbed.h>
+#include "mbed.h"
 #include "UIPEthernet.h"
 #include "utility/Enc28J60Network.h"
-
-#if (defined UIPETHERNET_DEBUG || defined UIPETHERNET_DEBUG_CHKSUM)
-    #include "HardwareSerial.h"
-#endif
 #include "UIPUdp.h"
 
 extern "C"
@@ -37,15 +33,15 @@
 }
 #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);
+memhandle       UIPEthernet::in_packet(NOBLOCK);
+memhandle       UIPEthernet::uip_packet(NOBLOCK);
+uint8_t         UIPEthernet::uip_hdrlen(0);
+uint8_t         UIPEthernet::packetstate(0);
 
-IPAddress UIPEthernetClass::        _dnsServerAddress;
-DhcpClass* UIPEthernetClass::       _dhcp(NULL);
+IPAddress       UIPEthernet::_dnsServerAddress;
+DhcpClass*      UIPEthernet::_dhcp(NULL);
 
-unsigned long UIPEthernetClass::    periodic_timer;
+unsigned long   UIPEthernet::periodic_timer;
 
 /**
  * @brief
@@ -55,60 +51,57 @@
  */
 void enc28J60_mempool_block_move_callback(memaddress dest, memaddress src, memaddress len) {
 
-    //void
+    //as ENC28J60 DMA is unable to copy single bytes:
 
-    //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) {
-        UIPEthernet.network.writeByte(dest, UIPEthernet.network.readByte(src));
+    if (len == 1) {
+        uIPEthernet.network.writeByte(dest, uIPEthernet.network.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.
+        /* 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.
        */
-        UIPEthernet.network.writeRegPair(EDMASTL, src);
-        UIPEthernet.network.writeRegPair(EDMADSTL, dest);
+        uIPEthernet.network.writeRegPair(EDMASTL, src);
+        uIPEthernet.network.writeRegPair(EDMADSTL, dest);
 
-        if((src <= RXSTOP_INIT) && (len > RXSTOP_INIT))
+        if ((src <= RXSTOP_INIT) && (len > RXSTOP_INIT))
             len -= (RXSTOP_INIT - RXSTART_INIT);
-        UIPEthernet.network.writeRegPair(EDMANDL, len);
+        uIPEthernet.network.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.
+        /* 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. */
-        UIPEthernet.network.writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_CSUMEN);
+           3. Verify that ECON1.CSUMEN is clear. */
+        uIPEthernet.network.writeOp(ENC28J60_BIT_FIELD_CLR, ECON1, ECON1_CSUMEN);
 
         /* 4. Start the DMA copy by setting ECON1.DMAST. */
-        UIPEthernet.network.writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_DMAST);
+        uIPEthernet.network.writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_DMAST);
 
-        // wait until runnig DMA is completed
-        while(UIPEthernet.network.readOp(ENC28J60_READ_CTRL_REG, ECON1) & ECON1_DMAST);
+        //    wait until runnig DMA is completed
+        while (uIPEthernet.network.readOp(ENC28J60_READ_CTRL_REG, ECON1) & ECON1_DMAST);
     }
 }
 
-// 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(PinName mosi, PinName miso, PinName sck, PinName cs) :
+/*
+ * 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.
+ */
+UIPEthernet::UIPEthernet(PinName mosi, PinName miso, PinName sck, PinName cs) :
     network(mosi, miso, sck, cs) {
     millis_start();
 }
@@ -121,8 +114,9 @@
  * @param
  * @retval
  */
-int UIPEthernetClass::begin(const uint8_t* mac) {
+int UIPEthernet::begin(const uint8_t* mac) {
     static DhcpClass    s_dhcp;
+
     _dhcp = &s_dhcp;
 
     // Initialise the basic info
@@ -130,7 +124,8 @@
 
     // Now try to get our config info from a DHCP server
     int ret = _dhcp->beginWithDHCP((uint8_t*)mac);
-    if(ret == 1) {
+
+    if (ret == 1) {
 
         // We've successfully found a DHCP server and got our configuration info, so set things
         // accordingly
@@ -147,8 +142,9 @@
  * @param
  * @retval
  */
-void UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip) {
+void UIPEthernet::begin(const uint8_t* mac, IPAddress ip) {
     IPAddress   dns = ip;
+
     dns[3] = 1;
     begin(mac, ip, dns);
 }
@@ -159,8 +155,9 @@
  * @param
  * @retval
  */
-void UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns) {
+void UIPEthernet::begin(const uint8_t* mac, IPAddress ip, IPAddress dns) {
     IPAddress   gateway = ip;
+
     gateway[3] = 1;
     begin(mac, ip, dns, gateway);
 }
@@ -171,8 +168,9 @@
  * @param
  * @retval
  */
-void UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway) {
+void UIPEthernet::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway) {
     IPAddress   subnet(255, 255, 255, 0);
+
     begin(mac, ip, dns, gateway, subnet);
 }
 
@@ -182,7 +180,7 @@
  * @param
  * @retval
  */
-void UIPEthernetClass::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) {
+void UIPEthernet::begin(const uint8_t* mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) {
     init(mac);
     configure(ip, dns, gateway, subnet);
 }
@@ -193,29 +191,30 @@
  * @param
  * @retval
  */
-int UIPEthernetClass::maintain(void) {
+int UIPEthernet::maintain(void) {
     tick();
 
     int rc = DHCP_CHECK_NONE;
+
 #if UIP_UDP
-    if(_dhcp != NULL) {
+    if (_dhcp != NULL) {
 
         //we have a pointer to dhcp, use it
         rc = _dhcp->checkLease();
-        switch(rc) {
-        case DHCP_CHECK_NONE:
-            //nothing done
-            break;
+        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;
+            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;
+            default:
+                //this is actually an error, it will retry though
+                break;
         }
     }
 
@@ -229,9 +228,9 @@
  * @param
  * @retval
  */
-IPAddress UIPEthernetClass::localIP(void) {
-    IPAddress       ret;
+IPAddress UIPEthernet::localIP(void) {
     uip_ipaddr_t    a;
+
     uip_gethostaddr(a);
     return ip_addr_uip(a);
 }
@@ -242,9 +241,9 @@
  * @param
  * @retval
  */
-IPAddress UIPEthernetClass::subnetMask(void) {
-    IPAddress       ret;
+IPAddress UIPEthernet::subnetMask(void) {
     uip_ipaddr_t    a;
+
     uip_getnetmask(a);
     return ip_addr_uip(a);
 }
@@ -255,9 +254,9 @@
  * @param
  * @retval
  */
-IPAddress UIPEthernetClass::gatewayIP(void) {
-    IPAddress       ret;
+IPAddress UIPEthernet::gatewayIP(void) {
     uip_ipaddr_t    a;
+
     uip_getdraddr(a);
     return ip_addr_uip(a);
 }
@@ -268,7 +267,7 @@
  * @param
  * @retval
  */
-IPAddress UIPEthernetClass::dnsServerIP(void) {
+IPAddress UIPEthernet::dnsServerIP(void) {
     return _dnsServerAddress;
 }
 
@@ -278,344 +277,320 @@
  * @param
  * @retval
  */
-void UIPEthernetClass::tick(void)
-{
-    if(in_packet == NOBLOCK) {
+void UIPEthernet::tick(void) {
+    if (in_packet == NOBLOCK) {
         in_packet = network.receivePacket();
 #ifdef UIPETHERNET_DEBUG
-        if(in_packet != NOBLOCK) {
-            Serial.print(F("--------------\nreceivePacket: "));
-            Serial.println(in_packet);
+        if (in_packet != NOBLOCK) {
+            printf("--------------\r\nreceivePacket: %d\r\n", in_packet);
         }
 #endif
     }
-    if(in_packet != NOBLOCK) {
+
+    if (in_packet != NOBLOCK) {
         packetstate = UIPETHERNET_FREEPACKET;
         uip_len = network.blockSize(in_packet);
-        if(uip_len > 0) {
+        if (uip_len > 0) {
             network.readPacket(in_packet, 0, (uint8_t*)uip_buf, UIP_BUFSIZE);
-            if(ETH_HDR->type == HTONS(UIP_ETHTYPE_IP)) {
+            if (ETH_HDR->type == HTONS(UIP_ETHTYPE_IP)) {
                 uip_packet = in_packet; //required for upper_layer_checksum of in_packet!
 #ifdef UIPETHERNET_DEBUG
-                Serial.print(F("readPacket type IP, uip_len: "));
-                Serial.println(uip_len);
+                printf("readPacket type IP, uip_len: %d\r\n", uip_len);
 #endif
                 uip_arp_ipin();
                 uip_input();
-                if(uip_len > 0) {
+                if (uip_len > 0) {
                     uip_arp_out();
                     network_send();
                 }
             }
             else
-            if(ETH_HDR->type == HTONS(UIP_ETHTYPE_ARP))
+            if (ETH_HDR->type == HTONS(UIP_ETHTYPE_ARP))
             {
 #ifdef UIPETHERNET_DEBUG
-                Serial.print(F("readPacket type ARP, uip_len: "));
-                Serial.println(uip_len);
+                printf("readPacket type ARP, uip_len: %d\r\n", uip_len);
 #endif
                 uip_arp_arpin();
-                if(uip_len > 0) {
+                if (uip_len > 0) {
                     network_send();
                 }
             }
         }
-        if(in_packet != NOBLOCK && (packetstate & UIPETHERNET_FREEPACKET))
+
+        if (in_packet != NOBLOCK && (packetstate & UIPETHERNET_FREEPACKET))
         {
 #ifdef UIPETHERNET_DEBUG
-            Serial.print(F("freeing packet: "));
-            Serial.println(in_packet);
+            printf("freeing packet: %d\r\n", in_packet);
 #endif
             network.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++) {
+        uip_conn = &uip_conns[i];
+        if (periodic) {
+            uip_process(UIP_TIMER);
+        }
+        else {
+            if ((long)(now - ((uip_userdata_t*)uip_conn->appstate)->timer) >= 0)
+                uip_process(UIP_POLL_REQUEST);
+            else
+                continue;
+        }
 
-            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((long)(now - ((uip_userdata_t*)uip_conn->appstate)->timer) >= 0)
-                        uip_process(UIP_POLL_REQUEST);
-                    else
-                        continue;
-                }
-#endif
-                // If the above function invocation resulted in data that
+        // 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();
+        }
+    }
 
-                // 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 (periodic) {
+        periodic_timer = now + UIP_PERIODIC_TIMER;
 #if UIP_UDP
-                for(int i = 0; i < UIP_UDP_CONNS; i++) {
-                    uip_udp_periodic(i);
+        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 */
+            // 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
+    }
+}
 
-        /**
+/**
  * @brief
  * @note
  * @param
  * @retval
  */
-        bool UIPEthernetClass::network_send(void) {
-            if(packetstate & UIPETHERNET_SENDPACKET)
-            {
+bool UIPEthernet::network_send(void) {
+    if (packetstate & UIPETHERNET_SENDPACKET)
+    {
 #ifdef UIPETHERNET_DEBUG
-                Serial.print(F("Enc28J60Network_send uip_packet: "));
-                Serial.print(uip_packet);
-                Serial.print(F(", hdrlen: "));
-                Serial.println(uip_hdrlen);
+        printf("Enc28J60Network_send uip_packet: %d, hdrlen: %d\r\n", uip_packet, uip_hdrlen);
 #endif
-                UIPEthernet.network.writePacket(uip_packet, 0, uip_buf, uip_hdrlen);
-                packetstate &= ~UIPETHERNET_SENDPACKET;
-                goto sendandfree;
-            }
+        uIPEthernet.network.writePacket(uip_packet, 0, uip_buf, uip_hdrlen);
+        packetstate &= ~UIPETHERNET_SENDPACKET;
+        goto sendandfree;
+    }
 
-            uip_packet = Enc28J60Network::allocBlock(uip_len);
-            if(uip_packet != NOBLOCK)
-            {
+    uip_packet = Enc28J60Network::allocBlock(uip_len);
+    if (uip_packet != NOBLOCK)
+    {
 #ifdef UIPETHERNET_DEBUG
-                Serial.print(F("Enc28J60Network_send uip_buf (uip_len): "));
-                Serial.print(uip_len);
-                Serial.print(F(", packet: "));
-                Serial.println(uip_packet);
+        printf("Enc28J60Network_send uip_buf (uip_len): %d, packet: %d\r\n", uip_len, uip_packet);
 #endif
-                UIPEthernet.network.writePacket(uip_packet, 0, uip_buf, uip_len);
-                goto sendandfree;
-            }
+        uIPEthernet.network.writePacket(uip_packet, 0, uip_buf, uip_len);
+        goto sendandfree;
+    }
 
-            return false;
+    return false;
 sendandfree:
-            network.sendPacket(uip_packet);
-            Enc28J60Network::freeBlock(uip_packet);
-            uip_packet = NOBLOCK;
-            return true;
-        }
+    network.sendPacket(uip_packet);
+    Enc28J60Network::freeBlock(uip_packet);
+    uip_packet = NOBLOCK;
+    return true;
+}
 
-        /**
+/**
  * @brief
  * @note
  * @param
  * @retval
  */
-        void UIPEthernetClass::init(const uint8_t* mac) {
-            periodic_timer = millis() + UIP_PERIODIC_TIMER;
+void UIPEthernet::init(const uint8_t* mac) {
+    periodic_timer = millis() + UIP_PERIODIC_TIMER;
 
-            network.init((uint8_t*)mac);
-            uip_seteth_addr(mac);
+    network.init((uint8_t*)mac);
+    uip_seteth_addr(mac);
 
-            uip_init();
-            uip_arp_init();
-        }
+    uip_init();
+    uip_arp_init();
+}
 
-        /**
+/**
  * @brief
  * @note
  * @param
  * @retval
  */
-        void UIPEthernetClass::configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) {
-            uip_ipaddr_t    ipaddr;
-
-            uip_ip_addr(ipaddr, ip);
-            uip_sethostaddr(ipaddr);
+void UIPEthernet::configure(IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet) {
+    uip_ipaddr_t    ipaddr;
 
-            uip_ip_addr(ipaddr, gateway);
-            uip_setdraddr(ipaddr);
-
-            uip_ip_addr(ipaddr, subnet);
-            uip_setnetmask(ipaddr);
+    uip_ip_addr(ipaddr, ip);
+    uip_sethostaddr(ipaddr);
 
-            _dnsServerAddress = dns;
-        }
-
-        //UIPEthernetClass UIPEthernet;
+    uip_ip_addr(ipaddr, gateway);
+    uip_setdraddr(ipaddr);
 
-        /*---------------------------------------------------------------------------*/
-        uint16_t UIPEthernetClass::chksum(uint16_t sum, const uint8_t* data, uint16_t len) {
-            uint16_t        t;
-            const uint8_t*  dataptr;
-            const uint8_t*  last_byte;
+    uip_ip_addr(ipaddr, subnet);
+    uip_setnetmask(ipaddr);
 
-            dataptr = data;
-            last_byte = data + len - 1;
-
-            while(dataptr < last_byte) {
+    _dnsServerAddress = dns;
+}
 
-                /* At least two more bytes */
-                t = (dataptr[0] << 8) + dataptr[1];
-                sum += t;
-                if(sum < t) {
-                    sum++;  /* carry */
-                }
-
-                dataptr += 2;
-            }
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+uint16_t UIPEthernet::chksum(uint16_t sum, const uint8_t* data, uint16_t len) {
+    uint16_t        t;
+    const uint8_t*  dataptr;
+    const uint8_t*  last_byte;
 
-            if(dataptr == last_byte) {
-                t = (dataptr[0] << 8) + 0;
-                sum += t;
-                if(sum < t) {
-                    sum++;  /* carry */
-                }
-            }
+    dataptr = data;
+    last_byte = data + len - 1;
+
+    while (dataptr < last_byte) {
 
-            /* Return sum in host byte order. */
-            return sum;
-        }
-
-        /*---------------------------------------------------------------------------*/
-        uint16_t UIPEthernetClass::ipchksum(void) {
-            uint16_t    sum;
-
-            sum = chksum(0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN);
-            return(sum == 0) ? 0xffff : htons(sum);
+        /* At least two more bytes */
+        t = (dataptr[0] << 8) + dataptr[1];
+        sum += t;
+        if (sum < t) {
+            sum++;  /* carry */
         }
 
-        /*---------------------------------------------------------------------------*/
-        uint16_t
-#if UIP_UDP
-        UIPEthernetClass::upper_layer_chksum(uint8_t proto)
-#else
-        uip_tcpchksum (void)
-#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;
+        dataptr += 2;
+    }
 
-            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);
-#ifdef UIPETHERNET_DEBUG_CHKSUM
-            Serial.print(F("chksum uip_buf["));
-            Serial.print(UIP_IPH_LEN + UIP_LLH_LEN);
-            Serial.print(F("-"));
-            Serial.print(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen);
-            Serial.print(F("]: "));
-            Serial.println(htons(sum), HEX);
-#endif
-            if(upper_layer_memlen < upper_layer_len) {
-                sum = network.chksum
-                    (
-                        sum, UIPEthernetClass::uip_packet, UIP_IPH_LEN +
-                        UIP_LLH_LEN +
-                        upper_layer_memlen, upper_layer_len -
-                        upper_layer_memlen
-                    );
-#ifdef UIPETHERNET_DEBUG_CHKSUM
-                Serial.print(F("chksum uip_packet("));
-                Serial.print(uip_packet);
-                Serial.print(F(")["));
-                Serial.print(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen);
-                Serial.print(F("-"));
-                Serial.print(UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_len);
-                Serial.print(F("]: "));
-                Serial.println(htons(sum), HEX);
-#endif
-            }
-            return(sum == 0) ? 0xffff : htons(sum);
+    if (dataptr == last_byte) {
+        t = (dataptr[0] << 8) + 0;
+        sum += t;
+        if (sum < t) {
+            sum++;  /* carry */
         }
+    }
 
-        /**
+    /* Return sum in host byte order. */
+    return sum;
+}
+
+/**
  * @brief
  * @note
  * @param
  * @retval
  */
-        uint16_t uip_ipchksum(void) {
-            return UIPEthernet.ipchksum();
-        }
+uint16_t UIPEthernet::ipchksum(void) {
+    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
+UIPEthernet::upper_layer_chksum(uint8_t proto)
+#else
+uip_tcpchksum (void)
+#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 = UIPEthernet::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 = UIPEthernet::chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], upper_layer_memlen);
+#ifdef UIPETHERNET_DEBUG_CHKSUM
+    printf("chksum uip_buf[%d-%d]: %d\r\n", UIP_IPH_LEN + UIP_LLH_LEN, UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen, htons(sum));
+#endif
+    if (upper_layer_memlen < upper_layer_len) {
+        sum = network.chksum
+            (
+                sum, UIPEthernet::uip_packet, UIP_IPH_LEN +
+                UIP_LLH_LEN +
+                upper_layer_memlen, upper_layer_len -
+                upper_layer_memlen
+            );
+#ifdef UIPETHERNET_DEBUG_CHKSUM
+        printf("chksum uip_packet(%d)[%d-%d]: %d\r\n", uip_packet, UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_memlen, UIP_IPH_LEN + UIP_LLH_LEN + upper_layer_len, htons(sum));
+#endif
+    }
+    return(sum == 0) ? 0xffff : htons(sum);
+}
+
+/**
  * @brief
  * @note
  * @param
  * @retval
  */
-        uint16_t uip_tcpchksum(void) {
-            uint16_t    sum = UIPEthernet.upper_layer_chksum(UIP_PROTO_TCP);
-            return sum;
-        }
+uint16_t uip_ipchksum(void) {
+    return uIPEthernet.ipchksum();
+}
 
-        /**
+#if UIP_UDP
+
+/**
  * @brief
  * @note
  * @param
  * @retval
  */
-        uint16_t uip_udpchksum(void) {
-            uint16_t    sum = UIPEthernet.upper_layer_chksum(UIP_PROTO_UDP);
-            return sum;
-        }
+uint16_t uip_tcpchksum(void) {
+    uint16_t    sum = uIPEthernet.upper_layer_chksum(UIP_PROTO_TCP);
+
+    return sum;
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+uint16_t uip_udpchksum(void) {
+    uint16_t    sum = uIPEthernet.upper_layer_chksum(UIP_PROTO_UDP);
+
+    return sum;
+}
 #endif
+