Skip to content

Programming Demo

In case anyone was sceptical that the server was really running on the 1802:

Emergency Debugging Continued

First, I keep having to re-find the blog post I originally based the server on. It was done for the w5100 but it’s been a lot of help so herewith

Thanks again to rwb on ermicroblog
for http://www.ermicro.com/blog/?p=1773.

Once I had some hard data to look at, I realized I had the wrong idea about the failure.  Because the 1802 had gone unresponsive, I assumed it was in a tight loop or had hit an idle op code due to a memory overwrite.  The dump seemed to indicate that it was trucking along executing reasonable-looking instructions.  Doing a hand trace I found it was in a section of the “send0” routine that is checking for completion of a send.  It’s looking for the 0x10 bit to be set in SnIR but it never sees it.  Instead it is seeing 0x01 which is described in the data sheet as the connection interrupt http://www.mouser.com/pdfdocs/w5500_ds_v100e.PDF

Googling around I see someone with a similar issue on the W5100. It looks like this is something that can happen with some sort of send/receive/connect collision.
https://code.google.com/p/arduino/issues/detail?id=1049

The response from wiznet seems to indicate that by polling for the interrupt you could miss it. I think they recommend instead checking that SnTX_RD==SnTX_WR

In my original version of this for the w5100(adapted from the blog post referred to above) I never checked the interrupt register. I just made sure that the command register had been set to 0. I started checking the interrupt register when I was having big problems in february. Those problems were completely unrelated so i may just drop the whole interrupt register check.

I’m going to leave it alone for the weekend though since I seem to be the only one that can break it and it’s theoretically live for the VCFMW.

For my records:

16:59:17.748> memory from 2900
16:59:17.829> 0000: D3E2 8622 7396 5283 A693 B646 B346 A330
16:59:17.829> 0010: 00D3 86A3 96B3 42B6 42A6 3011 F824 FF01
16:59:17.909> 0020: 3A1E D5F8 00AF BF9D F6BD 8D76 AD3B 3B22
16:59:17.909> 0030: 8C52 8FF4 AF9C 529F 74BF 129D 3A41 8D32
16:59:17.909> 
16:59:17.909> registers 1-14
16:59:17.998> 0001: 0003
16:59:17.998> 0002: 7E73
16:59:17.998> 0003: 18C1
16:59:17.998> 0004: 2906
16:59:17.998> 0005: 2912
16:59:17.998> 0006: 1A68
16:59:17.998> 0007: 6969
16:59:17.998> 0008: 081A
16:59:17.998> 0009: 6819
16:59:18.103> 000A: 8569
16:59:18.103> 000B: 0820
16:59:18.103> 000C: 7B00
16:59:18.103> 000D: 0208
16:59:18.103> 000E: 087E
16:59:18.103> 
16:59:18.103> stack area
16:59:18.209> 7E60: DCF8 63AC 0003 7E73 18C1 2906 2912 1A68
16:59:18.209> 7E70: 6969 081A 6819 8569 0820 7B00 0208 087E
16:59:18.209> 7E80: 8400 0100 0307 4A00 021C 1F22 8000 0222
16:59:18.318> 7E90: 9821 1300 1000 0022 981C 1D00 6122 8022
16:59:18.318> 7EA0: 8201 3922 8022 8000 0100 0303 7327 4D1C
16:59:18.427> 7EB0: 0705 0227 3100 0002 0706 E402 0706 E100
16:59:18.427> 7EC0: 1000 0006 D000 0626 3C26 4300 060C 2300
16:59:18.427> 7ED0: 8000 800C FB00 170D 177F 0025 7A00 1714
16:59:18.522> 7EE0: 280A 0000 2807 0014 C0A8 00B6 0D8F 6900
16:59:18.522> 7EF0: 1428 0A00 1428 0700 17C0 A800 B60D 8F69
unsigned int send0(unsigned char *buf,unsigned int buflen){
    unsigned int timeout,txsize,txfree;
    unsigned char intval;
	unsigned int txwr;
	//printf("send0 %d\n",buflen);
    if (buflen <= 0) return 0;
    // Make sure the TX Free Size Register shows enough room
    txfree=wizGetCtl16(SnTX_FSR);
	//printf("free %d\n",txfree);
    timeout=0;
    while (txfree < buflen) {
      delay(1);
     txfree=wizGetCtl16(SnTX_FSR);
     // Timeout for approx 1000 ms
     if (timeout++ > 1000) {
       	printf("TX Free Size Error!\n");
		wizCmd(CR_DISCON);// Disconnect the connection
       	return 0;
     }
   }


   	txwr=wizGetCtl16(SnTX_WR);  // Read the Tx Write Pointer
   	wizWrite(txwr,WIZNET_WRITE_S0TX,buf, buflen); //write the outgoing data to the transmit buffer
   	wizSetCtl16(SnTX_WR,txwr+buflen);//update the buffer pointer
	wizCmd(CR_SEND); // Now Send the SEND command which tells the wiznet the pointer is updated
	intval=wizGetCtl8(SnIR); //get the interrupt status
	//printf ("post send interrupt status is %cx\n",intval);
	while((intval&0x10)!=0x10){ //wait for sendok status
		intval=wizGetCtl8(SnIR); //get the interrupt status
	}*****THIS IS WHERE I WAS LOOPING***
	wizSetCtl8(SnIR,0x15);//reset interrupt status
	//printf("Interrupt register reset\n");
    return 1;
}

