diff --git a/branches/follower/wiz810mj/src/demo/WizDemo6/WizDemo2.pde b/branches/follower/wiz810mj/src/demo/WizDemo6/WizDemo2.pde new file mode 100644 index 0000000..8b00e8f --- /dev/null +++ b/branches/follower/wiz810mj/src/demo/WizDemo6/WizDemo2.pde @@ -0,0 +1,328 @@ +/* + + Code to test wiznet WIZ810MJ module + + See: + + + + Current features: + + * Initial W5100 driver port: + + + new-style network configuration + + + socket creation/listening/closing + + + Sending/Receiving okay + + + example "echo" server (no longer) + + + example "web server" with LED flash. + + * Terrible hacked-together code + + Author: + + follower@rancidbacon.com + + License: + + LGPL + + Version: + + 20071106-0005+ + +*/ + +#include + + + +// 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) + +// #define PIN_RESET 9 // WIZnet module /RESET + +#define PIN_RESET 8 // WIZnet module /RESET + +SOCKET testSocket; +byte ip[6]; + +void configureSPI() { + /* + + 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< "); + + Serial.print("send result: "); + //Serial.println(send(testSocket, buffer, 6), DEC); + Serial.println(send(testSocket, buffer, strlen((char *)buffer)), DEC); +} + +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\nfoo!\n"); + if (ledState) { + buffer[63] = 'F'; + } else { + buffer[65] = 'F'; + } + + Serial.print("send result: "); + Serial.println(send(testSocket, buffer, strlen((char *)buffer)), DEC); +} + + +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 in both cases... +#define MAX_RX_BUFFER_SIZE 5 +#define MAX_TX_BUFFER_SIZE 200 + uint8_t bytesReceived[MAX_RX_BUFFER_SIZE]; // NOTE: Actual buffer should be larger. + + uint8_t bytesToSend[MAX_TX_BUFFER_SIZE]; + + //sendBanner(bytesReceived); + + //sendPrompt(bytesReceived); + + int dataLength = 0; + +#define STATE_G 0 +#define STATE_E 1 +#define STATE_T 2 +#define STATE_SPACE 3 +#define STATE_SLASH 4 + +#define STATE_READ 5 + +#define STATE_END -2 + +#define STATE_ERR -1 + int state = STATE_G; + int ledState = 1; + unsigned char theByte; + + while (getSn_SR(testSocket) == SOCK_ESTABLISHED) { + while (getSn_RX_RSR(testSocket) > 0) { + recv(testSocket, bytesReceived, 1); + theByte = bytesReceived[0]; + //Serial.print(bytesReceived[0], BYTE); + Serial.print(theByte, BYTE); + if ((state == STATE_G) && (theByte == 'G')) { + state = STATE_E; + } else if ((state == STATE_E) && (theByte == 'E')) { + state = STATE_T; + } else if ((state == STATE_T) && (theByte == 'T')) { + state = STATE_SPACE; + } else if ((state == STATE_SPACE) && (theByte == ' ')) { + state = STATE_SLASH; + } else if ((state == STATE_SLASH) && (theByte == '/')) { + state = STATE_READ; + } else if ((state == STATE_READ) && (theByte == '0')) { + digitalWrite(PIN_LED, LOW); + ledState = 0; + //state = STATE_END; + delay(100); + } else if ((state == STATE_READ) && (theByte == '1')) { + digitalWrite(PIN_LED, HIGH); + ledState = 1; + //state = STATE_END; + delay(100); + } else if (state == STATE_READ) { + // 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); + + //sendPrompt(bytesReceived); + */ + + } + sendBanner(bytesToSend, ledState); + //sendPrompt(bytesReceived); + break; + } + + close(testSocket); + disconnect(testSocket); + + Serial.println("End test W5100 socket..."); + + + +} + diff --git a/branches/follower/wiz810mj/src/demo/WizDemo6/WizDemo3.pde b/branches/follower/wiz810mj/src/demo/WizDemo6/WizDemo3.pde new file mode 100644 index 0000000..7c20cf6 --- /dev/null +++ b/branches/follower/wiz810mj/src/demo/WizDemo6/WizDemo3.pde @@ -0,0 +1,346 @@ +/* + + Code to test wiznet WIZ810MJ module + + See: + + + + Current features: + + * Initial W5100 driver port: + + + new-style network configuration + + + socket creation/listening/closing + + + Sending/Receiving okay + + + example "echo" server (no longer) + + + example "web server" with LED flash. + + * Terrible hacked-together code + + Author: + + follower@rancidbacon.com + + License: + + LGPL + + Version: + + 20071106-0005+ + +*/ + +#include + + + +// 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) + +// #define PIN_RESET 9 // WIZnet module /RESET + +#define PIN_RESET 8 // WIZnet module /RESET + +SOCKET testSocket; +byte ip[6]; + +void configureSPI() { + /* + + 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<foo!\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..."); + + + +} + diff --git a/branches/follower/wiz810mj/src/demo/WizDemo6/WizDemo4.pde b/branches/follower/wiz810mj/src/demo/WizDemo6/WizDemo4.pde new file mode 100644 index 0000000..2775b54 --- /dev/null +++ b/branches/follower/wiz810mj/src/demo/WizDemo6/WizDemo4.pde @@ -0,0 +1,732 @@ +/* + + Code to test wiznet WIZ810MJ module + + See: + + + + 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 + + +/* --------- 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<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; +} + +// 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 + +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); + + Serial.println("End W5100 configuration..."); + + pinMode(PIN_LED, OUTPUT); + digitalWrite(PIN_LED, HIGH); + + Serial.println("Setup exit..."); + +/**/ + Serial.println("Test sockets..."); + +#if 0 + 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 + + // 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; ifoo!\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 diff --git a/branches/follower/wiz810mj/src/demo/WizDemo6/WizDemo5.pde b/branches/follower/wiz810mj/src/demo/WizDemo6/WizDemo5.pde new file mode 100644 index 0000000..d376b32 --- /dev/null +++ b/branches/follower/wiz810mj/src/demo/WizDemo6/WizDemo5.pde @@ -0,0 +1,1131 @@ +/* + + Code to test wiznet WIZ810MJ module + + See: + + + + 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 + + +/* --------- 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<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; ifoo!\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