Skip to content

Added W6100 for W6100 Ethernetshield #102

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,4 @@ EthernetNoHardware LITERAL1
EthernetW5100 LITERAL1
EthernetW5200 LITERAL1
EthernetW5500 LITERAL1
EthernetW6100 LITERAL1
1 change: 1 addition & 0 deletions src/Ethernet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/Ethernet.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ enum EthernetHardwareStatus {
EthernetNoHardware,
EthernetW5100,
EthernetW5200,
EthernetW5500
EthernetW5500,
EthernetW6100
};

class EthernetUDP;
Expand Down
59 changes: 47 additions & 12 deletions src/EthernetUdp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
258 changes: 246 additions & 12 deletions src/utility/w5100.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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<MAX_SOCK_NUM; i++) {
writeSnRX_SIZE(i, SSIZE >> 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
Expand All @@ -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)
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down
Loading