Emergency Debugging

I have some kind of evil problem with the web server where it is going into a loop or hanging somewhere. It’s probably a memory overwrite. I beat my head against it with diagnostic prints but no joy. I decided to do an emergency dump of registers and memory on startup and put a routine to print the dump into the first part of the web server.
The dump routine I put into LCC1802epiloDH which has the startup routines that prep the registers and give control to main(). Before initializing the regs I dump regs 1-14(0 and 15 are already corrupted), then copy memory from 0-100 and the top 128 bytes of the stack page into a reserved area(I moved the runtime stack down to start at 7EFF and the emergency dump area is 7F00:7FFF).
The code is in sastore.inc included into lcc1802epilodh and sadump.c included into the main routine. The output looks correct, now I just need a failure.

15:25:55.529> low memory
15:25:55.607> 0000: C027 7400 0000 0000 0000 2222 2287 7397
15:25:55.732> 0008: 5222 2222 228C A79C B782 FC06 AE92 7C00
15:25:55.732> 0010: BEF8 005E 1EF8 035E F86E ACF8 27BC 82FC
15:25:55.732> 0018: 06AD 927C 00BD D412 C5F8 69AC F827 BCF8
15:25:55.928> 0020: 80AD F822 BDD4 12C5 07AC F800 BCF8 80AD
15:25:55.928> 0028: F822 BDD4 0EC5 8FAB 9FBB 8BAC 9BBC D420
15:25:55.928> 0030: DCF8 63AC 0014 7ECF 0D0E 2901 2912 0D92
15:25:55.928> 
15:25:55.928> registers 1-14
15:25:55.928> 0001: 0014
15:25:55.928> 0002: 7ECF
15:25:55.928> 0003: 0D0E
15:25:55.928> 0004: 2901
15:25:55.928> 0005: 2912
15:25:55.928> 0006: 0D92
15:25:55.928> 0007: 0014
15:25:55.928> 0008: 7EC9
15:25:56.264> 0009: FEF3
15:25:56.264> 000A: 0000
15:25:56.264> 000B: 0014
15:25:56.264> 000C: 0014
15:25:56.264> 000D: 002E
15:25:56.264> 000E: 7EF8
15:25:56.264> 
15:25:56.264> stack area
15:25:56.264> 7E80: 0C7E 8900 010A A000 3100 0022 8000 3167
15:25:56.264> 7E90: D311 5300 0400 6400 6414 3100 017E 9F31
15:25:56.264> 7EA0: 0038 0027 0A67 D37E C300 0103 7600 801E
15:25:56.264> 7EB0: 9000 1000 001D 5E0C 1A24 3067 D312 C000
15:25:56.264> 7EC0: 0000 0819 8500 2E67 D37E DD00 010C 2600
15:25:56.264> 7ED0: 070C 5700 1400 800D 537F 0027 6200 0014
15:25:56.807> 7EE0: 2804 0014 2801 0017 C0A8 00B6 0D8F 6922
15:25:56.807> 7EF0: 9828 0400 1028 0100 14C0 A800 B601 3C69
sastore.inc
;Standalone reg save included at front of lcc1802init
	seq
	ldad r15,0x7f00+127	;begin register save
	sex r15			;set up for reg saves
	pushm r14
	pushm r13
	pushm r12
	pushm r11
	pushm r10
	pushm r9
	pushm r8
	pushm r7
	pushm r6
	pushm r5
	pushm r4
	pushm r3
	pushm r2
	pushm r1
