unsigned char OpenSocket(unsigned char sock, unsigned char eth_protocol, unsigned int tcp_port) { unsigned char retval; unsigned int sockaddr; retval = W5100_FAIL; // assume this doesn't work if (sock >= W5100_NUM_SOCKETS) return retval; // illegal socket value is bad! sockaddr = W5100_SKT_BASE(sock); // calc base addr for this socket if (w5100_read(sockaddr + W5100_SR_OFFSET) == W5100_SKT_SR_CLOSED) // Make sure we close the socket first { CloseSocket(sock); } w5100_write(sockaddr + W5100_MR_OFFSET, eth_protocol); // set protocol for this socket w5100_write(sockaddr + W5100_PORT_OFFSET, ((tcp_port & 0xFF00) >> 8)); // set port for this socket (MSB) w5100_write(sockaddr + W5100_PORT_OFFSET + 1, (tcp_port & 0x00FF)); // set port for this socket (LSB) w5100_write(sockaddr + W5100_CR_OFFSET, W5100_SKT_CR_OPEN); // open the socket while (w5100_read(sockaddr + W5100_CR_OFFSET)); // loop until device reports socket is open (blocks!!) char temp = w5100_read(sockaddr + W5100_SR_OFFSET); if ( temp == W5100_SKT_SR_INIT) { retval = sock; }// if success, return socket number else { CloseSocket(sock); }// if failed, close socket immediately return retval; }
unsigned int Receive(unsigned char sock, unsigned char *buf, unsigned int buflen) { unsigned int ptr; unsigned int offaddr; unsigned int realaddr; unsigned int sockaddr; if (buflen == 0 || sock >= W5100_NUM_SOCKETS) return W5100_FAIL; // ignore illegal conditions if (buflen > (MAX_BUF - 2)) buflen = MAX_BUF - 2; // requests that exceed the max are truncated sockaddr = W5100_SKT_BASE(sock); // calc base addr for this socket ptr = w5100_read(sockaddr + W5100_RX_RD_OFFSET); // get the RX read pointer (MSB) offaddr = (((ptr & 0x00FF) << 8) + w5100_read(sockaddr + W5100_RX_RD_OFFSET + 1)); // get LSB and calc offset addr while (buflen) { buflen--; realaddr = W5100_RXBUFADDR + (offaddr & W5100_RX_BUF_MASK); *buf = w5100_read(realaddr); offaddr++; buf++; } *buf = '\0'; // buffer read is complete, terminate the string // Increase the S0_RX_RD value, so it point to the next receive w5100_write(sockaddr + W5100_RX_RD_OFFSET, (offaddr & 0xFF00) >> 8); // update RX read offset (MSB) w5100_write(sockaddr + W5100_RX_RD_OFFSET + 1, (offaddr & 0x00FF)); // update LSB // Now Send the RECV command w5100_write(sockaddr + W5100_CR_OFFSET, W5100_SKT_CR_RECV); // issue the receive command __delay_us(5); // wait for receive to start return W5100_OK; }
uint8_t SOCK_Listen(uint8_t sock) { uint8_t val; uint16_t sockaddr; if (sock>=W5100_NUM_SOCKETS) { return ERR_VALUE; } sockaddr = W5100_SKT_BASE(sock); W5100_MemReadByte(sockaddr+W5100_SR_OFFSET, &val); if (val==W5100_SOCK_INIT) { /* Send the LISTEN Command */ W5100_MemWriteByte(sockaddr+W5100_CR_OFFSET, W5100_CR_LISTEN); /* Wait for Listening Process */ do { W5100_MemReadByte(sockaddr+W5100_CR_OFFSET, &val); } while(val!=0); /* Check for Listen Status */ W5100_MemReadByte(sockaddr+W5100_SR_OFFSET, &val); if (val==W5100_SOCK_LISTEN) { return ERR_OK; } else { SOCK_CloseSocket(sock); } } return ERR_FAILED; }
uint8_t SOCK_Receive(uint8_t sock, uint8_t *buf, size_t bufSize, size_t readSize) { uint16_t offaddr, realaddr; uint16_t sockaddr; if (readSize<=0 || sock>=W5100_NUM_SOCKETS) { return ERR_VALUE; /* failure */ } if (readSize>bufSize) { /* If the requested size > MAX_BUF, just truncate it */ readSize = bufSize-2; } sockaddr = W5100_SKT_BASE(sock); /* Read the Rx Read Pointer */ W5100_MemReadWord(sockaddr+W5100_RX_RD_OFFSET, &offaddr); while (readSize) { readSize--; realaddr = (W5100_RXBUFADDR + (0x0800*sock))+(offaddr&W5100_RX_BUF_MASK); W5100_MemReadByte(realaddr, buf); offaddr++; buf++; } *buf='\0'; /* string terminated character */ /* Increase the S0_RX_RD value, so it point to the next receive */ W5100_MemWriteWord(sockaddr+W5100_RX_RD_OFFSET, offaddr); /* Now Send the RECV command */ W5100_MemWriteByte(sockaddr+W5100_CR_OFFSET, W5100_CR_RECV); WAIT1_Waitus(5); /* Wait for Receive Process */ return ERR_OK; }
uint8_t SOCK_OpenSocket(uint8_t sock, uint8_t eth_protocol, uint16_t tcp_port) { uint8_t val; uint16_t sockaddr; if (sock>=W5100_NUM_SOCKETS) { return ERR_VALUE; /* out of range */ } sockaddr = W5100_SKT_BASE(sock); /* Make sure we close the socket first */ if (W5100_MemReadByte(sockaddr+W5100_SR_OFFSET, &val)!=ERR_OK) { return ERR_FAILED; /* failure */ } if (val==W5100_SOCK_CLOSED) { /* make sure we close the socket */ SOCK_CloseSocket(sock); } /* Assigned Socket 0 Mode Register */ W5100_MemWriteByte(sockaddr+W5100_MR_OFFSET, eth_protocol); /* Now open the Socket 0 */ W5100_MemWriteWord(sockaddr+W5100_PORT_OFFSET, tcp_port); W5100_MemWriteByte(sockaddr+W5100_CR_OFFSET, W5100_CR_OPEN); /* Open Socket */ /* Wait for Opening Process */ do { W5100_MemReadByte(sockaddr+W5100_CR_OFFSET, &val); } while(val!=0); /* Check for Init Status */ W5100_MemReadByte(sockaddr+W5100_SR_OFFSET, &val); if (val==W5100_SOCK_INIT) { return ERR_OK; } else { SOCK_CloseSocket(sock); } return ERR_FAILED; }
unsigned char Send(unsigned char sock, const unsigned char *buf, unsigned int buflen) { unsigned int ptr; unsigned int offaddr; unsigned int realaddr; unsigned int txsize; unsigned int timeout; unsigned int sockaddr; if (buflen == 0 || sock >= W5100_NUM_SOCKETS) return W5100_FAIL; // ignore illegal requests sockaddr = W5100_SKT_BASE(sock); // calc base addr for this socket // Make sure the TX Free Size Register is available txsize = W51_read(sockaddr + W5100_TX_FSR_OFFSET); // make sure the TX free-size reg is available txsize = (((txsize & 0x00FF) << 8) + W51_read(sockaddr + W5100_TX_FSR_OFFSET + 1)); timeout = 0; while (txsize < buflen) { _delay_ms(1); txsize = W51_read(sockaddr + W5100_TX_FSR_OFFSET); // make sure the TX free-size reg is available txsize = (((txsize & 0x00FF) << 8) + W51_read(sockaddr + W5100_TX_FSR_OFFSET + 1)); if (timeout++ > 1000) // if max delay has passed... { DisconnectSocket(sock); // can't connect, close it down return W5100_FAIL; // show failure } } // Read the Tx Write Pointer ptr = W51_read(sockaddr + W5100_TX_WR_OFFSET); offaddr = (((ptr & 0x00FF) << 8) + W51_read(sockaddr + W5100_TX_WR_OFFSET + 1)); while (buflen) { buflen--; realaddr = (W5100_TXBUFADDR + (0x0800 * sock)) + (offaddr & W5100_TX_BUF_MASK); // calc W5100 physical buffer addr for this socket W51_write(realaddr, *buf); // send a byte of application data to TX buffer offaddr++; // next TX buffer addr buf++; // next input buffer addr } W51_write(sockaddr + W5100_TX_WR_OFFSET, (offaddr & 0xFF00) >> 8); // send MSB of new write-pointer addr W51_write(sockaddr + W5100_TX_WR_OFFSET + 1, (offaddr & 0x00FF)); // send LSB W51_write(sockaddr + W5100_CR_OFFSET, W5100_SKT_CR_SEND); // start the send on its way while (W51_read(sockaddr + W5100_CR_OFFSET)) ; // loop until socket starts the send (blocks!!) return W5100_OK; }
void DisconnectSocket(unsigned char sock) { unsigned int sockaddr; if (sock > W5100_NUM_SOCKETS) return; // if illegal socket number, ignore request sockaddr = W5100_SKT_BASE(sock); // calc base addr for this socket w5100_write(sockaddr + W5100_CR_OFFSET, W5100_SKT_CR_DISCON); // disconnect the socket while (w5100_read(sockaddr + W5100_CR_OFFSET)); // loop until socket is closed (blocks!!) }
uint8_t SOCK_GetStatus(uint8_t sock, uint8_t *status) { uint16_t sockaddr; if (sock>=W5100_NUM_SOCKETS) { return ERR_VALUE; } sockaddr = W5100_SKT_BASE(sock); return W5100_MemReadByte(sockaddr+W5100_SR_OFFSET, status); }
unsigned int ReceivedSize(unsigned char sock) { unsigned int val; unsigned int sockaddr; if (sock >= W5100_NUM_SOCKETS) return 0; sockaddr = W5100_SKT_BASE(sock); // calc base addr for this socket val = w5100_read(sockaddr + W5100_RX_RSR_OFFSET) & 0xff; val = (val << 8) + w5100_read(sockaddr + W5100_RX_RSR_OFFSET + 1); return val; }
uint8_t SOCK_ReceivedSize(uint8_t sock, uint16_t *rxSize) { uint16_t sockaddr; *rxSize = 0; if (sock>=W5100_NUM_SOCKETS) { return ERR_VALUE; } sockaddr = W5100_SKT_BASE(sock); // calc base addr for this socket return W5100_MemReadWord(sockaddr+W5100_RX_RSR_OFFSET, rxSize); }
void CloseSocket(unsigned char sock) { unsigned int sockaddr; if (sock > W5100_NUM_SOCKETS) return; // if illegal socket number, ignore request sockaddr = W5100_SKT_BASE(sock); // calc base addr for this socket W51_write(sockaddr + W5100_CR_OFFSET, W5100_SKT_CR_CLOSE); // tell chip to close the socket while (W51_read(sockaddr + W5100_CR_OFFSET)) ; // loop until socket is closed (blocks!!) }
uint8_t SOCK_Disconnect(uint8_t sock) { uint8_t val; uint16_t sockaddr; if (sock>=W5100_NUM_SOCKETS) { return ERR_VALUE; } sockaddr = W5100_SKT_BASE(sock); /* Send Disconnect Command */ W5100_MemWriteByte(sockaddr+W5100_CR_OFFSET, W5100_CR_DISCON); do { /* Wait for Disconnecting Process */ W5100_MemReadByte(sockaddr+W5100_CR_OFFSET, &val); } while(val!=0); return ERR_OK; }
uint8_t SOCK_CloseSocket(uint8_t sock) { uint8_t val; uint16_t sockaddr; if (sock>=W5100_NUM_SOCKETS) { return ERR_VALUE; } sockaddr = W5100_SKT_BASE(sock); /* Send Close Command */ W5100_MemWriteByte(sockaddr+W5100_CR_OFFSET, W5100_CR_CLOSE); do { /* Waiting until the S0_CR is clear */ W5100_MemReadByte(sockaddr+W5100_CR_OFFSET, &val); } while(val!=0); return ERR_OK; }
unsigned char Listen(unsigned char sock) { unsigned char retval; unsigned int sockaddr; retval = W5100_FAIL; // assume this fails if (sock > W5100_NUM_SOCKETS) return retval; // if illegal socket number, ignore request sockaddr = W5100_SKT_BASE(sock); // calc base addr for this socket if (w5100_read(sockaddr + W5100_SR_OFFSET) == W5100_SKT_SR_INIT) // if socket is in initialized state... { w5100_write(sockaddr + W5100_CR_OFFSET, W5100_SKT_CR_LISTEN); // put socket in listen state while (w5100_read(sockaddr + W5100_CR_OFFSET)); // block until command is accepted if (w5100_read(sockaddr + W5100_SR_OFFSET) == W5100_SKT_SR_LISTEN) retval = W5100_OK; // if socket state changed, show success else CloseSocket(sock); // not in listen mode, close and show an error occurred } return retval; }
uint8_t SOCK_Send(uint8_t sock, const uint8_t *buf, size_t buflen) { uint16_t offaddr, realaddr, txsize, timeout, sockaddr; uint8_t val; if (buflen<=0 || sock>=W5100_NUM_SOCKETS) { return ERR_VALUE; } sockaddr = W5100_SKT_BASE(sock); /* Make sure the TX Free Size Register is available */ W5100_MemReadWord(sockaddr+W5100_TX_FSR_OFFSET, &txsize); timeout=0; while (txsize<buflen) { WAIT1_WaitOSms(1); W5100_MemReadWord(sockaddr+W5100_TX_FSR_OFFSET, &txsize); /* Timeout for approximately 1000 ms */ if (timeout++ > 1000) { /* Disconnect the connection */ SOCK_Disconnect(sock); return ERR_FAILED; } } /* Read the Tx Write Pointer */ W5100_MemReadWord(sockaddr+W5100_TX_WR_OFFSET, &offaddr); while(buflen) { buflen--; /* Calculate the real W5100 physical Tx Buffer Address */ realaddr = (W5100_TXBUFADDR+(0x0800*sock)) + (offaddr&W5100_TX_BUF_MASK); /* Copy the application data to the W5100 Tx Buffer */ W5100_MemWriteByte(realaddr, *buf); offaddr++; buf++; } /* Increase the S0_TX_WR value, so it point to the next transmit */ W5100_MemWriteWord(sockaddr+W5100_TX_WR_OFFSET, offaddr); /* Now Send the SEND command */ W5100_MemWriteByte(sockaddr+W5100_CR_OFFSET, W5100_CR_SEND); /* Wait for Sending Process */ do { W5100_MemReadByte(sockaddr+W5100_CR_OFFSET, &val); } while(val!=0); return ERR_OK; }
int main(void) { unsigned int sockaddr; unsigned char mysocket; unsigned int rsize; /* Initialize the UART for ATmega168 96008N1 */ uart_init(); stdout = &uart_stdout; //Required for printf init mysocket = 0; // magic number! declare the socket number we will us sockaddr = W5100_SKT_BASE(mysocket); // calc address of W5100 register set for this socket puts("AVR Ethernet\r\n"); /* * Initialize the ATmega168 SPI subsystem */ CS_PORT |= (1 << CS_BIT); // pull CS pin high CS_DDR |= (1 << CS_BIT); // now make it an output SPI_PORT = SPI_PORT | (1 << PORTB2); // make sure SS is high SPI_DDR = (1 << PORTB3) | (1 << PORTB5) | (1 << PORTB2); // set MOSI, SCK and SS as output, others as input SPCR = (1 << SPE) | (1 << MSTR); // enable SPI, master mode 0 SPSR |= (1 << SPI2X); // set the clock rate fck/2 /* * Load up the callback block, then initialize the Wiznet W5100 */ my_callbacks._select = &my_select; // callback for selecting the W5100 my_callbacks._xchg = &my_xchg; // callback for exchanging data my_callbacks._deselect = &my_deselect; // callback for deselecting the W5100 my_callbacks._reset = &my_reset; // callback for hardware-reset of the W5100 W51_register(&my_callbacks); // register our target-specific W5100 routines with the W5100 library W51_init(); // now initialize the W5100 /* * Configure the W5100 device to handle PING requests. * This requires configuring the chip, not a specific socket. */ W51_config(&my_cfg); // config the W5100 (MAC, TCP address, subnet, etc puts("Debug: AVR Ethernet after W5100 config\r\n"); /* * The main loop. Control stays in this loop forever, processing any received packets * and sending any requested data. */ while (1) { switch (W51_read(sockaddr + W5100_SR_OFFSET)) // based on current status of socket... { case W5100_SKT_SR_CLOSED: // if socket is closed... if (OpenSocket(mysocket, W5100_SKT_MR_TCP, HTTP_PORT) == mysocket) // if successful opening a socket... { Listen(mysocket); _delay_ms(1); } break; case W5100_SKT_SR_ESTABLISHED: // if socket connection is established... rsize = ReceivedSize(mysocket); // find out how many bytes if (rsize > 0) { if (Receive(mysocket, buf, rsize) != W5100_OK) break; // if we had problems, all done /* * Add code here to process the payload from the packet. * * For now, we just ignore the payload and send a canned HTML page so the client at least * knows we are alive. */ strcpy_P((char *)buf,PSTR("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\nPragma: no-cache\r\n\r\n")); strcat_P((char *)buf,PSTR("<html>\r\n<body>\r\n")); strcat_P((char *)buf,PSTR("<title>Title</title>\r\n")); strcat_P((char *)buf,PSTR("<p>Hello world</p>\r\n")); strcat_P((char *)buf,PSTR("</body>\r\n</html>\r\n")); if (Send(mysocket, buf, strlen((char *)buf)) == W5100_FAIL) break; // just throw out the packet for now DisconnectSocket(mysocket); } else // no data yet... { _delay_us(10); } break; case W5100_SKT_SR_FIN_WAIT: case W5100_SKT_SR_CLOSING: case W5100_SKT_SR_TIME_WAIT: case W5100_SKT_SR_CLOSE_WAIT: case W5100_SKT_SR_LAST_ACK: CloseSocket(mysocket); break; } } return 0; }