diff --git a/keywords.txt b/keywords.txt index 9fd25419..2fc46c11 100644 --- a/keywords.txt +++ b/keywords.txt @@ -65,3 +65,5 @@ EthernetNoHardware LITERAL1 EthernetW5100 LITERAL1 EthernetW5200 LITERAL1 EthernetW5500 LITERAL1 +EthernetW6100 LITERAL1 +EthernetW5100S LITERAL1 diff --git a/src/Ethernet.cpp b/src/Ethernet.cpp index 9257090c..200caf7a 100644 --- a/src/Ethernet.cpp +++ b/src/Ethernet.cpp @@ -118,9 +118,11 @@ EthernetLinkStatus EthernetClass::linkStatus() EthernetHardwareStatus EthernetClass::hardwareStatus() { switch (W5100.getChip()) { + case 50: return EthernetW5100S; 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 0045de88..46ed89a4 100644 --- a/src/Ethernet.h +++ b/src/Ethernet.h @@ -47,6 +47,79 @@ // does not always seem to work in practice (maybe WIZnet bugs?) //#define ETHERNET_LARGE_BUFFERS +//#define USE_SERIAL_DEBUG_PRINT + +#ifdef USE_SERIAL_DEBUG_PRINT +#define PRINTLINE_DEF(var) \ +PRINTLINE(); \ +Serial.println("PRINTLINE_DEF("#var")"); +#else +#define PRINTLINE_DEF(var) +#endif + +#ifdef USE_SERIAL_DEBUG_PRINT +#define PRINTLINE() \ +Serial.print("\r\n"); \ +Serial.print(__FILE__); \ +Serial.print(" "); \ +Serial.println(__LINE__); +#else +#define PRINTLINE() +#endif + +#ifdef USE_SERIAL_DEBUG_PRINT +#define PRINTVAR_HEX(var) \ +PRINTLINE(); \ +Serial.print("PRINTVAR_HEX("#var")"); \ +Serial.print(" = 0x"); \ +Serial.println(var, HEX); +#else +#define PRINTVAR_HEX(var) +#endif + +#ifdef USE_SERIAL_DEBUG_PRINT +#define PRINTVAR_HEXD(var1, var2) \ +PRINTLINE(); \ +Serial.print("PRINTVAR_HEXD("#var1", "#var2")"); \ +Serial.print(" = 0x"); \ +Serial.print(var1, HEX); \ +Serial.print(" = 0x"); \ +Serial.println(var2, HEX); +#else +#define PRINTVAR_HEXD(var1, var2) +#endif + +#ifdef USE_SERIAL_DEBUG_PRINT +#define PRINTVAR_HEXT(var1, var2, var3) \ +PRINTLINE(); \ +Serial.print("PRINTVAR_HEXT("#var1", "#var2", "#var3")"); \ +Serial.print(" = 0x"); \ +Serial.print(var1, HEX); \ +Serial.print(" = 0x"); \ +Serial.print(var2, HEX); \ +Serial.print(" = 0x"); \ +Serial.println(var3, HEX); +#else +#define PRINTVAR_HEXT(var1, var2, var3) +#endif + +#ifdef USE_SERIAL_DEBUG_PRINT +#define PRINTVAR(var) \ +PRINTLINE(); \ +Serial.print("PRINTVAR("#var")"); \ +Serial.print(" = "); \ +Serial.println(var); +#else +#define PRINTVAR(var) +#endif + +#ifdef USE_SERIAL_DEBUG_PRINT +#define PRINTSTR(var) \ +PRINTLINE(); \ +Serial.println("PRINTVAR_STR("#var")"); +#else +#define PRINTSTR(var) +#endif #include #include "Client.h" @@ -63,7 +136,9 @@ enum EthernetHardwareStatus { EthernetNoHardware, EthernetW5100, EthernetW5200, - EthernetW5500 + EthernetW5500, + EthernetW6100, + EthernetW5100S }; class EthernetUDP; diff --git a/src/EthernetServer.cpp b/src/EthernetServer.cpp index ddebd154..43a1f4b8 100644 --- a/src/EthernetServer.cpp +++ b/src/EthernetServer.cpp @@ -46,7 +46,7 @@ EthernetClient EthernetServer::available() 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 || chip == 50) maxindex = 4; // W5100+W5100S chips never support more than 4 sockets #endif for (uint8_t i=0; i < maxindex; i++) { if (server_port[i] == _port) { @@ -81,7 +81,7 @@ EthernetClient EthernetServer::accept() 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 || chip == 50) maxindex = 4; // W5100 chip never supports more than 4 sockets #endif for (uint8_t i=0; i < maxindex; i++) { if (server_port[i] == _port) { @@ -108,7 +108,7 @@ EthernetServer::operator bool() { 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 || W5100.getChip() == 50) maxindex = 4; // W5100 chip never supports more than 4 sockets #endif for (uint8_t i=0; i < maxindex; i++) { if (server_port[i] == _port) { @@ -165,7 +165,7 @@ size_t EthernetServer::write(const uint8_t *buffer, size_t size) 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 || chip == 50) maxindex = 4; // W5100 chip never supports more than 4 sockets #endif available(); for (uint8_t i=0; i < maxindex; i++) { 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/socket.cpp b/src/socket.cpp index 7dc83feb..dc86ae0b 100644 --- a/src/socket.cpp +++ b/src/socket.cpp @@ -68,7 +68,7 @@ uint8_t EthernetClass::socketBegin(uint8_t protocol, uint16_t port) chip = W5100.getChip(); if (!chip) return MAX_SOCK_NUM; // immediate error if no hardware detected #if MAX_SOCK_NUM > 4 - if (chip == 51) maxindex = 4; // W5100 chip never supports more than 4 sockets + if (chip == 51 || chip == 50) maxindex = 4; // W5100 chip never supports more than 4 sockets #endif //Serial.printf("W5000socket begin, protocol=%d, port=%d\n", protocol, port); SPI.beginTransaction(SPI_ETHERNET_SETTINGS); @@ -132,7 +132,7 @@ uint8_t EthernetClass::socketBeginMulticast(uint8_t protocol, IPAddress ip, uint chip = W5100.getChip(); if (!chip) return MAX_SOCK_NUM; // immediate error if no hardware detected #if MAX_SOCK_NUM > 4 - if (chip == 51) maxindex = 4; // W5100 chip never supports more than 4 sockets + if (chip == 51 || chip == 50) maxindex = 4; // W5100 chip never supports more than 4 sockets #endif //Serial.printf("W5000socket begin, protocol=%d, port=%d\n", protocol, port); SPI.beginTransaction(SPI_ETHERNET_SETTINGS); diff --git a/src/utility/w5100.cpp b/src/utility/w5100.cpp index 6e7dbd20..446201ad 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(); @@ -157,7 +160,29 @@ uint8_t W5100Class::init(void) writeSnTX_SIZE(i, 0); } #endif - // Try W5100 last. This simple chip uses fixed 4 byte frames + // Try W5100S. Brandnew based W5100. + } else if (isW5100S()) { + CH_BASE_MSB = 0x04; +#ifdef ETHERNET_LARGE_BUFFERS +#if MAX_SOCK_NUM <= 1 + SSIZE = 8192; + writeTMSR(0x03); + writeRMSR(0x03); +#elif MAX_SOCK_NUM <= 2 + SSIZE = 4096; + writeTMSR(0x0A); + writeRMSR(0x0A); +#else + SSIZE = 2048; + writeTMSR(0x55); + writeRMSR(0x55); +#endif + SMASK = SSIZE - 1; +#else + writeTMSR(0x55); + writeRMSR(0x55); +#endif + // Try W5100. 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 @@ -182,6 +207,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 @@ -202,18 +251,65 @@ uint8_t W5100Class::softReset(void) { uint16_t 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; + 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 + + 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 || (mr == 3 && chip == 50)) 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) @@ -231,6 +327,23 @@ uint8_t W5100Class::isW5100(void) return 1; } +uint8_t W5100Class::isW5100S(void) +{ + chip = 50; + //Serial.println("w5100.cpp: detect W5100S chip"); + if (!softReset()) return 0; + writeMR(0x13); + if (readMR() != 0x13) return 0; + writeMR(0x03); + if (readMR() != 0x03) return 0; + int ver = readVERSIONR_W5100S(); + //Serial.print("version="); + //Serial.println(ver); + if (ver != 81) return 0; + //Serial.println("chip is W5100S"); + return 1; +} + uint8_t W5100Class::isW5200(void) { chip = 52; @@ -275,6 +388,12 @@ W5100Linkstatus W5100Class::getLinkStatus() if (!init()) return UNKNOWN; switch (chip) { + case 50: + SPI.beginTransaction(SPI_ETHERNET_SETTINGS); + phystatus = readPHYCFGR_W5100S(); + SPI.endTransaction(); + if (phystatus & 0x01) return LINK_ON; + return LINK_OFF; case 52: SPI.beginTransaction(SPI_ETHERNET_SETTINGS); phystatus = readPSTATUS_W5200(); @@ -287,6 +406,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; } @@ -296,7 +421,7 @@ uint16_t W5100Class::write(uint16_t addr, const uint8_t *buf, uint16_t len) { uint8_t cmd[8]; - if (chip == 51) { + if (chip == 51 || chip == 50) { for (uint16_t i=0; i>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) { @@ -387,7 +595,7 @@ uint16_t W5100Class::read(uint16_t addr, uint8_t *buf, uint16_t len) { uint8_t cmd[4]; - if (chip == 51) { + if (chip == 51 || chip == 50) { for (uint16_t i=0; i < len; i++) { setSS(); #if 1 @@ -417,6 +625,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..71c29322 100644 --- a/src/utility/w5100.h +++ b/src/utility/w5100.h @@ -161,56 +161,129 @@ 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 (VERSIONR_W5100S, 0x0080, 0x0000); // Chip Version Register (W5100S only) + __GP_REGISTER8 (PSTATUS_W5200, 0x0035, 0x0000); // PHY Status + __GP_REGISTER8 (PHYCFGR_W5500, 0x002E, 0x0000); // PHY Configuration register, default: 10111xxx + __GP_REGISTER8 (PHYCFGR_W5100S, 0x003C, 0x0000); // PHY Status + + // 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 +296,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 +319,80 @@ 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) { \ + 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 @@ -300,8 +404,10 @@ class W5100Class { static uint8_t ss_pin; static uint8_t softReset(void); static uint8_t isW5100(void); + static uint8_t isW5100S(void); static uint8_t isW5200(void); static uint8_t isW5500(void); + static uint8_t isW6100(void); public: static uint8_t getChip(void) { return chip; } @@ -313,22 +419,26 @@ class W5100Class { static const uint16_t SMASK = 0x07FF; #endif static uint16_t SBASE(uint8_t socknum) { - if (chip == 51) { + if (chip == 51 || chip == 50) { return socknum * SSIZE + 0x4000; + } else if (chip == 61) { + return socknum * SSIZE + W6100_TX_BASE_ADDR; } else { return socknum * SSIZE + 0x8000; } } static uint16_t RBASE(uint8_t socknum) { - if (chip == 51) { + if (chip == 51 || chip == 50) { 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; }