;now copy 1st 100 bytes of  main memory
	ldad r15,0x7f00
	ldad r14,0x0000
	ldad r13,100
$$stm:
	lda r14
	str r15
	inc r15
	dec r13
	glo r13
	bnz $$stm
;now copy top 128 bytes of  stack area
	ldad r15,0x7f80
	ldad r14,0x7e80
	ldad r13,128
	
$$stk:
	lda r14
	str r15
	inc r15
	dec r13
	glo r13
	bnz $$stk
;end of standalone save
	req
	
sadump.c
//sadump print the contents of memory block 7f00-ff
//where init has saved registers and diagnostics
	unsigned int * sadptr=(unsigned int *)0x7f00;//pointer to sadump block
	unsigned int saloop;
	printf("\nlow memory\n");
	for (saloop=0; saloop<50;saloop+=8){
		printf("%x: %x %x %x %x %x %x %x %x\n",
				saloop, sadptr[saloop],sadptr[saloop+1],sadptr[saloop+2],sadptr[saloop+3],sadptr[saloop+4],sadptr[saloop+5],sadptr[saloop+6],sadptr[saloop+7]);
	}
	printf("\nregisters 1-14\n");
	for (saloop=1; saloop<15;saloop+=1){
		printf("%x: %x\n",
				saloop, sadptr[saloop+49]);
	}
	printf("\nstack area\n");
	for (saloop=64; saloop<128;saloop+=8){
		printf("%x: %x %x %x %x %x %x %x %x\n",
				saloop*2+0x7e00, sadptr[saloop],sadptr[saloop+1],sadptr[saloop+2],sadptr[saloop+3],sadptr[saloop+4],sadptr[saloop+5],sadptr[saloop+6],sadptr[saloop+7]);
	}

Hey! It worked!

15-08-25 firsttweet

I bodged together some code that established a session and issued a tweet! Nothing fancy like error checking but still, it worked! It’s using the technique in the arduino twitter library which uses sort of a twitter proxy at arduino-tweet.appspot.com. see https://arduino-tweet.appspot.com/

