diff --git a/keywords.txt b/keywords.txt index 9fd25419..188c907f 100644 --- a/keywords.txt +++ b/keywords.txt @@ -65,3 +65,4 @@ EthernetNoHardware LITERAL1 EthernetW5100 LITERAL1 EthernetW5200 LITERAL1 EthernetW5500 LITERAL1 +EthernetW6100 LITERAL1 diff --git a/src/Ethernet.cpp b/src/Ethernet.cpp index 9257090c..65bd3c28 100644 --- a/src/Ethernet.cpp +++ b/src/Ethernet.cpp @@ -121,6 +121,7 @@ EthernetHardwareStatus EthernetClass::hardwareStatus() case 51: return EthernetW5100; case 52: return EthernetW5200; case 55: return EthernetW5500; + case 61: return EthernetW6100; default: return EthernetNoHardware; } } diff --git a/src/Ethernet.h b/src/Ethernet.h index 745fa4a3..16175028 100644 --- a/src/Ethernet.h +++ b/src/Ethernet.h @@ -63,7 +63,8 @@ enum EthernetHardwareStatus { EthernetNoHardware, EthernetW5100, EthernetW5200, - EthernetW5500 + EthernetW5500, + EthernetW6100 }; class EthernetUDP; diff --git a/src/EthernetUdp.cpp b/src/EthernetUdp.cpp index e28791f6..b4e18a2a 100644 --- a/src/EthernetUdp.cpp +++ b/src/EthernetUdp.cpp @@ -108,19 +108,54 @@ int EthernetUDP::parsePacket() if (Ethernet.socketRecvAvailable(sockindex) > 0) { //HACK - hand-parse the UDP packet using TCP recv method - uint8_t tmpBuf[8]; + uint8_t tmpBuf[20]; int ret=0; - //read 8 header bytes and get IP and port from it - ret = Ethernet.socketRecv(sockindex, tmpBuf, 8); - if (ret > 0) { - _remoteIP = tmpBuf; - _remotePort = tmpBuf[4]; - _remotePort = (_remotePort << 8) + tmpBuf[5]; - _remaining = tmpBuf[6]; - _remaining = (_remaining << 8) + tmpBuf[7]; - - // When we get here, any remaining bytes are the data - ret = _remaining; + + if(W5100.getChip() == 61) { + //read 2 header bytes and get one IPv4 or IPv6 + ret = Ethernet.socketRecv(sockindex, tmpBuf, 2); + if(ret > 0) { + _remaining = (tmpBuf[0] & (0x7))<<8 | tmpBuf[1]; + + if((tmpBuf[0] & W6100_UDP_HEADER_IPV) == W6100_UDP_HEADER_IPV6) { + // IPv6 UDP Received + // 0 1 + // 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 + // 18 19 + + //read 16 header bytes and get IP and port from it + ret = Ethernet.socketRecv(sockindex, &tmpBuf[2], 18); + _remoteIP = &tmpBuf[2]; + _remotePort = (tmpBuf[18]<<8) | tmpBuf[19]; + } else { + // IPv4 UDP Received + // 0 1 + // 2 3 4 5 + // 6 7 + + //read 6 header bytes and get IP and port from it + ret = Ethernet.socketRecv(sockindex, &tmpBuf[2], 6); + _remoteIP = &tmpBuf[2]; + _remotePort = (tmpBuf[6]<<8) | tmpBuf[7]; + } + + ret = _remaining; + } + } else { + //read 8 header bytes and get IP and port from it + ret = Ethernet.socketRecv(sockindex, tmpBuf, 8); + + if (ret > 0) { + + _remoteIP = tmpBuf; + _remotePort = tmpBuf[4]; + _remotePort = (_remotePort << 8) + tmpBuf[5]; + _remaining = tmpBuf[6]; + _remaining = (_remaining << 8) + tmpBuf[7]; + + // When we get here, any remaining bytes are the data + ret = _remaining; + } } return ret; } diff --git a/src/utility/w5100.cpp b/src/utility/w5100.cpp index 07fcc313..ad68ab5b 100644 --- a/src/utility/w5100.cpp +++ b/src/utility/w5100.cpp @@ -52,6 +52,7 @@ // W5100 controller instance uint8_t W5100Class::chip = 0; uint8_t W5100Class::CH_BASE_MSB; +uint16_t W5100Class::CH_SIZE; uint8_t W5100Class::ss_pin = SS_PIN_DEFAULT; #ifdef ETHERNET_LARGE_BUFFERS uint16_t W5100Class::SSIZE = 2048; @@ -100,6 +101,8 @@ uint8_t W5100Class::init(void) // reset time, this can be edited or removed. delay(560); //Serial.println("w5100 init"); + + CH_SIZE = 0x0100; // Default except W6100 SPI.begin(); initSS(); @@ -182,6 +185,30 @@ uint8_t W5100Class::init(void) #else writeTMSR(0x55); writeRMSR(0x55); +#endif + // Try W6100. Brandnew based W5500. + } else if (isW6100()) { + CH_BASE_MSB = 0x60; + CH_SIZE = 0x0400; // W6100 +#ifdef ETHERNET_LARGE_BUFFERS +#if MAX_SOCK_NUM <= 1 + SSIZE = 16384; +#elif MAX_SOCK_NUM <= 2 + SSIZE = 8192; +#elif MAX_SOCK_NUM <= 4 + SSIZE = 4096; +#else + 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); + } #endif // No hardware seems to be present. Or it could be a W5200 // that's heard other SPI communication if its chip select @@ -201,19 +228,67 @@ uint8_t W5100Class::init(void) uint8_t W5100Class::softReset(void) { uint16_t count=0; + uint8_t sysr; + + if(chip == 61) { + writeCHPLCKR_W6100(W6100_CHPLCKR_UNLOCK); // Unlock SYSR[CHPL] + count = 0; + do{ // Wait Unlock Complete + if(++count > 20) { // Check retry count + return 0; // Over Limit retry count + } + } while ((readSYSR_W6100() & W6100_SYSR_CHPL_LOCK) ^ W6100_SYSR_CHPL_ULOCK); // Exit Wait Unlock Complete - //Serial.println("WIZnet soft reset"); - // write to reset bit - writeMR(0x80); - // then wait for soft reset to complete - do { - uint8_t mr = readMR(); - //Serial.print("mr="); - //Serial.println(mr, HEX); - if (mr == 0) return 1; - delay(1); - } while (++count < 20); - return 0; + writeSYCR0(0x0); // Software Reset + + do{ // Wait Lock Complete + if(++count > 20) { // Check retry count + return 0; // Over Limit retry count + } + + } while ((readSYSR_W6100() & W6100_SYSR_CHPL_LOCK) ^ W6100_SYSR_CHPL_LOCK); // Exit Wait Lock Complete + + return 1; + } else { + count = 0; + + //Serial.println("Wiznet soft reset"); + // write to reset bit + writeMR(0x80); + // then wait for soft reset to complete + do { + uint8_t mr = readMR(); + //Serial.print("mr="); + //Serial.println(mr, HEX); + if (mr == 0) return 1; + delay(1); + } while (++count < 20); + return 0; + } +} + +uint8_t W5100Class::isW6100(void) +{ + chip = 61; + CH_BASE_MSB = 0x80; + + if (!softReset()) return 0; + + // Unlock + writeCHPLCKR_W6100(W6100_CHPLCKR_UNLOCK); + writeNETLCKR_W6100(W6100_NETLCKR_UNLOCK); + writePHYLCKR_W6100(W6100_PHYLCKR_UNLOCK); + + // W6100 CIDR0 + // Version 97(dec) 0x61(hex) + int ver = readVERSIONR_W6100(); + + //Serial.print("version = 0x"); + //Serial.println(ver, HEX); + + if (ver != 97) return 0; + //Serial.println("chip is W6100"); + return 1; } uint8_t W5100Class::isW5100(void) @@ -287,6 +362,12 @@ W5100Linkstatus W5100Class::getLinkStatus() SPI.endTransaction(); if (phystatus & 0x01) return LINK_ON; return LINK_OFF; + case 61: + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + phystatus = readPHYCFGR_W6100(); + SPI.endTransaction(); + if (phystatus & 0x01) return LINK_ON; + return LINK_OFF; default: return UNKNOWN; } @@ -322,6 +403,89 @@ uint16_t W5100Class::write(uint16_t addr, const uint8_t *buf, uint16_t len) } #endif resetSS(); + } else if (chip == 61) { // chip == 61 + setSS(); + + if (addr < CH_BASE()) { + // common registers + + cmd[0] = (addr>>8) & 0x7F; + cmd[1] = addr & 0xFF; + cmd[2] = W6100_SPI_FRAME_CTL_BSB_BLK(0) + | W6100_SPI_FRAME_CTL_BSB_COMM + | W6100_SPI_FRAME_CTL_WD + | W6100_SPI_FRAME_CTL_OPM_VDM + ; + } else if (addr < W6100_TX_BASE_ADDR) { + // socket registers + + cmd[0] = (addr>>8) & 0x3; + cmd[1] = addr & 0xFF; + cmd[2] = W6100_SPI_FRAME_CTL_BSB_BLK((addr>>10)&0x7) + | W6100_SPI_FRAME_CTL_BSB_SOCK + | W6100_SPI_FRAME_CTL_WD + | W6100_SPI_FRAME_CTL_OPM_VDM + ; + } else if (addr < W6100_RX_BASE_ADDR) { + // transmit buffers + + cmd[0] = addr>>8; + cmd[1] = addr & 0xFF; + + #if defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 1 + cmd[2] = 0; // 16K buffers + #elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 2 + cmd[2] = ((addr >> 8) & 0x20); // 8K buffers + #elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 4 + cmd[2] = ((addr >> 7) & 0x60); // 4K buffers + #else + cmd[2] = ((addr >> 6) & 0xE0); // 2K buffers + #endif + + cmd[2] |= W6100_SPI_FRAME_CTL_BSB_BLK(0) + | W6100_SPI_FRAME_CTL_BSB_TXBF + | W6100_SPI_FRAME_CTL_WD + | W6100_SPI_FRAME_CTL_OPM_VDM + ; + } else { + // receive buffers + + cmd[0] = addr>>8; + cmd[1] = addr & 0xFF; + + #if defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 1 + cmd[2] = 0; // 16K buffers + #elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 2 + cmd[2] = ((addr >> 8) & 0x20); // 8K buffers + #elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 4 + cmd[2] = ((addr >> 7) & 0x60); // 4K buffers + #else + cmd[2] = ((addr >> 6) & 0xE0); // 2K buffers + #endif + + cmd[2] |= W6100_SPI_FRAME_CTL_BSB_BLK(0) + | W6100_SPI_FRAME_CTL_BSB_RXBF + | W6100_SPI_FRAME_CTL_WD + | W6100_SPI_FRAME_CTL_OPM_VDM + ; + } + 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); +#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) { @@ -417,6 +581,76 @@ uint16_t W5100Class::read(uint16_t addr, uint8_t *buf, uint16_t len) memset(buf, 0, len); SPI.transfer(buf, len); resetSS(); + } else if (chip == 61) { // chip == 61 + setSS(); + + if (addr < CH_BASE()) { + // common registers + + cmd[0] = (addr>>8) & 0x7F; + cmd[1] = addr & 0xFF; + cmd[2] = W6100_SPI_FRAME_CTL_BSB_BLK(0) + | W6100_SPI_FRAME_CTL_BSB_COMM + | W6100_SPI_FRAME_CTL_RD + | W6100_SPI_FRAME_CTL_OPM_VDM + ; + } else if (addr < W6100_TX_BASE_ADDR) { + // socket registers + + cmd[0] = (addr>>8) & 0x3; + cmd[1] = addr & 0xFF; + cmd[2] = W6100_SPI_FRAME_CTL_BSB_BLK((addr>>10)&0x7) + | W6100_SPI_FRAME_CTL_BSB_SOCK + | W6100_SPI_FRAME_CTL_RD + | W6100_SPI_FRAME_CTL_OPM_VDM + ; + } else if (addr < W6100_RX_BASE_ADDR) { + // transmit buffers + + cmd[0] = addr>>8; + cmd[1] = addr & 0xFF; + + #if defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 1 + cmd[2] = 0; // 16K buffers + #elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 2 + cmd[2] = ((addr >> 8) & 0x20); // 8K buffers + #elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 4 + cmd[2] = ((addr >> 7) & 0x60); // 4K buffers + #else + cmd[2] = ((addr >> 6) & 0xE0); // 2K buffers + #endif + + cmd[2] |= W6100_SPI_FRAME_CTL_BSB_BLK(0) + | W6100_SPI_FRAME_CTL_BSB_TXBF + | W6100_SPI_FRAME_CTL_RD + | W6100_SPI_FRAME_CTL_OPM_VDM + ; + } else { + // receive buffers + + cmd[0] = addr>>8; + cmd[1] = addr & 0xFF; + + #if defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 1 + cmd[2] = 0; // 16K buffers + #elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 2 + cmd[2] = ((addr >> 8) & 0x20); // 8K buffers + #elif defined(ETHERNET_LARGE_BUFFERS) && MAX_SOCK_NUM <= 4 + cmd[2] = ((addr >> 7) & 0x60); // 4K buffers + #else + cmd[2] = ((addr >> 6) & 0xE0); // 2K buffers + #endif + + cmd[2] |= W6100_SPI_FRAME_CTL_BSB_BLK(0) + | W6100_SPI_FRAME_CTL_BSB_RXBF + | W6100_SPI_FRAME_CTL_RD + | W6100_SPI_FRAME_CTL_OPM_VDM + ; + } + SPI.transfer(cmd, 3); + memset(buf, 0, len); + SPI.transfer(buf, len); + resetSS(); } else { // chip == 55 setSS(); if (addr < 0x100) { diff --git a/src/utility/w5100.h b/src/utility/w5100.h index b2e8ec83..60f73223 100644 --- a/src/utility/w5100.h +++ b/src/utility/w5100.h @@ -161,56 +161,127 @@ class W5100Class { return data; } -#define __GP_REGISTER8(name, address) \ - static inline void write##name(uint8_t _data) { \ - write(address, _data); \ +#define W6100_SPI_FRAME_CTL_BSB_BLK(sn) ((sn)<<5) + +#define W6100_SPI_FRAME_CTL_BSB_COMM (0<<3) +#define W6100_SPI_FRAME_CTL_BSB_SOCK (1<<3) +#define W6100_SPI_FRAME_CTL_BSB_TXBF (2<<3) +#define W6100_SPI_FRAME_CTL_BSB_RXBF (3<<3) + +#define W6100_SPI_FRAME_CTL_RD (0<<2) +#define W6100_SPI_FRAME_CTL_WD (1<<2) + +#define W6100_SPI_FRAME_CTL_OPM_VDM (0<<0) +#define W6100_SPI_FRAME_CTL_OPM_FDM1 (1<<0) +#define W6100_SPI_FRAME_CTL_OPM_FDM2 (2<<0) +#define W6100_SPI_FRAME_CTL_OPM_FDM4 (3<<0) + +#define W6100_COMMON_BASE_ADDR (0x0000) +#define W6100_SOCKET_BASE_ADDR (0x6000) +#define W6100_TX_BASE_ADDR (0x8000) +#define W6100_RX_BASE_ADDR (0xC000) +#define W6100_SOCKET_NUM(_s) ((_s)<<10)) + +#define W6100_CHPLCKR_UNLOCK 0xCE +#define W6100_NETLCKR_UNLOCK 0x3A +#define W6100_PHYLCKR_UNLOCK 0x53 + +#define W6100_SYSR_CHPL_LOCK (1<<7) +#define W6100_SYSR_CHPL_ULOCK (0<<7) + +#define W6100_UDP_HEADER_IPV (1<<7) +#define W6100_UDP_HEADER_IPV4 (0<<7) +#define W6100_UDP_HEADER_IPV6 (1<<7) +#define W6100_UDP_HEADER_ALL (1<<6) +#define W6100_UDP_HEADER_MUL (1<<5) +#define W6100_UDP_HEADER_GUA (0<<3) +#define W6100_UDP_HEADER_LLA (1<<3) + +#define __GP_REGISTER8(name, address, adrss_w6100) \ + static inline void write##name(uint8_t _data) { \ + if(chip == 61) { \ + write(adrss_w6100, _data); \ + } else { \ + write(address, _data); \ + } \ } \ static inline uint8_t read##name() { \ - return read(address); \ - } -#define __GP_REGISTER16(name, address) \ + if(chip == 61) { \ + return read(adrss_w6100); \ + } else { \ + return read(address); \ + } \ + } \ + +#define __GP_REGISTER16(name, address, adrss_w6100) \ static void write##name(uint16_t _data) { \ uint8_t buf[2]; \ buf[0] = _data >> 8; \ buf[1] = _data & 0xFF; \ - write(address, buf, 2); \ + if(chip == 61) { \ + write(adrss_w6100, buf, 2); \ + } else { \ + write(address, buf, 2); \ + } \ } \ static uint16_t read##name() { \ uint8_t buf[2]; \ - read(address, buf, 2); \ + if(chip == 61) { \ + read(adrss_w6100, buf, 2); \ + } else { \ + read(address, buf, 2); \ + } \ return (buf[0] << 8) | buf[1]; \ } -#define __GP_REGISTER_N(name, address, size) \ + +#define __GP_REGISTER_N(name, address, adrss_w6100, size) \ static uint16_t write##name(const uint8_t *_buff) { \ - return write(address, _buff, size); \ - } \ - static uint16_t read##name(uint8_t *_buff) { \ - return read(address, _buff, size); \ + if(chip == 61) { \ + return write(adrss_w6100, _buff, size); \ + } else { \ + return write(address, _buff, size); \ + } \ + } \ + static uint16_t read##name(uint8_t *_buff) { \ + if(chip == 61) { \ + return read(adrss_w6100, _buff, size); \ + } else { \ + return read(address, _buff, size); \ + } \ } static 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 - + __GP_REGISTER8 (MR, 0x0000, 0x4000); // Mode + __GP_REGISTER_N(GAR, 0x0001, 0x4130, 4); // Gateway IP address + __GP_REGISTER_N(SUBR, 0x0005, 0x4134, 4); // Subnet mask address + __GP_REGISTER_N(SHAR, 0x0009, 0x4120, 6); // Source MAC address + __GP_REGISTER_N(SIPR, 0x000F, 0x4138, 4); // Source IP address + __GP_REGISTER8 (IR, 0x0015, 0x2100); // Interrupt + __GP_REGISTER8 (IMR, 0x0016, 0x2104); // Interrupt Mask + __GP_REGISTER16(RTR, 0x0017, 0x2101); // Timeout address + __GP_REGISTER8 (RCR, 0x0019, 0x4200); // Retry count + __GP_REGISTER8 (RMSR, 0x001A, 0x0000); // Receive memory size (W5100 only) + __GP_REGISTER8 (TMSR, 0x001B, 0x0000); // Transmit memory size (W5100 only) + __GP_REGISTER8 (PATR, 0x001C, 0x0000); // Authentication type address in PPPoE mode + __GP_REGISTER8 (PTIMER, 0x0028, 0x4100); // PPP LCP Request Timer + __GP_REGISTER8 (PMAGIC, 0x0029, 0x4104); // PPP LCP Magic Number + __GP_REGISTER_N(UIPR, 0x002A, 0x0000, 4); // Unreachable IP address in UDP mode (W5100 only) + __GP_REGISTER16(UPORT, 0x002E, 0x0000); // Unreachable Port address in UDP mode (W5100 only) + __GP_REGISTER8 (VERSIONR_W5200, 0x001F, 0x0000); // Chip Version Register (W5200 only) + __GP_REGISTER8 (VERSIONR_W5500, 0x0039, 0x0000); // Chip Version Register (W5500 only) + __GP_REGISTER8 (PSTATUS_W5200, 0x0035, 0x0000); // PHY Status + __GP_REGISTER8 (PHYCFGR_W5500, 0x002E, 0x0000); // PHY Configuration register, default: 10111xxx + + // For W6100 + __GP_REGISTER8 (SYCR0, 0x0000, 0x2004); // System Command Register + __GP_REGISTER8 (SYSR_W6100, 0x0000, 0x2000); // System Status Register + __GP_REGISTER8 (NETLCKR_W6100, 0x0000, 0x41F5); // Network Lock Register + __GP_REGISTER8 (CHPLCKR_W6100, 0x0000, 0x41F4); // Chip Lock Register + __GP_REGISTER8 (PHYLCKR_W6100, 0x0000, 0x41F6); // PHY Lock Register + __GP_REGISTER8 (PHYCFGR_W6100, 0x0000, 0x3000); // PHY Status + __GP_REGISTER8 (VERSIONR_W6100, 0x0000, 0x0000); // Chip Version Register + __GP_REGISTER8 (CVERSIONR_W6100, 0x0000, 0x0002); // Chip Version Register #undef __GP_REGISTER8 #undef __GP_REGISTER16 @@ -223,10 +294,15 @@ class W5100Class { //if (chip == 55) return 0x1000; //if (chip == 52) return 0x4000; //return 0x0400; + + // 5500 : 0x10 << 8 = 0x1000 + // 6100 : 0x60 << 8 = 0x6000 (1000 0000 0000 0000) + 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 uint16_t CH_SIZE; static inline uint8_t readSn(SOCKET s, uint16_t addr) { return read(CH_BASE() + s * CH_SIZE + addr); @@ -241,54 +317,81 @@ class W5100Class { return write(CH_BASE() + s * CH_SIZE + addr, buf, len); } -#define __SOCKET_REGISTER8(name, address) \ +#define __SOCKET_REGISTER8(name, address, adrss_w6100) \ static inline void write##name(SOCKET _s, uint8_t _data) { \ - writeSn(_s, address, _data); \ + if(chip == 61) { \ + writeSn(_s, adrss_w6100, _data); \ + } else { \ + writeSn(_s, address, _data); \ + } \ } \ static inline uint8_t read##name(SOCKET _s) { \ - return readSn(_s, address); \ + if(chip == 61) { \ + uint8_t data; \ + return readSn(_s, adrss_w6100); \ + } else { \ + return readSn(_s, address); \ + } \ } -#define __SOCKET_REGISTER16(name, address) \ + +#define __SOCKET_REGISTER16(name, address, adrss_w6100) \ static void write##name(SOCKET _s, uint16_t _data) { \ uint8_t buf[2]; \ buf[0] = _data >> 8; \ buf[1] = _data & 0xFF; \ - writeSn(_s, address, buf, 2); \ + if(chip == 61) { \ + writeSn(_s, adrss_w6100, buf, 2);\ + } else { \ + writeSn(_s, address, buf, 2); \ + } \ } \ static uint16_t read##name(SOCKET _s) { \ uint8_t buf[2]; \ - readSn(_s, address, buf, 2); \ + if(chip == 61) { \ + readSn(_s, adrss_w6100, buf, 2); \ + } else { \ + readSn(_s, address, buf, 2); \ + } \ return (buf[0] << 8) | buf[1]; \ } -#define __SOCKET_REGISTER_N(name, address, size) \ + +#define __SOCKET_REGISTER_N(name, address, adrss_w6100, size)\ static uint16_t write##name(SOCKET _s, uint8_t *_buff) { \ - return writeSn(_s, address, _buff, size); \ + if(chip == 61) { \ + return writeSn(_s, adrss_w6100, _buff, size); \ + } else { \ + return writeSn(_s, address, _buff, size); \ + } \ } \ static uint16_t read##name(SOCKET _s, uint8_t *_buff) { \ - return readSn(_s, address, _buff, size); \ + if(chip == 61) { \ + return readSn(_s, adrss_w6100, _buff, size); \ + } else { \ + 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?) + __SOCKET_REGISTER8(SnMR, 0x0000, 0x0000) // Mode + __SOCKET_REGISTER8(SnCR, 0x0001, 0x0010) // Command + __SOCKET_REGISTER8(SnIR, 0x0002, 0x0020) // Interrupt + __SOCKET_REGISTER8(SnSR, 0x0003, 0x0030) // Status + __SOCKET_REGISTER16(SnPORT, 0x0004, 0x0114) // Source Port + __SOCKET_REGISTER_N(SnDHAR, 0x0006, 0x0118, 6) // Destination Hardw Addr + __SOCKET_REGISTER_N(SnDIPR, 0x000C, 0x0120, 4) // Destination IP Addr + __SOCKET_REGISTER16(SnDPORT, 0x0010, 0x0140) // Destination Port + __SOCKET_REGISTER16(SnMSSR, 0x0012, 0x0110) // Max Segment Size + __SOCKET_REGISTER8(SnPROTO, 0x0014, 0x0000) // Protocol in IP RAW Mode + __SOCKET_REGISTER8(SnTOS, 0x0015, 0x0104) // IP TOS + __SOCKET_REGISTER8(SnTTL, 0x0016, 0x0108) // IP TTL + __SOCKET_REGISTER8(SnRX_SIZE, 0x001E, 0x0220) // RX Memory Size (W5200 only) + __SOCKET_REGISTER8(SnTX_SIZE, 0x001F, 0x0200) // TX Memory Size (W5200 only) + __SOCKET_REGISTER16(SnTX_FSR, 0x0020, 0x0204) // TX Free Size + __SOCKET_REGISTER16(SnTX_RD, 0x0022, 0x0208) // TX Read Pointer + __SOCKET_REGISTER16(SnTX_WR, 0x0024, 0x020C) // TX Write Pointer + __SOCKET_REGISTER16(SnRX_RSR, 0x0026, 0x0224) // RX Free Size + __SOCKET_REGISTER16(SnRX_RD, 0x0028, 0x0228) // RX Read Pointer + __SOCKET_REGISTER16(SnRX_WR, 0x002A, 0x022C) // RX Write Pointer (supported?) #undef __SOCKET_REGISTER8 #undef __SOCKET_REGISTER16 @@ -302,6 +405,7 @@ class W5100Class { static uint8_t isW5100(void); static uint8_t isW5200(void); static uint8_t isW5500(void); + static uint8_t isW6100(void); public: static uint8_t getChip(void) { return chip; } @@ -315,6 +419,8 @@ class W5100Class { static uint16_t SBASE(uint8_t socknum) { if (chip == 51) { return socknum * SSIZE + 0x4000; + } else if (chip == 61) { + return socknum * SSIZE + W6100_TX_BASE_ADDR; } else { return socknum * SSIZE + 0x8000; } @@ -322,13 +428,15 @@ class W5100Class { static uint16_t RBASE(uint8_t socknum) { if (chip == 51) { return socknum * SSIZE + 0x6000; + } else if (chip == 61) { + return socknum * SSIZE + W6100_RX_BASE_ADDR; } else { return socknum * SSIZE + 0xC000; } } static bool hasOffsetAddressMapping(void) { - if (chip == 55) return true; + if (chip == 55 || chip == 61) return true; return false; } static void setSS(uint8_t pin) { ss_pin = pin; }