/** * @file W5500.hh * @version 1.0 * * @section License * Copyright (C) 2014-2017, Mikael Patel, Daniel Sutcliffe * * 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 file is part of the Arduino Che Cosa project. */ #ifndef COSA_W5500_HH #define COSA_W5500_HH #include "Cosa/Types.h" #if !defined(BOARD_ATTINY) #include "Cosa/SPI.hh" #include "Cosa/Socket.hh" /** * Cosa WIZnet W5500 device driver class. Provides an implementation * of the Cosa Socket and Cosa IOStream::Device classes. A socket may * be bound directly to a Cosa IOStream. The device internal * transmitter buffer is used. The buffer is sent on flush (TCP/UDP) * or when full (TCP). Integrated with Cosa INET/DHCP so that the * ethernet controller may obtain a network address and information * from a DHCP server. * * @section Circuit * @code * W5500 * +------------+ * (D10)--------------29-|CSN | * (D11)--------------28-|MOSI | * (D12)--------------27-|MISO | * (D13)--------------30-|SCK | * (D2)-----[ ]-------56-|IRQ | * +------------+ * @endcode * * @section References * 1. W5500 Datasheet Version 1.0.6, December 30, 2014, * http://wizwiki.net/wiki/lib/exe/fetch.php?media=products:w5500:w5500_ds_v106e_141230.pdf * 2. W5500 Application Note 1.1 April 09, 2014, * http://wizwiki.net/wiki/lib/exe/fetch.php?media=products:w5500:w5500_ap_ipraw_v110e.pdf */ class W5500 : private SPI::Driver { public: /** * Construct W5500 device driver with given hardware address, and * chip select. * @param[in] mac hardware address (in program memory, default NULL). * @param[in] csn chip selection pin (Default D10). */ W5500(const uint8_t* mac = NULL, Board::DigitalPin csn = Board::D10); /** * Get the current network address and subnet mask. * @param[in] ip network address. * @param[in] subnet mask. */ void addr(uint8_t ip[4], uint8_t subnet[4]); /** * Get DNS network address if W5500 device driver was initiated with * hostname and obtained network address from DHCP. * @param[in,out] ip network address. */ void dns_addr(uint8_t ip[4]) { memcpy(ip, m_dns, sizeof(m_dns)); } /** * Initiate W5500 device driver with given hostname. Network address, * subnet mask and gateway should be obtained from DHCP. Returns true * if successful otherwise false. * @param[in] hostname string in program memory. * @param[in] timeout retry timeout period (Default 500 ms). * @return bool. */ bool begin_P(const char* hostname, uint16_t timeout = 500); bool begin_P(str_P hostname, uint16_t timeout = 500) { return (begin_P((const char*) hostname, timeout)); } /** * Initiate W5500 device driver with given network address and subnet * mask. Returns true if successful otherwise false. * @param[in] ip network address (Default NULL, 0.0.0.0). * @param[in] subnet mask (Default NULL, 0.0.0.0). * @param[in] timeout retry timeout period (Default 500 ms). * @return bool. */ bool begin(uint8_t ip[4] = NULL, uint8_t subnet[4] = NULL, uint16_t timeout = 500); /** * Bind to the given network address and subnet mask. Returns zero * if successful otherwise negative error code. * @param[in] ip network address. * @param[in] subnet mask. * @param[in] gateway network address (Default NULL). * @return zero if successful otherwise negative error code. */ int bind(uint8_t ip[4], uint8_t subnet[4], uint8_t gateway[4] = NULL); /** * Allocate socket with the given protocol, port and flags. Returns * pointer to socket. The socket is deallocated with Socket::close(). * @param[in] proto socket protocol. * @param[in] port number (Default 0). * @param[in] flag (Default 0). * @return socket pointer or NULL. */ Socket* socket(Socket::Protocol proto, uint16_t port = 0, uint8_t flag = 0); /** * Terminate W5500 device driver. Closes all active sockets. Return * true if successful otherwise false. */ bool end(); protected: /** * Common Registers (chap. 3.1, pp. 30), big-endian 16-bit values. */ struct CommonRegister { uint8_t MR; //!< Mode Register. uint8_t GAR[4]; //!< Gateway Address Register. uint8_t SUBR[4]; //!< Subnet mask Address Register. uint8_t SHAR[6]; //!< Source Hardware Address Register. uint8_t SIPR[4]; //!< Source IP Address Register. uint16_t INTLEVEL; //!< Interrupt Low level Timer. uint8_t IR; //!< Interrupt Register. uint8_t IMR; //!< Interrupt Mask Register. uint8_t SIR; //!< Socket Interrupt Register. uint8_t SIMR; //!< Socket Interrupt Mask Register. uint16_t RTR; //!< Retry Time Register. uint8_t RCR; //!< Retry Count Register. uint8_t PTIMER; //!< PPP LCP Request Timer Register. uint8_t PMAGIC; //!< PPP LCP Magic number. uint8_t PHAR[6]; //!< PPP Destination MAC Address uint16_t PSID; //!< PPP Session Identification. uint16_t PMRU; //!< PPP Maximum Segment Size. uint8_t UIPR[4]; //!< Unreachable IP Address Register uint16_t UPORTR; //!< Unreachable Port Register uint8_t PHYCFGR; //!< PHY COnfiguration uint8_t reserved[10]; //!< Reserved uint8_t VERSIONR; //!< Chip Version }; /** * Mode Register bitfields, pp. 33-34. */ enum { MR_RST = 0x80, //!< S/W Reset. MR_WOL = 0x20, //!< Wake on LAN MR_PB = 0x10, //!< Ping Block Mode. MR_PPPoE = 0x08, //!< PPPoE Mode. MR_FARP = 0x02 //!< Force ARP } __attribute__((packed)); /** * Interrupt Register bitfields, pp. 36. */ enum { IR_CONFLICT = 0x80, //!< IP Conflict. IR_UNREACH = 0x40, //!< Destination Unreachable IR_PPPoE = 0x20, //!< PPPoE Connection Close. IR_MP = 0x10 //!< Magic Packet } __attribute__((packed)); /* * Interrupt Mask Register bitfields, pp. 37. */ enum { IMR_CONFLICT = 0x80, //