// A ROT-13 server illustrating the use of the Wiznet WIZ811MJ and W5100. //Copyright (c) 2012, Mel Wilson //License: Creative Commons Attribution 3.0 Unported License // #include "wiz5100.h" // Arduino pins connected to the SPI interface and W5100 .. // Chosen to make the demo shield easy to wire .. int mosiPin = 2; int misoPin = 3; int wizIntPin = A1; int wizSelPin = A2; int sckPin = A3; int wizResetPin = A4; // Internet addresses used by this server // Chosen to fit in my LAN .. byte my_ip[] = {192, 168, 0, 77}; // IP address for the WIZ interface word rot13_port = 712; // port to serve ROT-13 requests byte gateway_ip[] = {192, 168, 0, 1}; byte subnet_mask[] = {255, 255, 255, 0}; // MAC address must be unique within the LAN, but given that, can be anything. // Or'ing 2 with the first byte makes the MAC address a "locally administered" address // as explained by Wikipedia on MAC addresses. byte mac_addr[] = {0xAC | 2, 0xAB, 0xE8, 0x63, 0xE4, 0x13}; // WIZ buffer space allocations to match the power-on default // Define Receive and Transmit buffer sizes and addresses for the sockets we will use .. #define SOCK0_RX_SIZE 2048 #define SOCK0_TX_SIZE 2048 #define SOCK0_RX_BASE WIZ_RX_BUFFER_BASE #define SOCK0_RX_MASK (SOCK0_RX_SIZE - 1) #define SOCK0_TX_BASE WIZ_TX_BUFFER_BASE #define SOCK0_TX_MASK (SOCK0_TX_SIZE - 1) byte buffer [100]; // space for text sent from the clients typedef struct { // UDP packet header delivered by a W5100 byte destination_ip [4]; // client's IP address byte destination_port [2]; // client's port byte data_size [2]; // packet data size } udp_header_t; udp_header_t udp_header; // space for the client's IP address, port, etc. // Set the SPI /SS pin low to start a transaction with the W5100 void wiz_select () { digitalWrite (wizSelPin, LOW); } // wiz_select // Set the SPI /SS pin high to end a transaction with the W5100 void wiz_unselect() { digitalWrite (wizSelPin, HIGH); } // wiz_unselect // Read a uint8_t (Arduino byte) value from a location in the W5100 via SPI byte wiz_read (word addr) { byte b; wiz_select(); shiftOut (mosiPin, sckPin, MSBFIRST, 0x0F); // W5100 Read command shiftOut (mosiPin, sckPin, MSBFIRST, addr >> 8); shiftOut (mosiPin, sckPin, MSBFIRST, addr & 0xFF); b = shiftIn(misoPin, sckPin, MSBFIRST); wiz_unselect(); return b; } // wiz_read // Read a uint16_t (Arduino word) value from a location in the W5100 word wiz_read_16 (word addr) { byte b = wiz_read (addr); return ((word)b) << 8 | wiz_read (addr+1); } // wiz_read_16 // Write a uint8_t (Arduino byte) value to an address in the W5100 via SPI void wiz_write (word addr, byte b) { wiz_select(); shiftOut (mosiPin, sckPin, MSBFIRST, 0xF0); // W5100 Write command shiftOut (mosiPin, sckPin, MSBFIRST, addr >> 8); shiftOut (mosiPin, sckPin, MSBFIRST, addr & 0xFF); shiftOut (mosiPin, sckPin, MSBFIRST, b); wiz_unselect(); } // wiz_write // Write a uint16_t (Arduino word) value to an address in the W5100 void wiz_write_16 (word addr, word data) { wiz_write (addr, (byte)(data >> 8)); wiz_write (addr+1, (byte)(data & 0xFF)); } // Move data from a W5100 socket's circular-buffer to your buffer for processing .. // Return the address beyond the last one read from the circular-buffer word fetch_wiz_data (byte *buffer, word buffer_size, word data_addr, word data_size, word addr_base, word addr_mask) { word i, upper_size; if ((data_addr + data_size) > (addr_base + addr_mask + 1)) { // the data in the circular-buffer wraps around the end upper_size = addr_base + addr_mask + 1 - data_addr; for (i=0; i < upper_size; i++) { // move the bytes from the top part *buffer++ = wiz_read (data_addr); data_addr++; } // arrange to get the rest of the bytes from the bottom of the circular-buffer data_size -= upper_size; data_addr = addr_base; } // read bytes one-by-one from the circular-buffer for (i=0; i < data_size; i++) { *buffer++ = wiz_read (data_addr); data_addr++; } return data_addr; } // fetch_wiz_data // Move data from your buffer into a W5100 socket's circular-buffer to be sent .. // Return the address beyond the last one written into the circular-buffer word stash_wiz_data (byte *buffer, word buffer_size, word data_addr, word data_size, word addr_base, word addr_mask) { word i, upper_size; if ((data_addr + data_size) > (addr_base + addr_mask + 1)) { // your data will wrap around the end of the circular-buffer .. upper_size = addr_base + addr_mask + 1 - data_addr; for (i=0; i < upper_size; i++) { // fill to the top of the circular-buffer wiz_write (data_addr, *buffer++); data_addr++; } // arrange to put the rest of the data into the bottom of the circular-buffer data_size -= upper_size; data_addr = addr_base; } // write bytes one-by-one into the circular-buffer for (i=0; i < data_size; i++) { wiz_write (data_addr, *buffer++); data_addr++; } return data_addr; } // stash_wiz_data //--------------------------------------------- char rot_13 (char c) { static const char upper[53] = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"; static const char lower[53] = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"; if ('a' <= c && c <= 'z') return lower [c - 'a' + 13]; if ('A' <= c && c <= 'Z') return upper [c - 'A' + 13]; return c; } // rot_13 //--------------------------------------------- void setup () { int i; pinMode (sckPin, OUTPUT); pinMode (mosiPin, OUTPUT); pinMode (misoPin, INPUT); pinMode (wizIntPin, INPUT); pinMode (wizSelPin, OUTPUT); pinMode (wizResetPin, OUTPUT); digitalWrite (wizIntPin, HIGH); // enable pull-up on the /INT line digitalWrite (wizSelPin, HIGH); // unselect the WIZ811MJ SPI digitalWrite (wizResetPin, HIGH); // don't reset the WIZ811MJ Serial.begin (115200); // to log activity on the serial monitor // set up the network info in the W5100 .. for (i=0; i < sizeof gateway_ip; i++) // Gateway Address wiz_write (WIZ_GAR0+i, gateway_ip[i]); for (i=0; i < sizeof mac_addr; i++) // MAC Address wiz_write (WIZ_SHAR0+i, mac_addr[i]); for (i=0; i < sizeof subnet_mask; i++) // Subnet Mask wiz_write (WIZ_SUBR0+i, subnet_mask[i]); for (i=0; i < sizeof my_ip; i++) // Our Own IP Address wiz_write (WIZ_SIPR0+i, my_ip[i]); do { wiz_write (WIZS_MR(0), WIZSV_MR_UDP); // ask for UDP protocol wiz_write_16 (WIZS_PORT0(0), rot13_port); wiz_write (WIZS_CR(0), WIZSV_CR_OPEN); // try to open as UDP if (wiz_read (WIZS_SR(0)) != WIZSV_SR_SOCK_UDP) // open failed -- close and retry wiz_write (WIZS_CR(0), WIZSV_CR_CLOSE); } while (wiz_read (WIZS_SR(0)) != WIZSV_SR_SOCK_UDP); } // setup void loop() { word i, data_size, data_offset, data_address; if (wiz_read_16 (WIZS_RX_RSR0(0)) == 0) { return; // no data has arrived yet } // // A different way to detect an incoming packet .. // if ((wiz_read (WIZ_IR) & (1< sizeof buffer) { // don't handle data that would overflow our buffer .. // release the circular-buffer space holding this oversized-packet .. wiz_write_16 (WIZS_RX_RD0(0), wiz_read_16 (WIZS_RX_RD0(0)) + sizeof udp_header + data_size); wiz_write (WIZS_CR(0), WIZSV_CR_RECV); // wait to receive another packet return; } // fetch the client's data from the circular-buffer fetch_wiz_data (buffer, sizeof buffer , data_address, data_size , SOCK0_RX_BASE, SOCK0_RX_MASK); // release the circular-buffer space in the WIZ .. wiz_write_16 (WIZS_RX_RD0(0), wiz_read_16 (WIZS_RX_RD0(0)) + sizeof udp_header + data_size); // Here's the servers service: ROT-13 encrypting its input .. for (i=0; i < data_size; i++) { buffer[i] = rot_13 (buffer[i]); } // Transmit the encrypted buffer back // Set the IP address to send to for (i=0; i < 4; i++) wiz_write (WIZS_DIPR0(0) + i, udp_header.destination_ip[i]); // set the port to send to wiz_write (WIZS_DPORT0(0), udp_header.destination_port[0]); wiz_write (WIZS_DPORT1(0), udp_header.destination_port[1]); data_offset = wiz_read_16 (WIZS_TX_WR0(0)) & SOCK0_TX_MASK; data_address = SOCK0_TX_BASE + data_offset; stash_wiz_data (buffer, sizeof buffer , data_address, data_size , SOCK0_TX_BASE, SOCK0_TX_MASK); // update the socket's transmit offset to include the data we want to send .. wiz_write_16 (WIZS_TX_WR0(0), wiz_read_16 (WIZS_TX_WR0(0)) + data_size); wiz_write (WIZS_CR(0), WIZSV_CR_SEND); // command the socket to send while (wiz_read (WIZS_CR(0)) != 0) {} // wait for sending to finish wiz_write (WIZS_CR(0), WIZSV_CR_RECV); // wait to receive another packet } // loop