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.

425 lines
9.6 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 (no longer)
+ example "web server" with LED flash.
* Terrible hacked-together code
Author:
follower@rancidbacon.com
License:
LGPL
Version:
20071106-0005+
*/
#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);
private:
void _init(void);
byte * _packBuffer(byte b0, byte b1, byte b2, byte b3);
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) {
/*
*/
_scratchBuffer[0] = b0;
_scratchBuffer[1] = b1;
_scratchBuffer[2] = b2;
_scratchBuffer[3] = b3;
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));
}
/* ----------------------- */
// #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...");
SPI.begin();
Wiz810MjDevice WIZ810MJ = Wiz810MjDevice(PIN_RESET);
Serial.println("Test W5100 configuration...");
byte config_gateway[] = {192,168,2,101};
byte config_subnet_mask[] = {255,255,255,0};
byte config_mac_address[] = {0x02,0xDE,0xAD,0xBE,0xEF,0x00};
byte config_ip_address[] = {192,168,2,105};
setSHAR(config_mac_address);
WIZ810MJ.setIp(192,168,2,105);
WIZ810MJ.setMask(255,255,255,0);
WIZ810MJ.setGateway(192,168,2,101);
Serial.println("End test W5100 configuration...");
Serial.println("Test W5100 driver code...");
getGAR(ip);
Serial.print("Gateway IP read (first digit): ");
Serial.println(ip[0], DEC);
Serial.println("End test W5100 driver code...");
pinMode(PIN_LED, OUTPUT);
digitalWrite(PIN_LED, HIGH);
Serial.println("Setup exit...");
}
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...");
}