I don’t know if I have the nerve to put this stuff into the blinkenlights server. I would have to

  • initialize a second socket
  • keep track of when i wanted to tweet something (say a new ip address comes in)
  • in the main blinkenlights loop establish a safe spot
  • do the management and error control of the second socket the same way the main loop does socket 0
  • Also, poopoo to you google!

    Working on the compiler I set up a repository on google code and taught myself to use SVN and specifically tortoise svn.

    That was all fine until google pulled the plug on google code. I’m sure i’ll figure out eventually how to move to a new location but i still say poopoo to google.

    On Being a Web Client

    It’s a bit counter-intuitive but being a web server is quite a bit easier than being a client.  The client is usually a pretty sophisticated browser running on a capable machine so a lot is expected of it.  The server can get away with spewing out some fixed html but the client has to parse and deal with it.

    My servers usually open a socket and set it to listen on port 80, when a session is established they slurp in the request, pay not too much attention to it, and spit out a response.

    To be a client, you first have to find the ip of your target with dns, then you have to issue a connect and check that it works, then send your request, wait for a response, and deal with that.  You can also get redirection and any number of other complexities added in.

    To simplify things, I’m trying to work with an ip address that i’ve looked up in advance by pinging it.  www.google.ca pings to 24.156.153.25 so i’m bolting that into a variant of my server program and trying to connect rather than listen.  After a bunch of false starts I got google to respond with 2048 bytes of gobbledygook so that’s a start.

    The status code 15 means it’s in connection state equivalent to 14 for listen I guess. Code 17 is session established as usual. Once I got code 17 i just sent my request and started polling for available data. Quite quickly I got 2048 bytes back which was all i was set up to handle. I’m sure there’s some organized way of getting the next window of data. My goal though is to hit a twitter server so i’m hoping i don’t get that much back.

    
    /*****************************************************************************
    //  File Name    : w5500mule.c
    //  Version      : 1
    //  Description  : wiznet w5500 test harness
    //  Author       : WJR with thanks Karl Lunt & Wiznet
    //  Target       : Olduino
    //  Compiler     : LCC1802
    //  IDE          : TextPad
    //  Programmer   : Olduino bootloader via avrdude
    //  Created		 : Nov 26, 2014
    *****************************************************************************/
    #define	nofloats			//not using floating point
    #include <nstdlib.h> //for printf etc.
    #include <cpu1802spd4port7.h>
    #include <olduino.h> //for digitalRead, digitalWrite, delay
    #include <hspi2.h> //hardware spi header
    #include "w5500data.h"  //wiznet definitions
    #include "w5500code.h"  //wiznet code definitions
    union IPaddr thisip={182}; //the ip that a form/request came from
    #define MAX_BUF 1024
    unsigned char buf[MAX_BUF];			//memory buffer for incoming & outgoing data
    
    void sendreq(){//send a request
    	printf("getting response\n");
        sendlit("GET /search?q=olduino HTTP/1.1\n");
        sendlit("Host: www.google.ca\n");
        sendlit("Connection: close\n");
        sendlit("\n");
    }
    void getresp(){	//handle a session once it's established
    	unsigned int rsize,strncmpval;
    	unsigned int tries=100;
    	printf("getting response\n");
    	rsize=wizGetCtl16(SnRX_RSR); //get the size of the received data
    	while(rsize==0 && tries-->0){
    		delay(20);
    		printf("re-size ");
    		rsize=wizGetCtl16(SnRX_RSR); //retry size of the received data
    	}
    	printf("**rsz=%d\n",rsize);
    	if (rsize>0){
    		thisip.l=getip();
    		if (recv0(buf,min(1023,rsize))>0){ //get some characters
    			printf("%s\n",buf);
    		}
    	}
    	printf("flushing %d\n",rsize);
      	if (rsize>0) flush(rsize);	//get rid of the received data
    	wizCmd(CR_DISCON);// Disconnect the connection- we're done here
    	printf("done\n>\n");
    }
    
    
    void wizWrite(unsigned int addr, unsigned char opcode, void * data, unsigned int len);
    void socket0_client_init(){ //initialize socket 0 for http client
        unsigned char ggl_addr[]={24,156,153,25};//address for google destination
    	wizCmd(CR_CLOSE); //make sure port is closed
    	wizSetCtl8(SnIR,0xFF); //reset interrupt reg
    	wizSetCtl8(SnMR,MR_TCP); //set mode register to tcp
    	wizSetCtl16(SnPORT,1024); //set tcp port to 80
       	wizWrite(SnDIPR,WIZNET_WRITE_S0R,ggl_addr, 4); //write the outgoing dest ip address
       	wizSetCtl16(SnDPORT,80);//destination port
    	wizCmd(CR_OPEN); //open the port
    	wizCmd(CR_CONNECT); //try to make a conection
    }
    
    void main(void){
    	unsigned char socket0status;
        unsigned char ip_addr[] = {192,168,1,182}; //{169,254,180,2}; //
    	delay(100);
    	printf("\nW5500 Test Mule Client\n");
    	delay(500);
        wiz_Init(ip_addr); //initialize the wiznet chip
    	socket0_client_init();
    
    	while(1){  // Loop forever
    		socket0status=wizGetCtl8(SnSR);
    		printf("s0s=%cx ",socket0status);
    		if (socket0status==SOCK_ESTABLISHED){ //we're connected
    			sendreq();
    			getresp();
    			printf("stalling\n");
    			while(1);//loop here
    		}
    		delay(100);
    	}
    }
    #include <olduino.c>
    #include <nstdlib.c>
    #include <hspi2.c>
    #include "w5500code.c"
    

     

    13:14:51.777> W5500 Test Mule Client
    13:14:52.399> Done Wiznet W5500 Initialization on IP address 192.168.1.182
    13:14:52.399> Gateway Address 192.168.1.1
    13:14:52.399> 
    13:14:52.711> s0s=15 s0s=15 s0s=17 getting response
    13:14:52.711> getting response
    13:14:52.836> re-size re-size re-size re-size **rsz=2048
    13:14:52.898> HTTP/1.1 200 OK
    13:14:52.898> 
    13:14:52.898> Date: Tue, 25 Aug 2015 17:14:52 GMT
    13:14:52.898> 
    13:14:52.898> Expires: -1
    13:14:52.898> 
    13:14:52.898> Cache-Control: private, max-age=0
    13:14:52.898> 
    13:14:52.898> Content-Type: text/html; charset=ISO-8859-1
    13:14:52.898> 
    13:14:52.962> P3P: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info."
    13:14:52.962> 
    13:14:52.962> Server: gws
    13:14:52.962> 
    13:14:52.962> X-XSS-Protection: 1; mode=block
    13:14:52.962> 
    13:14:52.962> X-Frame-Options: SAMEORIGIN
    13:14:52.962> 
    13:14:53.024> Set-Cookie: PREF=ID=1111111111111111:FF=0:TM=1440522892:LM=1440522892:V=1:S=bPgUObdOy_1YCzrj; expires=Thu, 31-Dec-2015 16:02:17 GMT; path=/; domain=.google.ca
    13:14:53.024> 
    Set-Cookie: NID=70=JE6B7I2GKHSsE6xgpnZXSWt0-IS-Ww2BOKj8BNsJysk7nm2MzFYMW4Csmp_q70-oChJBLK3_v-13:14:53.086> gEbWbfQF4velwKkswhCYo2gWR7zezRcZ9q0BldXAQGzdSh2vN_0KPP; expires=Wed, 24-Feb-2016 17:14:52 GMT; path=/; domain=.google.ca; HttpOnly
    13:14:53.086> 
    13:14:53.086> Accept-Ranges: none
    13:14:53.086> 
    13:14:53.086> Vary: Accept-Encoding
    13:14:53.086> 
    13:14:53.086> Connection: close
    13:14:53.086> 
    13:14:53.086> 
    13:14:53.086> 
    <!doctype html><html itemscope="" 13:14:53.148> itemtype="http://schema.org/SearchResultsPage" lang="en-CA"><head><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"><meta content="/images/google_favicon_128.png" itemprop
    13:14:53.148> flushing 2048
    13:14:53.148> done
    13:14:53.148> >
    13:14:53.148> stalling
    

    Well, That Was Easy!

    15-08-22 Server Text15-08-22 W5500

    Very simple changes to the blinkenlights server and it worked the first time!  Most of the code for the W5100 wiznet chip had been included inline in the olduino server.  I mostly just had to delete all that and change the references to the control routines to what i had used for the W5500.  Not as easy as if it had been in a library but pretty simple.

    I’m going to do a couple more things:  I had made a version of this that showed an image of the stack with the LED either on or off, I’ll put those changes in.  I’ll also make sure I’m logging the IP where a page hit comes from just for fun.

    None of that will stop me from getting some pictures done and making a little poster for josh to take to the VCFMW.  I’ll plan to get it out to him Monday.

    
    /*****************************************************************************
    //  File Name    : olduinoserver4W5500.c
    //  Version      : 4.3
    //  Description  : olduino LED server
    //  Author       : WJR with thanks to RWB
    //  Target       : Olduino
    //  Compiler     : LCC1802
    //  IDE          : TextPad
    //  Programmer   : Olduino bootloader via avrdude
    //  Adaptated    : 17 May 2013 by Bill Rowe - WJR for the olduino platform
    //  Revised 	 : 22 Aug 2015 for the W5500
    *****************************************************************************/
    #define	nofloats			//not using floating point
    #include <nstdlib.h> //for printf etc.
    #include <cpu1802spd4port7.h> //defines processor type, speed, and host port
    #include <olduino.h> //for digitalRead, digitalWrite, delay
    #include <hspi2.h> //hardware spi header
    #include "w5500data.h"  //wiznet definitions
    #include "w5500code.h"  //wiznet code definitions
    
    #define MAX_BUF 512
    unsigned char buf[MAX_BUF];			//memory buffer for incoming & outgoing data
    int ledmode=0;	//0=off, 1=on
    union IPaddr cmdip,sessip; //most recent address where a command came from, current session ip
    int pages=0,sessions=0;
    char strbuf[16];
    void sendip(unsigned char * ip){
    	send0s(itoa(ip[0],strbuf));
    	sendlit(".");
    	send0s(itoa(ip[1],strbuf));
    	sendlit(".");
    	send0s(itoa(ip[2],strbuf));
    	sendlit(".");
    	send0s(itoa(ip[3],strbuf));
    }
    
    void sendCip(){
    	send0s("Last command from: ");
    	sendip(cmdip.c);
    	send0s("<p>");
    
    }
    void sendform(){
    	int sendrc;
    	static char hdr[]="HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n"
    						"<html><body><span style=\"color:#0000A0\">\r\n"
    						"<h1><center>Olduino 1802 Web Server V4.3.1</center></h1>\r\n";
    
    	static char postform[]="<p><form method=\"POST\">\r\n"
    						"<input type=\"submit\" value=\"Toggle Q LED\">\r\n"
    						"</form>";
    	static char getform[]="<p><form method=\"GET\">\r\n"
    						"<input type=\"submit\" value=\"Q LED Status\">\r\n"
    						"</form>";
    	static char trlr[]="</body></html>\r\n\r\n";
    
    	//printf(">SF\n");
    	pages+=1;
    	sendrc=send0s(hdr); 	// Now Send the HTTP Response first part
    	//printf("0\n");
    	send0s("Pages Served: "); send0s(itoa(pages,strbuf)); send0s("<p>");
    	//printf("1\n");
    	if (cmdip.c[0]!=0)
    		sendCip();
    	//printf("2\n");
    	sendrc=send0s("Q LED is ");
    	if (ledmode==1)
    		send0s("ON\r\n");
    	else
    		send0s("OFF\r\n");
    	sendrc=send0s(postform); 	// Now Send the "POST" form
    	sendrc=send0s(getform); 	// Now Send the "GET" form
    	sendrc=send0s(trlr); 	// Now Send the rest of the page
    	//printf("FS>\n");
    }
    int strindex(char *s,char *t)
    {
      unsigned int i,n;
    
      n=strlen(t);
      for(i=0;*(s+i); i++) {
        if (strncmp(s+i,t,n) == 0)
          return i;
      }
      return -1;
    }
    void handlepost(){
    	if (ledmode==1){
    		ledmode=0;
    		asm(" req\n"); //Q led off
    	} else {
    		ledmode=1;
    		asm(" seq\n"); //Q led on
    	}
    	cmdip.l=getip();
    	sendform();
    }
    void handlesession(){	//handle a session once it's established
    	unsigned int rsize,strncmpval;
    	unsigned int tries=10;
    	rsize=wizGetCtl16(SnRX_RSR); //get the size of the received data
    	while(rsize==0 && tries-->0){
    		delay(20);
    		printf("re-size ");
    		rsize=wizGetCtl16(SnRX_RSR); //retry size of the received data
    	}
    	printf("**rsz=%d\n",rsize);
    	if (rsize>0){
    		sessip.l=getip();
    		if (recv0(buf,min(16,rsize))>0){ //get enough characters to distinguish the request
    			printf("%s\n",buf);
      			if (strncmp((char *)buf,"POST /",6)==0){
      				handlepost(); //toggle LED, send the form
    			}
    			else if (strncmp((char *)buf,"GET /favicon",12)==0){
      				sendnak(); //no favicon here
    			}
      			else if (strncmp((char *)buf,"GET /",5)==0){
     				sendform(); //send the form
    			}
      			else{
    				printf("\nmystery meat\n");
     				sendform(); //initialize game, send the form
    			}
    		}
    		printf("flushing %d\n",rsize);
    		if (rsize>0) flush(rsize);	//get rid of the received data
    	}
    	wizCmd(CR_DISCON);// Disconnect the connection- we're done here
    	printf("done\n>\n");
    	sessions++;
    }
    void main(void){
    	unsigned char socket0status;
        unsigned char ip_addr[] = {192,168,1,182};//{169,254,180,2};//{10,0,0,180};//
        unsigned int SFWs=0; //count of times we've seen SOCK_FIN_WAIT
        printf("Olduino LED Server on W5500 4.3.1\n");
    	delay(500);
        wiz_Init(ip_addr); //initialize the wiznet chip
    	while(1){  // Loop forever
    		socket0status=wizGetCtl8(SnSR); //socket 0 status
    		switch (socket0status){
    			case SOCK_CLOSED: //initial condition
    				SFWs=0;
    				socket0_init();	//initialize socket 0
    				break;
    			case SOCK_ESTABLISHED: //someone wants to talk to the server
    				SFWs=0;
    				handlesession();
    				printf("%d sessions, %d pages\n",sessions,pages);
    				break;
    			//following are cases where we have to reset and reopen the socket
    			case SOCK_FIN_WAIT:
    				printf("SOCK_FIN_WAIT:");
    				if (++SFWs>2){
    					printf(" lost patience, closing\n");
    					wizCmd(CR_CLOSE);
    				}else{
    					printf(" ignoring\n");
    				}
    				break;
    			case SOCK_CLOSING: case SOCK_TIME_WAIT:
    			case SOCK_CLOSE_WAIT: case SOCK_LAST_ACK:
    				SFWs=0;
    				wizCmd(CR_CLOSE);
    				break;
    		}
    		delay(10);
    	}
    }
    
    #include <olduino.c>
    #include <nstdlib.c>
    #include <hspi2.c>
    #include "w5500code.c"
    
    Follow

    Get every new post delivered to your Inbox.