You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1132 lines
27 KiB

/*
Code to test wiznet WIZ810MJ module
See:
<http://code.rancidbacon.com/LearningAboutArduinoWIZ810MJ>
Current features:
* Initial W5100 driver port:
+ new-style network configuration
+ socket creation/listening/closing
+ Sending/Receiving okay
+ example "echo" server (new version with classes and multiple connections)
+ example "web server" with LED flash. (not currently)
* (slighty less) Terrible hacked-together code
Author:
follower@rancidbacon.com
License:
LGPL
Version:
20071220-0006+
*/
#include <WIZ810MJ.h>
/* --------- SPI --------- */
// Define SPI-related pins
#define PIN_DATA_OUT 11 // MOSI (Master Out / Slave In)
#define PIN_DATA_IN 12 // MISO (Master In / Slave Out)
#define PIN_SPI_CLOCK 13 // SCK (Serial Clock)
#define PIN_SLAVE_SELECT 10 // SS (Slave Select)
class SpiConfiguration {
public:
static void begin(void);
};
void SpiConfiguration::begin(void) {
/*
Configure pins and registers required for SPI communication.
*/
// Configure I/O pins
pinMode(PIN_DATA_OUT, OUTPUT);
pinMode(PIN_DATA_IN, INPUT);
pinMode(PIN_SPI_CLOCK, OUTPUT);
pinMode(PIN_SLAVE_SELECT, OUTPUT);
digitalWrite(PIN_SLAVE_SELECT, HIGH); // Disable slave
/*
Configure SPI Control Register (SPCR) (All values initially 0)
Bit Description
7 SPI Interrupt Enable -- disable (SPIE --> 0)
6 SPI Enable -- enable (SPE --> 1)
5 Data Order -- MSB 1st (DORD --> 0) (Slave specific)
4 Master/Slave Select -- master (MSTR --> 1)
3 Clock Polarity -- (CPOL --> 0) (Slave specific) ("Mode")
2 Clock Phase -- (CPHA --> 0) (Slave specific)
1 SPI Clock Rate Select 1 -- } (SPR1 --> 0)
0 SPI Clock Rate Select 0 -- } fOSC/4 (SPR0 --> 0) ("Fastest" but see SPI2X in SPSR)
*/
SPCR = (1<<SPE)| (1<<MSTR);
// Clear previous data and status (TODO: Determine if necessary/better way.)
// (Based on Playground SPI example.)
byte dummy;
dummy = SPSR;
dummy = SPDR;
delay(10);
}
SpiConfiguration SPI = SpiConfiguration();
/* ----------------------- */
/* ------ WIZ810MJ ------ */
class Wiz810MjDevice {
public:
Wiz810MjDevice(int resetPin);
void setIp(byte b0, byte b1, byte b2, byte b3);
void setMask(byte b0, byte b1, byte b2, byte b3);
void setGateway(byte b0, byte b1, byte b2, byte b3);
void setMac(byte b0, byte b1, byte b2, byte b3, byte b4, byte b5);
private:
void _init(void);
byte * _packBuffer(byte b0, byte b1, byte b2, byte b3);
byte * _packBuffer(byte b0, byte b1, byte b2, byte b3, byte b4, byte b5);
int _resetPin;
byte _scratchBuffer[6]; // Can we make this static?
};
Wiz810MjDevice::Wiz810MjDevice(int resetPin) {
// TODO: We should really allow the chip-select pin to be set here?
// Or require that it's defined. (Currently in the library file 'types.h'.)
_resetPin = resetPin;
_init();
}
void Wiz810MjDevice::_init(void) {
/*
Initialise the WIZ810MJ module and driver.
*/
/*
Initialise the W5100 chip
(Originally I thought it was possible for the chip
to function without a hardware reset but it
seems not to be the case.)
*/
pinMode(_resetPin, OUTPUT);
// We rely on the time between function calls to
// be long enough for the chip to recognise the
// reset.
digitalWrite(_resetPin, HIGH);
digitalWrite(_resetPin, LOW); // reset
digitalWrite(_resetPin, HIGH);
// Chip initialisation by driver
// Might be redundant following the above reset,
// as this performs a software reset.
iinchip_init();
// Initialise driver
// (This is required to configure some variables used
// internally by the driver--even if the default chip
// configuration is used.)
sysinit(0x55, 0x55);
}
byte * Wiz810MjDevice::_packBuffer(byte b0, byte b1, byte b2, byte b3) {
/*
*/
return _packBuffer(b0, b1, b2, b3, 0, 0); // Adds two bytes of padding
}
byte * Wiz810MjDevice::_packBuffer(byte b0, byte b1, byte b2, byte b3, byte b4, byte b5) {
/*
*/
_scratchBuffer[0] = b0;
_scratchBuffer[1] = b1;
_scratchBuffer[2] = b2;
_scratchBuffer[3] = b3;
_scratchBuffer[4] = b4;
_scratchBuffer[5] = b5;
return _scratchBuffer;
}
void Wiz810MjDevice::setIp(byte b0, byte b1, byte b2, byte b3) {
/*
*/
setSIPR(_packBuffer(b0, b1, b2, b3));
}
void Wiz810MjDevice::setMask(byte b0, byte b1, byte b2, byte b3) {
/*
*/
setSUBR(_packBuffer(b0, b1, b2, b3));
}
void Wiz810MjDevice::setGateway(byte b0, byte b1, byte b2, byte b3) {
/*
*/
setGAR(_packBuffer(b0, b1, b2, b3));
}
void Wiz810MjDevice::setMac(byte b0, byte b1, byte b2, byte b3, byte b4, byte b5) {
/*
*/
setSHAR(_packBuffer(b0, b1, b2, b3, b4, b5));
}
/* ----------------------- */
/* ---- NetworkConnection ---- */
// TODO: Make this 'NetworkServerConnection'? Or just 'ServerConnection'?
// TODO: Pull one-line methods into class definition to allow inlining?
class NetworkConnection { // Essentially a Socket wrapper
public:
// TODO: Split into client/server connections? Subclass?
NetworkConnection(uint16_t port); // TODO: Add UDP, TCP choice? // For servers
NetworkConnection(); // For clients--is using the default constructor hide misuse? TODO: As above.
int listen();
int connect(uint8 * addr, uint16 port);
int isConnected();
int available();
int read();
void print(uint8_t);
void print(const char * text);
void close();
private:
SOCKET _socket;
static const int _MAX_SOCKETS = MAX_SOCK_NUM; // TODO: Use this.
static int _nextSocket;
};
int NetworkConnection::_nextSocket = 0;
NetworkConnection::NetworkConnection(uint16_t port) {
/*
*/
_socket = _nextSocket; // TODO: Do properly (& max)
_nextSocket++;
socket(_socket, Sn_MR_TCP, port, 0);
}
NetworkConnection::NetworkConnection() {
/*
*/
NetworkConnection(0);
}
int NetworkConnection::listen() { // TODO: Make private or protected?
/*
*/
return !!::listen(_socket); // TODO: Use C++ namespaces for the driver functions?
}
int NetworkConnection::connect(uint8 * addr, uint16 port) { // TODO: Make private or protected?
/*
*/
// TODO: Accept bytes here for addr?
int result = 0;
result = !!::connect(_socket, addr, port); // TODO: Use C++ namespaces for the driver functions?
Serial.println(IINCHIP_READ(Sn_DPORT0(_socket)), HEX);
Serial.println(IINCHIP_READ(Sn_DPORT0(_socket) + 1), HEX);
return result;
}
int NetworkConnection::available() {
/*
Functionality matches 'Serial.available()'.
Note: If the socket is not connected then this will return 0,
but it is intended that 'isConnected()' would be checked first.
Returns:
"The number of bytes available to read ... or 0 if none are available.
If any data has come in, [...].available() will be greater than 0."
*/
// TODO: Do we want to check for 'isConnected' as well, or not?
// We have to, I guess, for valid behaviour with 'getSn_*'.
if (!isConnected()) {
return 0;
}
return getSn_RX_RSR(_socket);
}
#define NO_READ_DATA_AVAILABLE -1
int NetworkConnection::read() {
/*
Functionality matches 'Serial.read()'.
Returns:
"an int, the first byte of incoming serial data available
(or -1 if no data is available)."
Note: I thought 'recv' blocked until data was available,
but it currently seems not to block after all.
However, because I'm seeking to match the 'Serial.read'
behaviour we don't actually want to block anyway,
so we'll ignore it for the moment and handle things
ourself for now.
*/
uint8_t theByte;
if (!available()) {
return NO_READ_DATA_AVAILABLE;
}
recv(_socket, &theByte, 1);
return theByte;
}
int NetworkConnection::isConnected() {
/*
*/
// TODO: If we want the 'Network*' classes to be generic we
// would need to handle this differently:
//Serial.println(getSn_SR(_socket), HEX);
return (getSn_SR(_socket) == SOCK_ESTABLISHED);
}
void NetworkConnection::print(uint8_t b) {
/*
*/
if (isConnected()) {
send(_socket, &b, 1);
} else {
// Just drop it if we're not connected.
}
}
void NetworkConnection::print(const char * text) {
/*
*/
for (int idx = 0; idx < strlen(text); idx++) {
print(text[idx]);
Serial.print(text[idx]);
}
}
void NetworkConnection::close() {
/*
*/
// TODO: Determine if we need/want the disconnect (see pg 26 W5100)
::close(_socket);
disconnect(_socket);
}
/* ----------------------- */
/* -- NetworkInterface -- */
#define HANDLE_BAD_ERROR() while (1) {};
// TODO?: Do we want to have a "default" socket accessible by 'Network.read()' etc?
class NetworkInterface {
public:
NetworkInterface(Wiz810MjDevice& networkDevice);
NetworkConnection listen(uint16_t port);
NetworkConnection connect(byte b0, byte b1, byte b2, byte b3, uint16 port);
Wiz810MjDevice& device; // TODO: Make this a generic "network device" interface
};
NetworkInterface::NetworkInterface(Wiz810MjDevice& networkDevice) : device (networkDevice) {
/*
Note: The "weirdness" in this function declaration is a "initalization list",
i.e. this bit:
) : device (networkDevice) {
it is needed to give the 'device' Reference a value supplied to the method
rather than having a new 'Wiz810MjDevice' instance created.
*/
// This may not be the best place to do all this, but it'll do for now:
device.setMac(0x02,0xDE,0xAD,0xBE,0xEF,0x00);
device.setIp(169,254,254,169); // A local-link IP -- NOTE: This is out of spec.
device.setMask(255,255,0,0); // Matches local-link IP /16
device.setGateway(0,0,0,0); // We can't even guess this, so just skip it.
};
NetworkConnection NetworkInterface::listen(uint16_t port) {
/*
NOTE: For reasons I don't understand, this FAILS TO WORK if port >255.
The port that gets opened is ~(port mod 255) but if you limit
port to be uint8_t for example you don't get an error until
the port number is bigger than 'long'.
TODO: Track and fix this for port numbers > 255.
Returns a NetworkConnection listening on the specified TCP port.
*/
NetworkConnection connection = NetworkConnection(port);
// TODO: How to best handle errors?
// There's two major categories I can think of currently:
// 1) A socket wasn't available to listen in the first place
// 2) The listen attempt failed for some reason
// Using 'HANDLE_BAD_ERROR()' (currently an infinite loop) is
// not ideal but should prevent the above errors slipping by unnoticed.
if (!connection.listen()) {
HANDLE_BAD_ERROR();
}
return connection;
}
NetworkConnection NetworkInterface::connect(byte b0, byte b1, byte b2, byte b3, uint16 port) {
/*
*/
NetworkConnection connection = NetworkConnection(4000);
byte _scratchBuffer[4]; // TODO: Move this?
// TODO: Better?
_scratchBuffer[0] = b0;
_scratchBuffer[1] = b1;
_scratchBuffer[2] = b2;
_scratchBuffer[3] = b3;
if (!connection.connect(_scratchBuffer, port)) {
HANDLE_BAD_ERROR();
}
return connection;
}
// NetworkInterface Network = NetworkInterface(...); // TODO: Make this a global
/* ----------------------- */
/* ----- EchoServer ------ */
#define ECHO_CONNECT_WAIT 0
#define ECHO_CONNECTED 1
#define ECHO_CLOSE 2
#define ECHO_HALT 3
class EchoServer {
public:
EchoServer(int port);
void next(); // TODO: Return something useful?
private:
NetworkConnection _connection; // TODO: Make public?
int _state;
};
EchoServer::EchoServer(int port) : _connection (NetworkConnection(port)) {
/*
*/
_state = ECHO_CONNECT_WAIT;
_connection.listen(); // TODO: We should be using Network.listen(...) here and in initialisation list.
}
void EchoServer::next() {
/*
*/
// TODO: Use better state machine implementation?
if (_state == ECHO_CONNECT_WAIT) {
if (_connection.isConnected()) {
_state = ECHO_CONNECTED;
} else {
// Keep waiting
}
} else if (_state == ECHO_CONNECTED) {
if (_connection.available()) {
_connection.print(_connection.read());
} else if (!_connection.isConnected()) {
// Data finished and client disconnected
_state == ECHO_CLOSE;
}
} else if (_state == ECHO_CLOSE) {
_connection.close();
_state = ECHO_HALT;
} else if (_state == ECHO_HALT) {
// Do nothing
} else {
// Unknown state, do nothing.
}
}
/* ----------------------- */
// #define PIN_RESET 9 // WIZnet module /RESET
#define PIN_RESET 8 // WIZnet module /RESET
SOCKET testSocket;
byte ip[6];
#define PIN_LED 2
//------
// Note: Probably not efficient or anything...
class StreamConnection {
public:
StreamConnection(NetworkConnection& connection);
int peekByte();
int readByte();
int skipSegment(const char * separators); // TODO: Return if separators found or not?
int readSegmentByte(const char * separators);
int debug;
int gobbleMatch(const char * separators, const char * target);
private:
NetworkConnection& _connection;
int _byteSeen;
};
StreamConnection::StreamConnection(NetworkConnection& connection) : _connection (connection) {
/*
*/
_byteSeen = -1;
debug = 0;
}
int StreamConnection::peekByte() {
/*
*/
if (_byteSeen < 0) {
if (_connection.available()) {
_byteSeen = _connection.read();
}
}
return _byteSeen;
}
int StreamConnection::readByte() {
/*
*/
int newByte = -1;
if (_byteSeen < 0) {
if (_connection.available()) {
newByte = _connection.read();
}
} else {
newByte = _byteSeen;
_byteSeen = -1;
}
if (debug == 1) {
Serial.print(newByte, BYTE);
}
return newByte;
}
int StreamConnection::readSegmentByte(const char * separators) {
/*
*/
// Blocks
while (peekByte() < 0) { // TODO: Time out?
delay(500);
}
if (!strchr(separators, peekByte())) {
return readByte();
}
return -1;
}
int StreamConnection::skipSegment(const char * separators) {
/*
*/
if (debug == 1) {
Serial.println("Start skipping non-separator");
}
do {
if (peekByte() < 0) {
return -1;
}
// Skip everything not a separator
} while (!strchr(separators, peekByte()) && readByte());
if (debug == 1) {
Serial.println("Finished skipping non-separator");
}
do {
/* // We can't return here or we get stuck above.
if (peekByte() < 0) {
return -1;
}*/
while (peekByte() < 0) {
delay(500); // TODO: Time out?
}
// Skip everything that *is* a separator
} while (strchr(separators, peekByte()) && readByte());
if (debug == 1) {
Serial.println("Finished skipping separator");
}
return 1;
}
int StreamConnection::gobbleMatch(const char * separators, const char * target) {
/*
*/
int idx = 0;
int byteRead = -1;
while ((byteRead = readSegmentByte(separators)) >=0) {
if (idx < strlen(target)) {
if (byteRead != target[idx]) {
break;
}
idx++;
} else {
break;
}
}
if ((byteRead == -1) && (idx == strlen(target))) { // Matched
while (skipSegment(separators) < 0) {
// Ummm, we ran outta data--this screws things up...
// TODO: Have a time out?
delay(500);
}
return 1;
}
return -1;
}
//------
void setup () {
Serial.begin(9600);
Serial.println("Setup enter...");
Serial.println("Start W5100 configuration...");
SPI.begin();
Wiz810MjDevice WIZ810MJ = Wiz810MjDevice(PIN_RESET);
NetworkInterface Network = NetworkInterface(WIZ810MJ);
Network.device.setIp(192,168,2,105);
Network.device.setMask(255,255,255,0);
Network.device.setGateway(192,168,2,101);
Serial.println("End W5100 configuration...");
pinMode(PIN_LED, OUTPUT);
digitalWrite(PIN_LED, HIGH);
Serial.println("Setup exit...");
// Serial.println(((analogRead(2)*70)/630)/10+'0', BYTE);
/**/
Serial.println("Test sockets...");
#if 1
#if 1 //b
NetworkConnection conn = Network.connect(209,177,146,34, 6667); // TODO: Better?
Serial.println("Waiting to connect...");
while (!conn.isConnected()) {
//Serial.print(!conn.isConnected());
delay(500);
}
Serial.println("Connected...");
int byteRead = -1;
int dataWait = 0;
StreamConnection stream = StreamConnection(conn);
conn.print("NICK Arduino\n");
conn.print("USER Arduino 0 0 Arduino\n");
byte buf[4] = {0, 0, 0, 0};
int state = 0;
while (conn.isConnected()) {
#if 1 //c
if (stream.peekByte() >= 0) {
// New line
//Serial.println("Process new line...");
if (stream.peekByte() != ':') {
// Skip local responses/messages entirely. TODO: Handle PINGs?
while (stream.skipSegment("\x0A\x0D") < 0) {
// Ummm, we ran outta data--this screws things up...
// TODO: Have a time out?
delay(500);
}
} else {
//Serial.println(state, HEX);
if (state == 0) {
// Skip sending servername // TODO: Check it's the main one?
while (stream.skipSegment(" ") < 0) {
// Ummm, we ran outta data--this screws things up...
// TODO: Have a time out?
delay(500);
}
for (int idx=0; idx < 3; idx++) {
while (stream.peekByte() < 0) { // TODO: Time out?
delay(500);
}
buf[idx] = stream.readByte();
//Serial.print(buf[idx], BYTE);
}
//Serial.print("//");
Serial.println((const char *) buf);
if (strcmp((const char *) buf, "376") == 0) { // End MOTD
state=1;
conn.print("JOIN #arduino\n");
//stream.debug = 1;
}
} else if (state == 1) {
//stream.debug = 1;
//Serial.println("Skip servername");
// Skip sending servername // TODO: Check it's the main one?
while (stream.skipSegment(" ") < 0) {
// Ummm, we ran outta data--this screws things up...
// TODO: Have a time out?
delay(500);
}
//stream.debug = 0;
/*
int idx = 0;
const char * PRIVMSG = "PRIVMSG";
//Serial.println("Checking for PRIVMSG.");
//stream.debug = 1;
while ((byteRead = stream.readSegmentByte(" ")) >=0) {
if (idx < strlen(PRIVMSG)) {
if (byteRead != PRIVMSG[idx]) {
break;
}
idx++;
} else {
break;
}
}
// stream.debug = 0;
//Serial.println("Finished check PRIVMSG, determining result.");
if ((byteRead == -1) && (idx == strlen(PRIVMSG))) { // Matched
//Serial.println("Matched.");
while (stream.skipSegment(" ") < 0) {
// Ummm, we ran outta data--this screws things up...
// TODO: Have a time out?
delay(500);
}
*/
if (stream.gobbleMatch(" ", "PRIVMSG") > 0) {
/* **
while ((byteRead = stream.readSegmentByte("\x0A\x0D")) >=0) {
Serial.print(byteRead, BYTE);
}
Serial.println("");
*/
Serial.println("Matched PRIV MSG");
if (stream.gobbleMatch(" :", "#arduino") > 0) { // We treat the ":" as a separator too--does this break?
Serial.println("Matched #arduino");
//Serial.println(stream.peekByte(), HEX);
//if (stream.gobbleMatch("\x0A\x0D", "arduino:") > 0) {
//if (stream.gobbleMatch(":", "Arduino") > 0) {
//Serial.println("Matched Arduino");
if ((stream.peekByte() == 'A') && (stream.gobbleMatch(":", "Arduino") > 0)) {
Serial.println("Matched something");
//conn.print("PRIVMSG #arduino :Huh, what? Was someone talking to me?\n");
conn.print("PRIVMSG #arduino :My current pot status is ");
conn.print(((analogRead(2)*70)/630)/10+'0');
conn.print("3%, man!\n");
}
}
} else {
//Serial.println("No match.");
}
} else {
while ((byteRead = stream.readSegmentByte("\x0A\x0D")) >=0) {
Serial.print(byteRead, BYTE);
}
Serial.println("");
}
//Serial.println("Skipping this:");
//stream.debug = 1;
while (stream.skipSegment("\x0A\x0D") < 0) {
// Ummm, we ran outta data--this screws things up...
// TODO: Have a time out?
delay(500);
}
//stream.debug = 0;
//Serial.println("\nFinish skipping.");
}
}
#else //c
if (conn.available()) {
byteRead = conn.read();
Serial.print(byteRead, BYTE);
if (byteRead == '\n') {
dataWait++;
Serial.println(dataWait, DEC);
}
if (dataWait==4) {
//conn.print("NICK Arduino\n");
//conn.print("USER Arduino Arduino Arduino Arduino\n");
dataWait++;
}
if (dataWait==67) {
conn.print("JOIN #arduino\n");
//conn.print("PRIVMSG #arduino :Hello, world!\n");
//delay(10000);
conn.print("QUIT\n");
dataWait++;
}
//conn.print(conn.read());
} else {
//dataWait++;
//Serial.print(dataWait, DEC);
}
#endif //c
}
Serial.println("");
conn.close();
#else //b
NetworkConnection conn = Network.listen(7);
Serial.println("Waiting for connection...");
while (!conn.isConnected()) {
//Serial.print(!conn.isConnected());
delay(500);
}
Serial.println("Connected...");
while (conn.isConnected()) {
if (conn.available()) {
// Serial.print(conn.read(), BYTE);
conn.print(conn.read());
}
}
Serial.println("");
conn.close();
#endif //b
#else
// This uses the 1-argument constructor of EchoServer and supplies it with 7 for each instance.
EchoServer servers[MAX_SOCK_NUM] = {7, 7, 7, 7}; // This will break if MAX_SOCK_NUM changes.
while (1) {
for (int i=0; i<MAX_SOCK_NUM; i++) {
servers[i].next();
}
}
#endif
Serial.println("End test and dummy loop");
while (1) {}
/**/
}
#if 0
void sendBanner(uint8_t *buffer, int ledState) { // {Socket targetSocket, ) {
//strcpy((char *) buffer, "Content-Type: text/plain\n\nfoo!\n");
strcpy((char *) buffer, "HTTP/1.1 200 OK\nContent-Type: text/html\n\n<html><body bgcolor='#000000'>foo!</body></html>\n");
if (ledState) {
buffer[63] = 'F';
} else {
buffer[65] = 'F';
}
Serial.print("send result: ");
Serial.println(send(testSocket, buffer, strlen((char *)buffer)), DEC);
}
uint8_t readByte() {
uint8_t theByte;
recv(testSocket, &theByte, 1);
return theByte;
}
int readMatch(char *stringToMatch) {
/*
Routine to read and match bytes received.
(Essentially strcmp replacement without requiring a large receive buffer.)
NOTE: Failed matches drop all bytes read so far. (i.e. you can't check for
a bunch of possible matches from the same starting position).
TODO: Fix this.
Note: This blocks if there isn't enough data in the rx buffer.
*/
while (getSn_RX_RSR(testSocket) < strlen(stringToMatch)) {
// block
// TODO: Return error or wait or "too short"?
}
// TODO: Do fancy string-matching techniques to avoid reading the whole string
// on non-matches. :-)
for (int currCharIdx = 0; currCharIdx < strlen(stringToMatch); currCharIdx++) {
if (readByte() != stringToMatch[currCharIdx]) {
return 0;
}
}
return 1;
}
void loop() {
Serial.println("Test W5100 socket...");
Serial.print("Create socket result: ");
Serial.println(socket(testSocket, Sn_MR_TCP, 80, 0), DEC);
Serial.print("Socket status: ");
Serial.println(IINCHIP_READ(Sn_SR(testSocket)), HEX);
if (IINCHIP_READ(Sn_SR(testSocket)) == SOCK_CLOSED) {
Serial.println("Socket still closed, waiting...");
while (IINCHIP_READ(Sn_SR(testSocket)) == SOCK_CLOSED) {
//pass
}
}
Serial.print("Listen on socket result: ");
Serial.println(listen(testSocket), DEC);
Serial.println("Waiting for connection...");
while (getSn_SR(testSocket) == SOCK_LISTEN) {
delay(500);
}
Serial.println(getSn_SR(testSocket),HEX);
getSn_DIPR(testSocket, ip);
Serial.print("Destination IP read (last digit): ");
Serial.println(ip[3], DEC);
// TODO: Avoid buffer overflows...
#define MAX_TX_BUFFER_SIZE 200
uint8_t bytesToSend[MAX_TX_BUFFER_SIZE];
//sendBanner(bytesReceived);
int dataLength = 0;
#define STATE_GET 0
#define STATE_READ 5
#define STATE_END -2
#define STATE_ERR -1
int state = STATE_GET;
int ledState = 1;
unsigned char theByte;
while (getSn_SR(testSocket) == SOCK_ESTABLISHED) {
while (getSn_RX_RSR(testSocket) > 0) {
if (state == STATE_GET) {
if (readMatch("GET /")) {
state = STATE_READ;
} else {
state = STATE_ERR;
}
}
if (state == STATE_READ) {
theByte = readByte();
if (theByte == '0') {
digitalWrite(PIN_LED, LOW);
ledState = 0;
delay(100);
} else if (theByte == '1') {
digitalWrite(PIN_LED, HIGH);
ledState = 1;
delay(100);
} else {
// It's not a valid byte.
state = STATE_END;
}
} else {
state = STATE_ERR;
}
if ((state == STATE_ERR) || (state == STATE_END)) {
Serial.println("");
break;
}
/*
dataLength = getSn_RX_RSR(testSocket);
if (dataLength >= MAX_RX_BUFFER_SIZE) { // TODO: blah, blah...
dataLength = MAX_RX_BUFFER_SIZE-1;
}
// Serial.print("dataLength: "); Serial.println(dataLength, HEX);
//Serial.print("recv result: ");
//Serial.println(recv(testSocket, bytesReceived, dataLength), DEC); // NOTE: Throws away unread portion? No?
recv(testSocket, bytesReceived, dataLength); // TODO: Return length?
bytesReceived[dataLength]=0x00;
Serial.print((char *)bytesReceived);
//Serial.print("send result: ");
//Serial.println(send(testSocket, bytesReceived, dataLength), DEC);
*/
}
sendBanner(bytesToSend, ledState);
break;
}
close(testSocket);
disconnect(testSocket);
Serial.println("End test W5100 socket...");
}
#else
void loop() {
}
#endif