diff --git a/libraries/Ethernet/src/utility/socket.cpp b/libraries/Ethernet/src/utility/socket.cpp index 9254b7439e7..54dc162b240 100644 --- a/libraries/Ethernet/src/utility/socket.cpp +++ b/libraries/Ethernet/src/utility/socket.cpp @@ -362,7 +362,7 @@ uint16_t recvfrom(SOCKET s, uint8_t *buf, uint16_t len, uint8_t *addr, uint16_t /** * @brief Wait for buffered transmission to complete. */ -void flush(SOCKET s) { +void flush(SOCKET /* s */) { // TODO } diff --git a/libraries/Ethernet/src/utility/w5100.cpp b/libraries/Ethernet/src/utility/w5100.cpp index f616d0634ea..4c940cac921 100644 --- a/libraries/Ethernet/src/utility/w5100.cpp +++ b/libraries/Ethernet/src/utility/w5100.cpp @@ -12,17 +12,18 @@ #include "w5100.h" -// W5100 controller instance -W5100Class W5100; +// W5x00 controller instance +W5x00Class W5100; + +uint8_t W5x00Class::chipset = W5x00Chipset::W5100; +uint8_t W5x00Class::sockets = 4; +uint16_t W5x00Class::CH_BASE = 0; #define TX_RX_MAX_BUF_SIZE 2048 #define TX_BUF 0x1100 #define RX_BUF (TX_BUF + TX_RX_MAX_BUF_SIZE) -#define TXBUF_BASE 0x4000 -#define RXBUF_BASE 0x6000 - -void W5100Class::init(void) +void W5x00Class::init(void) { delay(300); @@ -31,80 +32,145 @@ void W5100Class::init(void) initSS(); #else SPI.begin(ETHERNET_SHIELD_SPI_CS); - // Set clock to 4Mhz (W5100 should support up to about 14Mhz) - SPI.setClockDivider(ETHERNET_SHIELD_SPI_CS, 21); - SPI.setDataMode(ETHERNET_SHIELD_SPI_CS, SPI_MODE0); #endif + + /* + * Runtime detection of Wiznet Chip. + * Based on code from: https://github.com/jbkim/Differentiate-WIznet-Chip + */ + uint8_t testW5200[] = { 0x00, 0x1F, 0x00, 0x01, 0x00 }; + uint8_t testW5500[] = { 0x00, 0x39, 0x00, 0x00 }; SPI.beginTransaction(SPI_ETHERNET_SETTINGS); - writeMR(1< SSIZE) - { - // Wrap around circular buffer - uint16_t size = SSIZE - offset; - write(dstAddr, data, size); - write(SBASE[s], data + size, len - size); - } - else { - write(dstAddr, data, len); + if (chipset != W5x00Chipset::W5500) { + uint16_t offset = ptr & SMASK; + uint16_t dstAddr = offset + SBASE[s]; + if (offset + len > SSIZE) + { + // Wrap around circular buffer + uint16_t size = SSIZE - offset; + write(dstAddr, 0x00, data, size); + write(SBASE[s], 0x00, data + size, len - size); + } else { + write(dstAddr, 0x00, data, len); + } + } else { + write(ptr, (s<<5) + 0x14, data, len); } ptr += len; writeSnTX_WR(s, ptr); } - -void W5100Class::recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek) +void W5x00Class::recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uint8_t peek) { - uint16_t ptr; - ptr = readSnRX_RD(s); + uint16_t ptr = readSnRX_RD(s); read_data(s, ptr, data, len); if (!peek) { @@ -113,113 +179,258 @@ void W5100Class::recv_data_processing(SOCKET s, uint8_t *data, uint16_t len, uin } } -void W5100Class::read_data(SOCKET s, volatile uint16_t src, volatile uint8_t *dst, uint16_t len) +void W5x00Class::read_data(SOCKET s, uint16_t src, uint8_t *dst, uint16_t len) { - uint16_t size; - uint16_t src_mask; - uint16_t src_ptr; - - src_mask = src & RMASK; - src_ptr = RBASE[s] + src_mask; - - if( (src_mask + len) > RSIZE ) - { - size = RSIZE - src_mask; - read(src_ptr, (uint8_t *)dst, size); - dst += size; - read(RBASE[s], (uint8_t *) dst, len - size); - } - else - read(src_ptr, (uint8_t *) dst, len); + if (chipset != W5x00Chipset::W5500) { + uint16_t src_mask = src & RMASK; + uint16_t src_ptr = RBASE[s] + src_mask; + if ((src_mask + len) > RSIZE) { + uint16_t size = RSIZE - src_mask; + read(src_ptr, 0x00, dst, size); + dst += size; + read(RBASE[s], 0x00, dst, len - size); + } else { + read(src_ptr, 0x00, dst, len); + } + } else { + read(src, (s<<5) + 0x18, dst, len); + } } -uint8_t W5100Class::write(uint16_t _addr, uint8_t _data) +uint8_t W5x00Class::write(uint16_t _addr, uint8_t _cb, uint8_t _data) { #if !defined(SPI_HAS_EXTENDED_CS_PIN_HANDLING) - setSS(); - SPI.transfer(0xF0); - SPI.transfer(_addr >> 8); - SPI.transfer(_addr & 0xFF); - SPI.transfer(_data); + setSS(); + if (chipset == W5x00Chipset::W5100) { + SPI.transfer(0xF0); + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + SPI.transfer(_data); + } else if (chipset == W5x00Chipset::W5200) { + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + SPI.transfer(0x80); + SPI.transfer(0x01); + SPI.transfer(_data); + } else { + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + SPI.transfer(_cb); + SPI.transfer(_data); + } resetSS(); #else - SPI.transfer(ETHERNET_SHIELD_SPI_CS, 0xF0, SPI_CONTINUE); - SPI.transfer(ETHERNET_SHIELD_SPI_CS, _addr >> 8, SPI_CONTINUE); - SPI.transfer(ETHERNET_SHIELD_SPI_CS, _addr & 0xFF, SPI_CONTINUE); - SPI.transfer(ETHERNET_SHIELD_SPI_CS, _data); + if (chipset == W5x00Chipset::W5100) { + SPI.transfer(ETHERNET_SHIELD_SPI_CS, 0xF0, SPI_CONTINUE); + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _addr & 0xFF, SPI_CONTINUE); + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _data); + } else if (chipset == W5x00Chipset::W5200) { + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _addr & 0xFF, SPI_CONTINUE); + SPI.transfer(ETHERNET_SHIELD_SPI_CS, 0x80, SPI_CONTINUE); + SPI.transfer(ETHERNET_SHIELD_SPI_CS, 0x01, SPI_CONTINUE); + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _data); + } else { + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _addr & 0xFF, SPI_CONTINUE); + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _cb, SPI_CONTINUE); + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _data); + } #endif return 1; } -uint16_t W5100Class::write(uint16_t _addr, const uint8_t *_buf, uint16_t _len) +uint16_t W5x00Class::write(uint16_t _addr, uint8_t _cb, const uint8_t *_buf, uint16_t _len) { - for (uint16_t i=0; i<_len; i++) - { #if !defined(SPI_HAS_EXTENDED_CS_PIN_HANDLING) - setSS(); - SPI.transfer(0xF0); + if (chipset == W5x00Chipset::W5100) { + 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 (chipset == W5x00Chipset::W5200) { + if (_len == 0) + return 0; + setSS(); SPI.transfer(_addr >> 8); SPI.transfer(_addr & 0xFF); - _addr++; - SPI.transfer(_buf[i]); + SPI.transfer(0x80 | ((_len & 0x7F00) >> 8)); + SPI.transfer(_len & 0xFF); + for (uint16_t i=0; i<_len; i++) { + SPI.transfer(_buf[i]); + } resetSS(); + } else { + setSS(); + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + SPI.transfer(_cb); + for (uint16_t i=0; i<_len; i++) { + SPI.transfer(_buf[i]); + } + resetSS(); + } #else - SPI.transfer(ETHERNET_SHIELD_SPI_CS, 0xF0, SPI_CONTINUE); + uint16_t i; + if (chipset == W5x00Chipset::W5100) { + for (i=0; i<_len; i++) + { + SPI.transfer(ETHERNET_SHIELD_SPI_CS, 0xF0, SPI_CONTINUE); + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _addr & 0xFF, SPI_CONTINUE); + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _buf[i]); + _addr++; + } + } else if (chipset == W5x00Chipset::W5200) { + if (_len == 0) + return 0; SPI.transfer(ETHERNET_SHIELD_SPI_CS, _addr >> 8, SPI_CONTINUE); SPI.transfer(ETHERNET_SHIELD_SPI_CS, _addr & 0xFF, SPI_CONTINUE); + SPI.transfer(ETHERNET_SHIELD_SPI_CS, 0x80 | ((_len & 0x7F00) >> 8), SPI_CONTINUE); + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _len & 0xFF, SPI_CONTINUE); + for (i=0; i<_len-1; i++) { + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _buf[i], SPI_CONTINUE); + } + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _buf[i]); + } else { + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _addr & 0xFF, SPI_CONTINUE); + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _cb, SPI_CONTINUE); + for (i=0; i<_len-1; i++) { + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _buf[i], SPI_CONTINUE); + } SPI.transfer(ETHERNET_SHIELD_SPI_CS, _buf[i]); - _addr++; -#endif } +#endif return _len; } -uint8_t W5100Class::read(uint16_t _addr) +uint8_t W5x00Class::read(uint16_t _addr, uint8_t _cb) { + uint8_t res; #if !defined(SPI_HAS_EXTENDED_CS_PIN_HANDLING) - setSS(); - SPI.transfer(0x0F); - SPI.transfer(_addr >> 8); - SPI.transfer(_addr & 0xFF); - uint8_t _data = SPI.transfer(0); + setSS(); + if (chipset == W5x00Chipset::W5100) { + SPI.transfer(0x0F); + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + res = SPI.transfer(0); + } else if (chipset == W5x00Chipset::W5200) { + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + SPI.transfer(0x00); + SPI.transfer(0x01); + res = SPI.transfer(0); + } else { + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + SPI.transfer(_cb); + res = SPI.transfer(0); + } resetSS(); #else - SPI.transfer(ETHERNET_SHIELD_SPI_CS, 0x0F, SPI_CONTINUE); - SPI.transfer(ETHERNET_SHIELD_SPI_CS, _addr >> 8, SPI_CONTINUE); - SPI.transfer(ETHERNET_SHIELD_SPI_CS, _addr & 0xFF, SPI_CONTINUE); - uint8_t _data = SPI.transfer(ETHERNET_SHIELD_SPI_CS, 0); + if (chipset == W5x00Chipset::W5100) { + SPI.transfer(ETHERNET_SHIELD_SPI_CS, 0x0F, SPI_CONTINUE); + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _addr & 0xFF, SPI_CONTINUE); + res = SPI.transfer(ETHERNET_SHIELD_SPI_CS, 0); + } else if (chipset == W5x00Chipset::W5200) { + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _addr & 0xFF, SPI_CONTINUE); + SPI.transfer(ETHERNET_SHIELD_SPI_CS, 0x00, SPI_CONTINUE); + SPI.transfer(ETHERNET_SHIELD_SPI_CS, 0x01, SPI_CONTINUE); + res = SPI.transfer(ETHERNET_SHIELD_SPI_CS, 0); + } else { + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _addr & 0xFF, SPI_CONTINUE); + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _cb, SPI_CONTINUE); + uint8_t _data = SPI.transfer(ETHERNET_SHIELD_SPI_CS, 0); + } #endif - return _data; + return res; } -uint16_t W5100Class::read(uint16_t _addr, uint8_t *_buf, uint16_t _len) +uint16_t W5x00Class::read(uint16_t _addr, uint8_t _cb, uint8_t *_buf, uint16_t _len) { - for (uint16_t i=0; i<_len; i++) - { #if !defined(SPI_HAS_EXTENDED_CS_PIN_HANDLING) + if (chipset == W5x00Chipset::W5100) { + for (uint16_t i=0; i<_len; i++) + { + setSS(); + SPI.transfer(0x0F); + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + _addr++; + _buf[i] = SPI.transfer(0); + resetSS(); + } + } else if (chipset == W5x00Chipset::W5200) { + setSS(); + SPI.transfer(_addr >> 8); + SPI.transfer(_addr & 0xFF); + SPI.transfer((_len & 0x7F00) >> 8); + SPI.transfer(_len & 0xFF); + for (uint16_t i=0; i<_len; i++){ + _buf[i] = SPI.transfer(0); + } + resetSS(); + } else { setSS(); - SPI.transfer(0x0F); SPI.transfer(_addr >> 8); SPI.transfer(_addr & 0xFF); - _addr++; - _buf[i] = SPI.transfer(0); + SPI.transfer(_cb); + for (uint16_t i=0; i<_len; i++){ + _buf[i] = SPI.transfer(0); + } resetSS(); + } #else - SPI.transfer(ETHERNET_SHIELD_SPI_CS, 0x0F, SPI_CONTINUE); + uint16_t i; + if (chipset == W5x00Chipset::W5100) { + for (i=0; i<_len; i++) + { + SPI.transfer(ETHERNET_SHIELD_SPI_CS, 0x0F, SPI_CONTINUE); + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _addr & 0xFF, SPI_CONTINUE); + _buf[i] = SPI.transfer(ETHERNET_SHIELD_SPI_CS, 0); + _addr++; + } + } else if (chipset == W5x00Chipset::W5200) { SPI.transfer(ETHERNET_SHIELD_SPI_CS, _addr >> 8, SPI_CONTINUE); SPI.transfer(ETHERNET_SHIELD_SPI_CS, _addr & 0xFF, SPI_CONTINUE); - _buf[i] = SPI.transfer(ETHERNET_SHIELD_SPI_CS, 0); - _addr++; -#endif + SPI.transfer(ETHERNET_SHIELD_SPI_CS, (_len & 0x7F00) >> 8, SPI_CONTINUE); + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _len & 0xFF, SPI_CONTINUE); + for (i=0; i<_len-1; i++){ + _buf[i] = SPI.transfer(ETHERNET_SHIELD_SPI_CS, 0, SPI_CONTINUE); + } + _buf[_len-1] = SPI.transfer(ETHERNET_SHIELD_SPI_CS, 0); + } else { + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _addr >> 8, SPI_CONTINUE); + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _addr & 0xFF, SPI_CONTINUE); + SPI.transfer(ETHERNET_SHIELD_SPI_CS, _cb, SPI_CONTINUE); + for (i=0; i<_len-1; i++){ + _buf[i] = SPI.transfer(ETHERNET_SHIELD_SPI_CS, 0, SPI_CONTINUE); + } + _buf[_len-1] = SPI.transfer(ETHERNET_SHIELD_SPI_CS, 0); } +#endif + return _len; } -void W5100Class::execCmdSn(SOCKET s, SockCMD _cmd) { +void W5x00Class::execCmdSn(SOCKET s, SockCMD _cmd) { // Send command to socket writeSnCR(s, _cmd); // Wait for command to complete while (readSnCR(s)) ; } + diff --git a/libraries/Ethernet/src/utility/w5100.h b/libraries/Ethernet/src/utility/w5100.h index 15de01c8383..ebb7fb6ac28 100644 --- a/libraries/Ethernet/src/utility/w5100.h +++ b/libraries/Ethernet/src/utility/w5100.h @@ -7,15 +7,13 @@ * published by the Free Software Foundation. */ -#ifndef W5100_H_INCLUDED -#define W5100_H_INCLUDED +#ifndef W5x00_H_INCLUDED +#define W5x00_H_INCLUDED #include #define ETHERNET_SHIELD_SPI_CS 10 -#define MAX_SOCK_NUM 4 - typedef uint8_t SOCKET; #define IDM_OR 0x8000 @@ -127,7 +125,14 @@ class IPPROTO { static const uint8_t RAW = 255; }; -class W5100Class { +class W5x00Chipset { +public: + static const uint8_t W5100 = 0; + static const uint8_t W5200 = 1; + static const uint8_t W5500 = 2; +}; + +class W5x00Class { public: void init(); @@ -139,7 +144,7 @@ class W5100Class { * the data from Receive buffer. Here also take care of the condition while it exceed * the Rx memory uper-bound of socket. */ - void read_data(SOCKET s, volatile uint16_t src, volatile uint8_t * dst, uint16_t len); + void read_data(SOCKET s, uint16_t src, uint8_t *dst, uint16_t len); /** * @brief This function is being called by send() and sendto() function also. @@ -148,6 +153,7 @@ class W5100Class { * register. User should read upper byte first and lower byte later to get proper value. */ void send_data_processing(SOCKET s, const uint8_t *data, uint16_t len); + /** * @brief A copy of send_data_processing that uses the provided ptr for the * write offset. Only needed for the "streaming" UDP API, where @@ -158,7 +164,6 @@ class W5100Class { * in from TX_WR * @return New value for ptr, to be used in the next call */ -// FIXME Update documentation void send_data_processing_offset(SOCKET s, uint16_t data_offset, const uint8_t *data, uint16_t len); /** @@ -190,63 +195,73 @@ class W5100Class { uint16_t getTXFreeSize(SOCKET s); uint16_t getRXReceivedSize(SOCKET s); + inline uint8_t getMaxSockets() { return sockets; } - // W5100 Registers +private: + static uint8_t chipset; + static uint8_t sockets; + + // W5x00 Registers // --------------- private: - static uint8_t write(uint16_t _addr, uint8_t _data); - static uint16_t write(uint16_t addr, const uint8_t *buf, uint16_t len); - static uint8_t read(uint16_t addr); - static uint16_t read(uint16_t addr, uint8_t *buf, uint16_t len); + static uint8_t write(uint16_t _addr, uint8_t _cb, uint8_t _data); + static uint16_t write(uint16_t addr, uint8_t _cb, const uint8_t *buf, uint16_t len); + static uint8_t read(uint16_t addr, uint8_t _cb); + static uint16_t read(uint16_t addr, uint8_t _cb, uint8_t *buf, uint16_t len); #define __GP_REGISTER8(name, address) \ static inline void write##name(uint8_t _data) { \ - write(address, _data); \ + write(address, 0x04, _data); \ } \ static inline uint8_t read##name() { \ - return read(address); \ + return read(address, 0x00); \ } #define __GP_REGISTER16(name, address) \ static void write##name(uint16_t _data) { \ - write(address, _data >> 8); \ - write(address+1, _data & 0xFF); \ + write(address, 0x04, _data >> 8); \ + write(address+1, 0x04, _data & 0xFF); \ } \ static uint16_t read##name() { \ - uint16_t res = read(address); \ - res = (res << 8) + read(address + 1); \ + uint16_t res = read(address, 0x00); \ + res = (res << 8) + read(address + 1, 0x00); \ return res; \ } #define __GP_REGISTER_N(name, address, size) \ static uint16_t write##name(uint8_t *_buff) { \ - return write(address, _buff, size); \ + return write(address, 0x04, _buff, size); \ } \ static uint16_t read##name(uint8_t *_buff) { \ - return read(address, _buff, size); \ + return read(address, 0x00, _buff, size); \ } 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 - __GP_REGISTER8 (TMSR, 0x001B); // Transmit memory size - __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 - __GP_REGISTER16(UPORT, 0x002E); // Unreachable Port address in UDP mode - + __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_W5100_W5200, 0x0017); // Timeout address + __GP_REGISTER16(RTR_W5500, 0x0019); // Timeout address + __GP_REGISTER8 (RCR_W5100_W5200, 0x0019); // Retry count + __GP_REGISTER8 (RCR_W5500, 0x001B); // Retry count + __GP_REGISTER8 (RMSR, 0x001A); // Receive memory size + __GP_REGISTER8 (TMSR, 0x001B); // Transmit memory size + __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_W5100_W5200, 0x002A, 4); // Unreachable IP address in UDP mode + __GP_REGISTER_N(UIPR_W5500, 0x0028, 4); // Unreachable IP address in UDP mode + __GP_REGISTER16(UPORT_W5100_W5200, 0x002E); // Unreachable Port address in UDP mode + __GP_REGISTER16(UPORT_W5500, 0x002C); // Unreachable Port address in UDP mode + __GP_REGISTER8 (PHYCFGR_W5500, 0x002E); // PHY Configuration register, default value: 0b 1011 1xxx + #undef __GP_REGISTER8 #undef __GP_REGISTER16 #undef __GP_REGISTER_N - // W5100 Socket registers + // W5x00 Socket registers // ---------------------- private: static inline uint8_t readSn(SOCKET _s, uint16_t _addr); @@ -254,7 +269,7 @@ class W5100Class { static inline uint16_t readSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len); static inline uint16_t writeSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len); - static const uint16_t CH_BASE = 0x0400; + static uint16_t CH_BASE; static const uint16_t CH_SIZE = 0x0100; #define __SOCKET_REGISTER8(name, address) \ @@ -286,24 +301,26 @@ class W5100Class { } 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_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?) + __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(SnRXBUF_SIZE, 0x001E) // RX Buffer Size + __SOCKET_REGISTER8(SnTXBUF_SIZE, 0x001F) // TX Buffer Size + __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 @@ -313,114 +330,108 @@ class W5100Class { private: static const uint8_t RST = 7; // Reset BIT - static const int SOCKETS = 4; static const uint16_t SMASK = 0x07FF; // Tx buffer MASK static const uint16_t RMASK = 0x07FF; // Rx buffer MASK public: static const uint16_t SSIZE = 2048; // Max Tx buffer size private: static const uint16_t RSIZE = 2048; // Max Rx buffer size - uint16_t SBASE[SOCKETS]; // Tx buffer base address - uint16_t RBASE[SOCKETS]; // Rx buffer base address + uint16_t SBASE[8]; // Tx buffer base address + uint16_t RBASE[8]; // Rx buffer base address private: + // W5100 supports up to 14Mhz #if !defined(SPI_HAS_EXTENDED_CS_PIN_HANDLING) - #define SPI_ETHERNET_SETTINGS SPISettings(4000000, MSBFIRST, SPI_MODE0) - #if defined(ARDUINO_ARCH_AVR) - #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) - inline static void initSS() { DDRB |= _BV(4); }; - inline static void setSS() { PORTB &= ~_BV(4); }; - inline static void resetSS() { PORTB |= _BV(4); }; - #elif defined(__AVR_ATmega32U4__) - inline static void initSS() { DDRB |= _BV(6); }; - inline static void setSS() { PORTB &= ~_BV(6); }; - inline static void resetSS() { PORTB |= _BV(6); }; - #elif defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB162__) - inline static void initSS() { DDRB |= _BV(0); }; - inline static void setSS() { PORTB &= ~_BV(0); }; - inline static void resetSS() { PORTB |= _BV(0); }; - #else - inline static void initSS() { DDRB |= _BV(2); }; - inline static void setSS() { PORTB &= ~_BV(2); }; - inline static void resetSS() { PORTB |= _BV(2); }; - #endif - #elif defined(__ARDUINO_ARC__) - inline static void initSS() { pinMode(10, OUTPUT); }; - inline static void setSS() { digitalWrite(10, LOW); }; - inline static void resetSS() { digitalWrite(10, HIGH); }; + #define SPI_ETHERNET_SETTINGS SPISettings(14000000, MSBFIRST, SPI_MODE0) + #if defined(__ARDUINO_ARC__) + inline static void initSS() { pinMode(ETHERNET_SHIELD_SPI_CS, OUTPUT); } + inline static void setSS() { digitalWrite(ETHERNET_SHIELD_SPI_CS, LOW); } + inline static void resetSS() { digitalWrite(ETHERNET_SHIELD_SPI_CS, HIGH); } #else - inline static void initSS() { - *portModeRegister(digitalPinToPort(ETHERNET_SHIELD_SPI_CS)) |= digitalPinToBitMask(ETHERNET_SHIELD_SPI_CS); - } - inline static void setSS() { - *portOutputRegister(digitalPinToPort(ETHERNET_SHIELD_SPI_CS)) &= ~digitalPinToBitMask(ETHERNET_SHIELD_SPI_CS); - } - inline static void resetSS() { - *portOutputRegister(digitalPinToPort(ETHERNET_SHIELD_SPI_CS)) |= digitalPinToBitMask(ETHERNET_SHIELD_SPI_CS); - } + inline static void initSS() { pinMode(ETHERNET_SHIELD_SPI_CS, OUTPUT); } + inline static void setSS() { *portOutputRegister(digitalPinToPort(ETHERNET_SHIELD_SPI_CS)) &= ~digitalPinToBitMask(ETHERNET_SHIELD_SPI_CS); } + inline static void resetSS() { *portOutputRegister(digitalPinToPort(ETHERNET_SHIELD_SPI_CS)) |= digitalPinToBitMask(ETHERNET_SHIELD_SPI_CS); } #endif #else - #define SPI_ETHERNET_SETTINGS ETHERNET_SHIELD_SPI_CS,SPISettings(4000000, MSBFIRST, SPI_MODE0) + #define SPI_ETHERNET_SETTINGS ETHERNET_SHIELD_SPI_CS,SPISettings(14000000, MSBFIRST, SPI_MODE0) // initSS(), setSS(), resetSS() not needed with EXTENDED_CS_PIN_HANDLING #endif }; -extern W5100Class W5100; +extern W5x00Class W5100; -uint8_t W5100Class::readSn(SOCKET _s, uint16_t _addr) { - return read(CH_BASE + _s * CH_SIZE + _addr); +uint8_t W5x00Class::readSn(SOCKET _s, uint16_t _addr) { + if (chipset != W5x00Chipset::W5500) + return read(CH_BASE + _s * CH_SIZE + _addr, 0x00); + else + return read(_addr, (_s<<5) + 0x08); } -uint8_t W5100Class::writeSn(SOCKET _s, uint16_t _addr, uint8_t _data) { - return write(CH_BASE + _s * CH_SIZE + _addr, _data); +uint8_t W5x00Class::writeSn(SOCKET _s, uint16_t _addr, uint8_t _data) { + if (chipset != W5x00Chipset::W5500) + return write(CH_BASE + _s * CH_SIZE + _addr, 0x00, _data); + else + return write(_addr, (_s<<5) + 0x0C, _data); } -uint16_t W5100Class::readSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len) { - return read(CH_BASE + _s * CH_SIZE + _addr, _buf, _len); +uint16_t W5x00Class::readSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len) { + if (chipset != W5x00Chipset::W5500) + return read(CH_BASE + _s * CH_SIZE + _addr, 0x00, _buf, _len); + else + return read(_addr, (_s<<5) + 0x08, _buf, _len); } -uint16_t W5100Class::writeSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len) { - return write(CH_BASE + _s * CH_SIZE + _addr, _buf, _len); +uint16_t W5x00Class::writeSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len) { + if (chipset != W5x00Chipset::W5500) + return write(CH_BASE + _s * CH_SIZE + _addr, 0x00, _buf, _len); + else + return write(_addr, (_s<<5) + 0x0C, _buf, _len); } -void W5100Class::getGatewayIp(uint8_t *_addr) { +void W5x00Class::getGatewayIp(uint8_t *_addr) { readGAR(_addr); } -void W5100Class::setGatewayIp(uint8_t *_addr) { +void W5x00Class::setGatewayIp(uint8_t *_addr) { writeGAR(_addr); } -void W5100Class::getSubnetMask(uint8_t *_addr) { +void W5x00Class::getSubnetMask(uint8_t *_addr) { readSUBR(_addr); } -void W5100Class::setSubnetMask(uint8_t *_addr) { +void W5x00Class::setSubnetMask(uint8_t *_addr) { writeSUBR(_addr); } -void W5100Class::getMACAddress(uint8_t *_addr) { +void W5x00Class::getMACAddress(uint8_t *_addr) { readSHAR(_addr); } -void W5100Class::setMACAddress(uint8_t *_addr) { +void W5x00Class::setMACAddress(uint8_t *_addr) { writeSHAR(_addr); } -void W5100Class::getIPAddress(uint8_t *_addr) { +void W5x00Class::getIPAddress(uint8_t *_addr) { readSIPR(_addr); } -void W5100Class::setIPAddress(uint8_t *_addr) { +void W5x00Class::setIPAddress(uint8_t *_addr) { writeSIPR(_addr); } -void W5100Class::setRetransmissionTime(uint16_t _timeout) { - writeRTR(_timeout); +void W5x00Class::setRetransmissionTime(uint16_t _timeout) { + if (chipset != W5x00Chipset::W5500) + writeRTR_W5100_W5200(_timeout); + else + writeRTR_W5500(_timeout); } -void W5100Class::setRetransmissionCount(uint8_t _retry) { - writeRCR(_retry); +void W5x00Class::setRetransmissionCount(uint8_t _retry) { + if (chipset != W5x00Chipset::W5500) + writeRCR_W5100_W5200(_retry); + else + writeRCR_W5500(_retry); } #endif