This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430 ethernet connectivity.

Other Parts Discussed in Thread: MSP430F149, MSP430F249

hi,

  I am using MSP430 along with ethernet controller CS8900. I need to connect the controller to PC through ethernet. I am able to send data to PC through ethernet, (i am using olimax easy - web board.). The controler has been assigned a ip address and i can see the data on my pc . here micro controller (MSP+ethernet controller) acts as a web server and pc acts as a clinet. I need a duplex communication. Pls help me how can i send data from pc to microcontroller through the ethernet.

 can i use the same code to make the micro controller act as a clinet??

Thanks in advance.

Regards,

Manmesha. 

  • manmesha patankar said:
    Pls help me how can i send data from pc to microcontroller through the ethernet.

    That is a pretty vague question. What do you mean by send data? You mention webserver, so do you mean simple HTTP protocol over IP from a browser on the PC requesting a page from MSP430? Or do you mean something else?

    If you have the link working, you should be able to use a suitable PC application to send IP packets out of the PC's ethernet port.

    manmesha patankar said:
    can i use the same code to make the micro controller act as a clinet?

    Hard to say, as we know nothing about your code. My gut feeling is no, without a lot of changing. It would depend on how close your API on the MSP430 matches the API on the PC that the client software is using (the driver stack).

  • manmesha patankar said:

    I am using MSP430 along with ethernet controller CS8900.  Pls help me how can i send data from pc to microcontroller through the ethernet.

    I'm not familiar with the CS8900.  However if you use the CC3000, we could help guide you through this example application.

    CC3000 HTTP Web Server Application for MSP430F5529

  • manmesha patankar said:
    micro controller (MSP+ethernet controller) acts as a web server and pc acts as a clinet. 

    So think about it: clearly it is, in general, possible for a web client to send data to a web server;  after all, you managed to send your post (which is just "data") from your PC web client ("browser") to the TI web server (this forum) - didn't you?!

    So you need to spend some time studying & understanding how the interaction between a web server & web client works.

    Here's a good tutorial to get you started: http://www.jmarshall.com/easy/

    Note that this is standard stuff - nothing specifically to do with microcontrollers or MSP430.

     

  • Andy Neil said:
    nothing specifically to do with microcontrollers or MSP430

    Also nothing specifically to do with Ethernet - the HTTP is oblivious to whatever transport is used.

    Think about it: your Browser neither knows nor cares whether your PC is using an Ethernet connection, or WiFi, or 3G - or even a dial-up phone line modem!

    This is the whole point of a layered architecture!

    http://en.wikipedia.org/wiki/OSI_model

    http://en.wikipedia.org/wiki/Protocol_stack

     

  • Hi Jason,

       Thanks a lot for your reply. I went through the link u provided. It uses a different MSP430 (I am using easyweb board that uses, MSP430F149 along with CS8900 ethernet controller). Moreover it says about evaluation board!! Is it possible to develop the same using simple MSP430 and CC3000 (w/o using a development board)? Pls provide me with some more info.

    Regards,

    Manmesha.

  • Hi Brain,

           I will elaborate. Yes. I meant simple HTTP protocol over TCP/IP from a browser on the PC that requests a page with IP address of my board (MSP430F149+Ethernet controller CS8900). MSP430 acts as a server as responds to this query.

        Now, I have access to MSP430 (i.e. i can download code into it ..). but I dont have access to CS8900 that is responsible for the actual transmission/reception over Ethernet  With the sample codes available i could use MSP430 acting as a client and my PC requesting for data (acting as a client). But now i am sure if the roles can be swapped (with given codes) where my MSP430 will act as a client and my PC as server.

    In addition to it, I want to develop a duplex communication between PC and MSP430 (i.e. MSP430 should b able to act as a server as well as a client at times, same with my PC. ) 

    Hope my query is more clear now...

    For ref. i am appending the code files.

    //------------------------------------------------------------------------------
    // Name: cs8900.c
    // Func: ethernet driver for use with LAN controller CS8900A
    // Ver.: 1.1
    // Date: January 2004
    // Auth: Andreas Dannenberg
    //       MSP430 Applications
    //       Texas Instruments Inc.
    // Rem.: -
    //------------------------------------------------------------------------------
    
    #include "msp430x14x.h"
    #include "support.h"
    #include "cs8900.h"
    
    //------------------------------------------------------------------------------
    const unsigned int MyMAC[] =                     // "M1-M2-M3-M4-M5-M6"
    {
    
      MYMAC_1 + (unsigned int)(MYMAC_2 << 8),
      MYMAC_3 + (unsigned int)(MYMAC_4 << 8),
      MYMAC_5 + (unsigned int)(MYMAC_6 << 8)
    };
    
    static const TInitSeq InitSeq[] =
    {
      PP_IA, MYMAC_1 + (MYMAC_2 << 8),               // set our MAC as Individual Address
      PP_IA + 2, MYMAC_3 + (MYMAC_4 << 8),
      PP_IA + 4, MYMAC_5 + (MYMAC_6 << 8),
      PP_LineCTL, SERIAL_RX_ON | SERIAL_TX_ON,       // configure the Physical Interface
      PP_RxCTL, RX_OK_ACCEPT | RX_IA_ACCEPT | RX_BROADCAST_ACCEPT
    };
    //------------------------------------------------------------------------------
    // configure port-pins for use with LAN-controller,
    // issue reset and send the configuration-sequence (InitSeq[])
    //------------------------------------------------------------------------------
    void Init8900(void)
    {
      unsigned int i;
    
      P3OUT = IOR | IOW;                             // reset outputs, control lines high
      P3DIR = 0xff;                                  // switch control port to output
    
      P5OUT = 0;                                     // reset outputs
      P5DIR = 0xff;                                  // switch data port to output
    
      DelayCycles(40000);                            // delay 10ms @ 8MHz MCLK to allow
      DelayCycles(40000);                            // time for CS8900 POR
    
      Write8900(ADD_PORT, PP_SelfCTL);               // set register
      Write8900(DATA_PORT, POWER_ON_RESET);          // reset the Ethernet-Controller
    
      do
        Write8900(ADD_PORT, PP_SelfST);              // set register
      while (!(Read8900(DATA_PORT) & INIT_DONE));    // wait until chip-reset is done
      
      for (i = 0; i < sizeof InitSeq / sizeof (TInitSeq); i++) // configure the CS8900
      {
        Write8900(ADD_PORT, InitSeq[i].Addr);
        Write8900(DATA_PORT, InitSeq[i].Data);
      }
    }
    //------------------------------------------------------------------------------
    // writes a word in little-endian byte order to
    // a specified port-address
    //------------------------------------------------------------------------------
    void Write8900(unsigned char Address, unsigned int Data)
    {
      P5DIR = 0xff;                                  // data port to output
      P3OUT = IOR | IOW | Address;                   // put address on bus
      P5OUT = Data;                                  // write low order byte to data bus
      P3OUT &= ~IOW;                                 // toggle IOW-signal
      P3OUT = IOR | IOW | (Address + 1);             // and put next address on bus
      P5OUT = Data >> 8;                             // write high order byte to data bus
      P3OUT &= ~IOW;                                 // toggle IOW-signal
      P3OUT |= IOW;
    }
    //------------------------------------------------------------------------------
    // writes a word in little-endian byte order to TX_FRAME_PORT
    //------------------------------------------------------------------------------
    void WriteFrame8900(unsigned int Data)
    {
      P5DIR = 0xff;                                  // data port to output
      P3OUT = IOR | IOW | TX_FRAME_PORT;             // put address on bus
      P5OUT = Data;                                  // write low order byte to data bus
      P3OUT &= ~IOW;                                 // toggle IOW-signal
      P3OUT = IOR | IOW | (TX_FRAME_PORT + 1);       // and put next address on bus
      P5OUT = Data >> 8;                             // write high order byte to data bus
      P3OUT &= ~IOW;                                 // toggle IOW-signal
      P3OUT |= IOW;
    }
    //------------------------------------------------------------------------------
    // copies bytes from MCU-memory to frame port
    // NOTES:     * MCU-memory MUST start at word-boundary
    //------------------------------------------------------------------------------
    void CopyToFrame8900(void *Source, unsigned int Size)
    {
      unsigned int *pSource = Source;
      
      P5DIR = 0xff;                                  // data port to output
    
      while (Size > 1)
      {
        P3OUT = IOR | IOW | TX_FRAME_PORT;           // put address on bus
        P5OUT = *pSource;                            // write low order byte to data bus
        P3OUT &= ~IOW;                               // toggle IOW-signal
        P3OUT = IOR | IOW | (TX_FRAME_PORT + 1);     // and put next address on bus
        P5OUT = (*pSource++) >> 8;                   // write high order byte to data bus
        P3OUT &= ~IOW;                               // toggle IOW-signal
        P3OUT |= IOW;
        Size -= 2;
      }
      
      if (Size)                                      // if odd num. of bytes...
      {
        P3OUT = IOR | IOW | TX_FRAME_PORT;           // put address on bus
        P5OUT = *pSource;                            // write byte to data bus
        P3OUT &= ~IOW;                               // toggle IOW-signal
        P3OUT |= IOW;
      }
    }
    //------------------------------------------------------------------------------
    // reads a word in little-endian byte order from
    // a specified port-address
    //------------------------------------------------------------------------------
    unsigned int Read8900(unsigned char Address)
    {
      unsigned int ReturnValue;
    
      P5DIR = 0x00;                                  // data port to input
      P3OUT = IOR | IOW | Address;                   // put address on bus
      P3OUT &= ~IOR;                                 // IOR-signal low
      ReturnValue = P5IN;                            // get low order byte from data bus
      P3OUT = IOR | IOW | (Address + 1);             // IOR high and put next address on bus
      P3OUT &= ~IOR;                                 // IOR-signal low
      ReturnValue |= P5IN << 8;                      // get high order byte from data bus
      P3OUT |= IOR;
      P5DIR = 0xff;                                  // data port to output
      
      return ReturnValue;
    }
    //------------------------------------------------------------------------------
    // reads a word in little-endian byte order from RX_FRAME_PORT
    //------------------------------------------------------------------------------
    unsigned int ReadFrame8900(void)
    {
      unsigned int ReturnValue;
    
      P5DIR = 0x00;                                  // data port to input
      P3OUT = IOR | IOW | RX_FRAME_PORT;             // access to RX_FRAME_PORT
      P3OUT &= ~IOR;                                 // IOR-signal low
      ReturnValue = P5IN;                            // get 1st byte from data bus (low-byte)
      P3OUT = IOR | IOW | (RX_FRAME_PORT + 1);       // IOR high and put next address on bus
      P3OUT &= ~IOR;                                 // IOR-signal low
      ReturnValue |= P5IN << 8;                      // get 2nd byte from data bus (high-byte)
      P3OUT |= IOR;
      P5DIR = 0xff;                                  // data port to output
      
      return ReturnValue;
    }
    //------------------------------------------------------------------------------
    // reads a word in big-endian byte order from RX_FRAME_PORT
    // (useful to avoid permanent byte-swapping while reading
    // TCP/IP-data)
    //------------------------------------------------------------------------------
    unsigned int ReadFrameBE8900(void)
    {
      unsigned int ReturnValue;
    
      P5DIR = 0x00;                                  // data port to input
      P3OUT = IOR | IOW | RX_FRAME_PORT;             // access to RX_FRAME_PORT
      P3OUT &= ~IOR;                                 // IOR-signal low
      ReturnValue = P5IN << 8;                       // get 1st byte from data bus (high-byte)
      P3OUT = IOR | IOW | (RX_FRAME_PORT + 1);       // IOR high and put next address on bus
      P3OUT &= ~IOR;                                 // IOR-signal low
      ReturnValue |= P5IN;                           // get 2nd byte from data bus (low-byte)
      P3OUT |= IOR;
      P5DIR = 0xff;                                  // data port to output
      
      return ReturnValue;
    }
    //------------------------------------------------------------------------------
    // reads a word in little-endian byte order from
    // a specified port-address
    // NOTE: this func. xfers the high-byte 1st, must be used to
    //       access some special registers (e.g. RxStatus)
    //------------------------------------------------------------------------------
    unsigned int ReadHB1ST8900(unsigned char Address)
    {
      unsigned int ReturnValue;
    
      P5DIR = 0x00;                                  // data port to input
      P3OUT = IOR | IOW | (Address + 1);             // put address on bus
      P3OUT &= ~IOR;                                 // IOR-signal low
      ReturnValue = P5IN << 8;                       // get high order byte from data bus
      P3OUT = IOR | IOW | Address;                   // IOR high and put next address on bus
      P3OUT &= ~IOR;                                 // IOR-signal low
      ReturnValue |= P5IN;                           // get low order byte from data bus
      P3OUT |= IOR;
      P5DIR = 0xff;                                  // data port to output
      
      return ReturnValue;
    }
    //------------------------------------------------------------------------------
    // copies bytes from frame port to MCU-memory
    // NOTES:     * MCU-memory MUST start at word-boundary
    //------------------------------------------------------------------------------
    void CopyFromFrame8900(void *Dest, unsigned int Size)
    {
      unsigned int *pDest = Dest;
    
      P5DIR = 0x00;                                  // data port to input
    
      while (Size > 1)
      {
        P3OUT = IOR | IOW | RX_FRAME_PORT;           // access to RX_FRAME_PORT
        P3OUT &= ~IOR;                               // IOR-signal low
        *pDest = P5IN;                               // get 1st byte from data bus (low-byte)
        P3OUT = IOR | IOW | (RX_FRAME_PORT + 1);     // IOR high and put next address on bus
        P3OUT &= ~IOR;                               // IOR-signal low
        *pDest++ |= P5IN << 8;                       // get 2nd byte from data bus (high-byte)
        P3OUT |= IOR;
        Size -= 2;
      }
      
      if (Size)                                      // check for leftover byte...
      {
        P3OUT = IOR | IOW | RX_FRAME_PORT;           // access to RX_FRAME_PORT
        P3OUT &= ~IOR;                               // IOR-signal low
        *(unsigned char *)pDest = P5IN;              // get byte from data bus
        P3OUT |= IOR;                                // IOR high
      }
    
      P5DIR = 0xff;                                  // data port to output
    }
    //------------------------------------------------------------------------------
    // does a dummy read on the CS8900A frame-I/O-port
    //------------------------------------------------------------------------------
    void DummyReadFrame8900(unsigned int Size)
    {
      P5DIR = 0x00;                                  // data port to input
    
      while (Size--)
      {
        P3OUT = IOR | IOW | RX_FRAME_PORT;           // access to RX_FRAME_PORT
        P3OUT &= ~IOR;                               // IOR-signal low
      }
      
      P3OUT |= IOR;                                  // IOR high
      P5DIR = 0xff;                                  // data port to output
    }
    //------------------------------------------------------------------------------
    // requests space in CS8900 on-chip memory for
    // storing an outgoing frame
    //------------------------------------------------------------------------------
    void RequestSend(unsigned int FrameSize)
    {
      Write8900(TX_CMD_PORT, TX_START_ALL_BYTES);
      Write8900(TX_LEN_PORT, FrameSize);
    }
    //------------------------------------------------------------------------------
    // check if CS8900 is ready to accept the
    // frame we want to send
    //------------------------------------------------------------------------------
    unsigned int Rdy4Tx(void)
    {
      Write8900(ADD_PORT, PP_BusST);
      return Read8900(DATA_PORT) & READY_FOR_TX_NOW;
    }
    

    8168.cs8900.h

    //------------------------------------------------------------------------------
    // Name: easyweb.c
    // Func: implements a dynamic HTTP-server by using
    //       the easyWEB-API
    // Ver.: 1.1
    // Date: January 2004
    // Auth: Andreas Dannenberg
    //       MSP430 Applications
    //       Texas Instruments Inc.
    // Rem.: - For detailed software/hardware information refer to MSP430
    //         application note SLAA137 (www.ti.com/msp430)
    //       - Build with IAR EW V2.21B
    //       - The compiler option "Formatted write" should be set to "Medium"
    //         (to ensure proper operation of the sprintf() function)
    //------------------------------------------------------------------------------
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include "msp430f149.h"
    //#include "msp430x14x.h"
    #include "support.h"
    #include "easyweb.h"
    #include "tcpip.h"                               // easyWEB TCP/IP stack
    
    #include "webside.c"                             // webside for our HTTP server (HTML)
    
    static const unsigned char GetResponse[] =       // 1st thing server sends to a client
    {
      "HTTP/1.0 200 OK\r\n"                          // protocol ver 1.0, code 200, reason OK
      "Content-Type: text/html\r\n"                  // type of data we want to send
      "\r\n"                                         // indicate end of HTTP-header
    };
    
    static unsigned char *PWebSide;                  // pointer to webside
    static unsigned int HTTPBytesToSend;             // bytes left to send
    static unsigned char HTTPStatus;                 // status byte
    
    //------------------------------------------------------------------------------
    // ADC12 Module Temperature Table
    //
    // These values assume nominal values for the temp sensor and
    // temperature coefficient. They also assume the 2.5V internal
    // reference is used for the conversion. The transfer function out
    // of the MSP430x1xx Family User's Guide has been used.
    //------------------------------------------------------------------------------
    static const unsigned int Temp_Tab[] =
    {
      0x064F,                                        // 0C
      0x0655,
      0x065B,
      0x0660,
      0x0666,
      0x066C,                                        // 5C
      0x0672,
      0x0678,
      0x067D,
      0x0683,
      0x0689,                                        // 10C
      0x068F,
      0x0695,
      0x069B,
      0x06A0,
      0x06A6,                                        // 15C
      0x06AC,
      0x06B2,
      0x06B8,
      0x06BD,
      0x06C3,                                        // 20C
      0x06C9,
      0x06CF,
      0x06D5,
      0x06DB,
      0x06E0,                                        // 25C
      0x06E6,
      0x06EC,
      0x06F2,
      0x06F8,
      0x06FD,                                        // 30C
      0x0703,
      0x0709,
      0x070F,
      0x0715,
      0x071B,                                        // 35C
      0x0720,
      0x0726,
      0x072C,
      0x0732,
      0x0738,                                        // 40C
      0x073D,
      0x0743,
      0x0749,
      0x074F,
      0x0755,                                        // 45C
      0x0FFF                                         // Too high
    };
    //------------------------------------------------------------------------------
    // Local function prototypes
    //------------------------------------------------------------------------------
    static void InitOsc(void);
    static void InitPorts(void);
    static void InitADC12(void);
    static void HTTPServer(void);
    static void InsertDynamicValues(void);
    static unsigned int GetAD7Val(void);
    static unsigned int GetTempVal(void);
    static int z=0;
    static int f1=0;
    static int c=0;
    static int data=0;
    #define sw1 BIT1 
    //------------------------------------------------------------------------------
    void main(void)
    {
      InitOsc();
      InitPorts();
     InitADC12();
    
      TCPLowLevelInit();  // tcpip.c
    
      __enable_interrupt();                          // enable interrupts
    
    //unsigned int data=5;
      *(unsigned char *)RemoteIP =10;               // uncomment those lines to get the
      *((unsigned char *)RemoteIP + 1) =107;          // quote of the day from a real
      *((unsigned char *)RemoteIP + 2) =16;         // internet server! (gateway must be
      *((unsigned char *)RemoteIP + 3) =120;      // set to your LAN-router)
    
     TCPLocalPort =2025;
    TCPRemotePort = TCP_PORT_QOTD;
    
      TCPActiveOpen();
    
      while (SocketStatus & SOCK_ACTIVE)             // read the quote from memory
      {                                              // by using the hardware-debugger
        DoNetworkStuff();
      }
    
    
      HTTPStatus = 0;                                // clear HTTP-server's flag register
    
      TCPLocalPort = TCP_PORT_HTTP;                  // set port we want to listen to
      
      while (1)                                      // repeat forever
      {
        if (!(SocketStatus & SOCK_ACTIVE)) TCPPassiveOpen();   // listen for incoming TCP-connection
        DoNetworkStuff();                                      // handle network and easyWEB-stack
                                                               // events
        HTTPServer();   // calls for adc sampling and data acquasiton
      }
    }
    //------------------------------------------------------------------------------
    // This function implements a very simple dynamic HTTP-server.
    // It waits until connected, then sends a HTTP-header and the
    // HTML-code stored in memory. Before sending, it replaces
    // some special strings with dynamic values.
    // NOTE: For strings crossing page boundaries, replacing will
    // not work. In this case, simply add some extra lines
    // (e.g. CR and LFs) to the HTML-code.
    //------------------------------------------------------------------------------
    static void HTTPServer(void)
    {
      if (SocketStatus & SOCK_CONNECTED)             // check if somebody has connected to our TCP
      {
        if (SocketStatus & SOCK_DATA_AVAILABLE)      // check if remote TCP sent data
          TCPReleaseRxBuffer();                      // and throw it away
    
        if (SocketStatus & SOCK_TX_BUF_RELEASED)     // check if buffer is free for TX
        {
          if (!(HTTPStatus & HTTP_SEND_PAGE))        // init byte-counter and pointer to webside
          {                                          // if called the 1st time
            HTTPBytesToSend = sizeof(WebSide) - 1;   // get HTML length, ignore trailing zero
            PWebSide = (unsigned char *)WebSide;     // pointer to HTML-code
          }
    
          if (HTTPBytesToSend > MAX_TCP_TX_DATA_SIZE)     // transmit a segment of MAX_SIZE
          {
            if (!(HTTPStatus & HTTP_SEND_PAGE))           // 1st time, include HTTP-header
            {
              memcpy(TCP_TX_BUF, GetResponse, sizeof(GetResponse) - 1);
              memcpy(TCP_TX_BUF + sizeof(GetResponse) - 1, PWebSide,
                MAX_TCP_TX_DATA_SIZE - sizeof(GetResponse) + 1);
              HTTPBytesToSend -= MAX_TCP_TX_DATA_SIZE - sizeof(GetResponse) + 1;
              PWebSide += MAX_TCP_TX_DATA_SIZE - sizeof(GetResponse) + 1;
            }
            else
            {
              memcpy(TCP_TX_BUF, PWebSide, MAX_TCP_TX_DATA_SIZE);
              HTTPBytesToSend -= MAX_TCP_TX_DATA_SIZE;
              PWebSide += MAX_TCP_TX_DATA_SIZE;
            }
              
            TCPTxDataCount = MAX_TCP_TX_DATA_SIZE;   // bytes to xfer
            InsertDynamicValues();                   // exchange some strings...
            TCPTransmitTxBuffer();                   // xfer buffer
          }
          else if (HTTPBytesToSend)                  // transmit leftover bytes
          {
            memcpy(TCP_TX_BUF, PWebSide, HTTPBytesToSend);
            TCPTxDataCount = HTTPBytesToSend;        // bytes to xfer
            InsertDynamicValues();                   // exchange some strings...
            TCPTransmitTxBuffer();                   // send last segment
            TCPClose();                              // and close connection
            HTTPBytesToSend = 0;                     // all data sent
          }
    
          HTTPStatus |= HTTP_SEND_PAGE;              // ok, 1st loop executed
        }
      }
      else
        HTTPStatus &= ~HTTP_SEND_PAGE;               // reset help-flag if not connected
    }
    //------------------------------------------------------------------------------
    // samples and returns the AD-converter value of channel 7
    // (associated with Port P6.7)
    //------------------------------------------------------------------------------
    static unsigned int GetAD7Val(void)
    {
    
      #define sw1 BIT1 
      /*
      ADC12MCTL0 = SREF_1 + INCH_7;                  // Select channel 7, Vref+
      
      ADC12CTL0 |= ENC;                              // enable conversion
      ADC12CTL0 |= ADC12SC;                          // sample & convert
      
      while (ADC12CTL0 & ADC12SC);                   // wait until conversion is complete
      
      ADC12CTL0 &= ~ENC;                             // disable conversion
    
      return ADC12MEM0 >> 5;                         // Scale value  
      */
    data=0; 
       if ((P4IN & sw1)==2)
       {
         
         f1=1;   //p4.1 bit is high
       }
    for(c=0; c<10000; c++)       
          {
           P4OUT = 0x01;//  LED P2.2 ON for timer of  exact 20 sec. timer led is kept ON
           P4DIR = 0x01;
               for(z=0; z<500; z++) //timer starts    z value for 20sec. 
                   {
                 P4DIR = 0x01;
                 if(f1==1)    //line is still high
                       {
                                if((P4IN & sw1)==0) //line changes to logic level
                                       {
                                         f1=0;  //flag set to zero i.e. logic level of i/n is zero-- current state
                                         data = data+1; // counter incremented by 1
                                       }
                       }   
                 else                               //i.e. flag status is 0; previous state is logic zero.
                       {
                       
                              if((P4IN & sw1)==2)
                                       {
                                           f1=1;   //current state changed to logic 1
                                       }
                
                       }
                
                   }
          }
      P4OUT = 0x00;//  LED P2.2 ON for timer of  exact 20 sec. timer led is kept ON
           P4DIR = 0x01;
           return data;
     
     
    }
     
      
    
    //------------------------------------------------------------------------------
    // samples and returns AD-converter value of channel 10
    // (MSP430 internal temperature reference diode)
    //------------------------------------------------------------------------------
    static unsigned int GetTempVal(void)
    {
      unsigned int i;
      unsigned int ADCResult;
    
      ADC12MCTL0 = SREF_1 + INCH_10;                 // Select channel A10, Vref+
    
      ADC12CTL0 |= ENC;                              // enable conversion
      ADC12CTL0 |= ADC12SC;                          // sample & convert
      
      while (ADC12CTL0 & ADC12SC);                   // wait until conversion is complete
      
      ADC12CTL0 &= ~ENC;                             // disable conversion
    
      ADCResult = ADC12MEM0;                         // Read out ADC12 value
    
      for (i = 0; i < sizeof Temp_Tab; i++)          // Get temperature value out
        if (ADCResult < Temp_Tab[i])                 // of table
          break;
    
      return i << 1;                                 // Scale value
    }
    //------------------------------------------------------------------------------
    // searches the TX-buffer for special strings and replaces them
    // with dynamic values (AD-converter results)
    //------------------------------------------------------------------------------
    static void InsertDynamicValues(void)
    {//ONLY CHANGE KEY+---  FOR INCREMENT IN DIGITS. NO NEED TO CHANGE ANY OF THE COUNTER.
      char *Key;
      char NewKey[5];
      int i;
      
      if (TCPTxDataCount < 4) return;                // there can't be any special string
      
      Key = (char *)TCP_TX_BUF;
      
      for (i = 0; i < TCPTxDataCount - 3 ; i++)
      {
        if (*Key == 'A')
         if (*(Key + 1) == 'D')
         if (*(Key + 3) == '5')                  // "AD7%"?
           if (*(Key + 2) == '6')                  // "AD7%"?
         // if (*(Key + 2) == '6')                  // "AD7%"?
          //   if (*(Key + 3) == '7')                  // "AD7%"?
             
           if (*(Key + 5) == '%')
             if (*(Key + 4) == '7')                  // "AD7%"?
             {
               sprintf(NewKey, "%3u", GetAD7Val());  // insert AD converter value
               memcpy(Key, NewKey, 5);               // channel 7 (P6.7)    
             }
             else if (*(Key + 2) == 'A')
             {
             //  sprintf(NewKey, "%3u", GetTempVal()); // insert AD converter value
            //   memcpy(Key, NewKey, 3);               // channel 10 (temp.-diode)
             }
        Key++;
      }
    }
    //------------------------------------------------------------------------------
    // enables the 8MHz crystal on XT1 and use
    // it as MCLK
    //------------------------------------------------------------------------------
    static void InitOsc(void)
    {
      WDTCTL = WDTPW + WDTHOLD;                      // stop watchdog timer
    
      BCSCTL1 |= XTS;                                // XT1 as high-frequency
      __bic_SR_register(OSCOFF);                     // turn on XT1 oscillator
    
      do
      {
        IFG1 &= ~OFIFG;                              // Clear OFIFG
        DelayCycles(100);                            // Wait ~130us
      } while (IFG1 & OFIFG);                        // Test oscillator fault flag
      
      BCSCTL2 = SELM_3;                              // set XT1 as MCLK
     P1DIR =0xFF;
     P1OUT= 0XFF; 
     DelayCycles(160000000);                               // i guess the delay is of around 3 sec. 
     P1OUT= 0X00;
     DelayCycles(160000000);                               // i guess the delay is of around 3 sec. 
     
      
    }  
    //------------------------------------------------------------------------------
    static void InitPorts(void)
    {
      P1OUT = 0;                                     // switch all unused ports to output   
      P1DIR = 0xff;                                  // (Rem.: ports 3 & 5 are set in "cs8900.c")
    
     // P2OUT = 0;
      //P2DIR = 0xff;
    
      P4OUT =0x00;
      P4DIR = 0xfd;
    
      P6SEL = 0x80;                                  // use P6.7 for the ADC module
      P6OUT = 0;
      P6DIR = 0x7f;                                  // all output except P6.7
    }
    //------------------------------------------------------------------------------
    static void InitADC12(void)
    {
      ADC12CTL0 = ADC12ON + REFON + REF2_5V + SHT0_6;// Turn on ADC12, 2.5Vref, set SHT0
      ADC12CTL1 = SHS_0 + SHP + CONSEQ_0;            // Use sampling timer, ADC12SC
                                                     // triggers conversion,
                                                     // single channel single conversion,
    
    
      P2DIR = 0xff;
      P2OUT = 0xff;
      DelayCycles(160000000);
      P2DIR = 0x00;
      P2OUT = 0x00;
    }
    
    
    

    //------------------------------------------------------------------------------
    // Name: tcpip.c
    // Func: implements the TCP/IP-stack and provides an API
    // Ver.: 1.1
    // Date: January 2004
    // Auth: Andreas Dannenberg
    //       MSP430 Applications
    //       Texas Instruments Inc.
    // Rem.: -
    //------------------------------------------------------------------------------
    
    #include "msp430x14x.h"
    #include "support.h"
    #include "cs8900.h"
    #include "tcpip.h"
    
    // constants
    const unsigned int MyIP[] =                      // "MYIP1.MYIP2.MYIP3.MYIP4"
    {
      MYIP_1 + (unsigned int)(MYIP_2 << 8),
      MYIP_3 + (unsigned int)(MYIP_4 << 8)
    };
    
    const unsigned int SubnetMask[] =                // "SUBMASK1.SUBMASK2.SUBMASK3.SUBMASK4"
    {
      SUBMASK_1 + (unsigned int)(SUBMASK_2 << 8),
      SUBMASK_3 + (unsigned int)(SUBMASK_4 << 8)
    };
    
    const unsigned int GatewayIP[] =                 // "GWIP1.GWIP2.GWIP3.GWIP4"
    {
      GWIP_1 + (unsigned int)(GWIP_2 << 8),
      GWIP_3 + (unsigned int)(GWIP_4 << 8)
    };
    
    // variables
    static TTCPStateMachine TCPStateMachine;         // perhaps the most important var at all ;-)
    static TLastFrameSent LastFrameSent;             // retransmission type
    
    static unsigned int ISNGenHigh;                  // upper word of our Initial Sequence Number
    static unsigned long TCPSeqNr;                   // next sequence number to send
    static unsigned long TCPUNASeqNr;                // last unaknowledged sequence number
                                                     // incremented AFTER sending data
    static unsigned long TCPAckNr;                   // next seq to receive and ack to send
                                                     // incremented AFTER receiving data
    static unsigned char TCPTimer;                   // inc'd each 262ms
    static unsigned char RetryCounter;               // nr. of retransmissions
    
    static unsigned int TxFrame1Size;                // bytes to send in TxFrame1
    static unsigned char TxFrame2Size;               // bytes to send in TxFrame2
    static unsigned char TransmitControl;
    static unsigned char TCPFlags;
    unsigned int TCPRxDataCount;                     // nr. of bytes rec'd
    unsigned int TCPTxDataCount;                     // nr. of bytes to send
    unsigned int TCPLocalPort;                       // TCP ports
    unsigned int TCPRemotePort;
    unsigned int RemoteMAC[3];                       // MAC and IP of current TCP-session
    unsigned int RemoteIP[2];
    unsigned char SocketStatus;
    
    // properties of the just received frame
    static unsigned int RecdFrameLength;             // CS8900 reported frame length
    static unsigned int RecdFrameMAC[3];             // 48 bit MAC
    static unsigned int RecdFrameIP[2];              // 32 bit IP
    static unsigned int RecdIPFrameLength;           // 16 bit IP packet length
    
    // the next 3 buffers must be word-aligned!
    unsigned int TxFrame1Mem[(ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE +
                              MAX_TCP_TX_DATA_SIZE + 1) >> 1];
    static unsigned int TxFrame2Mem[(ETH_HEADER_SIZE + MAX_ETH_TX_DATA_SIZE + 1) >> 1];
    unsigned int RxTCPBufferMem[(MAX_TCP_RX_DATA_SIZE + 1) >> 1];  // space for incoming TCP-data
    //------------------------------------------------------------------------------
    // Handlers for incoming frames
    static void ProcessEthBroadcastFrame(void);
    static void ProcessEthIAFrame(void);
    static void ProcessICMPFrame(void);
    static void ProcessTCPFrame(void);
    
    // fill TX-buffers
    static void PrepareARP_REQUEST(void);
    static void PrepareARP_ANSWER(void);
    static void PrepareICMP_ECHO_REPLY(void);
    
    static void PrepareTCP_FRAME(unsigned long seqnr, unsigned long acknr,
      unsigned int TCPCode);
    static void PrepareTCP_DATA_FRAME(void);
    
    // general help functions
    static void TCPStartRetryTimer(void);
    static void TCPStartFinTimer(void);
    static void TCPRestartTimer(void);
    static void TCPStopTimer(void);
    static void TCPHandleRetransmission(void);
    static void TCPHandleTimeout(void);
    static unsigned int CalcChecksum(void *Start, unsigned int Count,
      unsigned char IsTCP);
    //------------------------------------------------------------------------------
    // easyWEB-API function
    // initalizes the LAN-controller, reset flags, starts timer-ISR
    //------------------------------------------------------------------------------
    void TCPLowLevelInit(void)
    {
      BCSCTL1 &= ~DIVA0;                             // ACLK = XT1 / 4 = 2 MHz
      BCSCTL1 |= DIVA1;
      TACTL = ID_3 + TASSEL_1 + MC_2 + TAIE;         // stop timer, use ACLK / 8 = 250 kHz, gen. int.
                                                     // start timer in continuous up-mode
      Init8900();
      TransmitControl = 0;
      TCPFlags = 0;
      TCPStateMachine = CLOSED;
      SocketStatus = 0;
    }
    //------------------------------------------------------------------------------
    // easyWEB-API function
    // does a passive open (listen on 'MyIP:TCPLocalPort' for an incoming
    // connection)
    //------------------------------------------------------------------------------
    void TCPPassiveOpen(void)
    {
      if (TCPStateMachine == CLOSED)
      {
        TCPFlags &= ~TCP_ACTIVE_OPEN;                // let's do a passive open!
        TCPStateMachine = LISTENING;
        SocketStatus = SOCK_ACTIVE;                  // reset, socket now active
      }
    }
    //------------------------------------------------------------------------------
    // easyWEB-API function
    // does an active open (tries to establish a connection between
    // 'MyIP:TCPLocalPort' and 'RemoteIP:TCPRemotePort')
    //------------------------------------------------------------------------------
    void TCPActiveOpen(void)
    {
      if ((TCPStateMachine == CLOSED) || (TCPStateMachine == LISTENING))
      {
        TCPFlags |= TCP_ACTIVE_OPEN;                 // let's do an active open!
        TCPFlags &= ~IP_ADDR_RESOLVED;               // we haven't opponents MAC yet
      
        PrepareARP_REQUEST();                        // ask for MAC by sending a broadcast
        LastFrameSent = ARP_REQUEST;
        TCPStartRetryTimer();
        SocketStatus = SOCK_ACTIVE;                  // reset, socket now active    
      }
    }
    //------------------------------------------------------------------------------
    // easyWEB-API function
    // closes an open connection
    //------------------------------------------------------------------------------
    void TCPClose(void)
    {
      switch (TCPStateMachine)
      {
        case LISTENING :
        case SYN_SENT :
          TCPStateMachine = CLOSED;
          TCPFlags = 0;
          SocketStatus = 0;
          break;
        case SYN_RECD :
        case ESTABLISHED :
          TCPFlags |= TCP_CLOSE_REQUESTED;
          break;
      }
    }
    //------------------------------------------------------------------------------
    // easyWEB-API function
    // releases the receive-buffer and allows easyWEB to store new data
    // NOTE: rx-buffer MUST be released periodically, else the other TCP
    //       get no ACKs for the data it sent
    //------------------------------------------------------------------------------
    void TCPReleaseRxBuffer(void)
    {
      SocketStatus &= ~SOCK_DATA_AVAILABLE;
    }
    //------------------------------------------------------------------------------
    // easyWEB-API function
    // transmitts data stored in 'TCP_TX_BUF'
    // NOTE: * number of bytes to transmit must have been written to 'TCPTxDataCount'
    //       * data-count MUST NOT exceed 'MAX_TCP_TX_DATA_SIZE'
    //------------------------------------------------------------------------------
    void TCPTransmitTxBuffer(void)
    {
      if ((TCPStateMachine == ESTABLISHED) || (TCPStateMachine == CLOSE_WAIT))
        if (SocketStatus & SOCK_TX_BUF_RELEASED)
        {
          SocketStatus &= ~SOCK_TX_BUF_RELEASED;               // occupy tx-buffer
          TCPUNASeqNr += TCPTxDataCount;                       // advance UNA
          
          TxFrame1Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE + TCPTxDataCount;
          TransmitControl |= SEND_FRAME1;
          
          LastFrameSent = TCP_DATA_FRAME;
          TCPStartRetryTimer();
        }
    }
    //------------------------------------------------------------------------------
    // easyWEB's 'main()'-function
    // must be called from user program periodically (the often - the better)
    // handles network, TCP/IP-stack and user events
    //------------------------------------------------------------------------------
    void DoNetworkStuff(void)
    {
      unsigned int ActRxEvent;                       // copy of cs8900's RxEvent-Register
    
      Write8900(ADD_PORT, PP_RxEvent);               // point to RxEvent
      ActRxEvent = Read8900(DATA_PORT);              // read, implied skip of last frame
    
      if (ActRxEvent & RX_OK)
      {
        if (ActRxEvent & RX_IA) ProcessEthIAFrame();
        if (ActRxEvent & RX_BROADCAST) ProcessEthBroadcastFrame();
      }
    
      if (TCPFlags & TCP_TIMER_RUNNING)
        if (TCPFlags & TIMER_TYPE_RETRY)
        {
          if (TCPTimer > RETRY_TIMEOUT)
          {
            TCPRestartTimer();                       // set a new timeout
    
            if (RetryCounter)
            {
              TCPHandleRetransmission();             // resend last frame
              RetryCounter--;
            }
            else
            {
              TCPStopTimer();
              TCPHandleTimeout();
            }
          }
        }
        else if (TCPTimer > FIN_TIMEOUT)
        {
          TCPStateMachine = CLOSED;
          TCPFlags = 0;                              // reset all flags, stop retransmission...
          SocketStatus &= SOCK_DATA_AVAILABLE;       // clear all flags but data available
        }
    
      switch (TCPStateMachine)
      {
        case CLOSED :
        case LISTENING :
          if (TCPFlags & TCP_ACTIVE_OPEN)            // stack has to open a connection?
            if (TCPFlags & IP_ADDR_RESOLVED)         // IP resolved?
              if (!(TransmitControl & SEND_FRAME2))  // buffer free?
              {
                TCPSeqNr = ((unsigned long)ISNGenHigh << 16) | TAR; // set local ISN
                TCPUNASeqNr = TCPSeqNr;
                TCPAckNr = 0;                                       // we don't know what to ACK!
                TCPUNASeqNr++;                                      // count SYN as a byte
                PrepareTCP_FRAME(TCPSeqNr, TCPAckNr, TCP_CODE_SYN); // send SYN frame
                LastFrameSent = TCP_SYN_FRAME;
                TCPStartRetryTimer();                               // we NEED a retry-timeout
                TCPStateMachine = SYN_SENT;
              }
          break;
        case SYN_RECD :
        case ESTABLISHED :
          if (TCPFlags & TCP_CLOSE_REQUESTED)                  // user has user initated a close?
            if (!(TransmitControl & (SEND_FRAME2 | SEND_FRAME1)))   // buffers free?
              if (TCPSeqNr == TCPUNASeqNr)                          // all data ACKed?
              {
                TCPUNASeqNr++;
                PrepareTCP_FRAME(TCPSeqNr, TCPAckNr, TCP_CODE_FIN | TCP_CODE_ACK);
                LastFrameSent = TCP_FIN_FRAME;
                TCPStartRetryTimer();
                TCPStateMachine = FIN_WAIT_1;
              }
          break;
        case CLOSE_WAIT :
          if (!(TransmitControl & (SEND_FRAME2 | SEND_FRAME1)))     // buffers free?
            if (TCPSeqNr == TCPUNASeqNr)                            // all data ACKed?
            {
              TCPUNASeqNr++;                                        // count FIN as a byte
              PrepareTCP_FRAME(TCPSeqNr, TCPAckNr, TCP_CODE_FIN | TCP_CODE_ACK);  // we NEED a retry-timeout
              LastFrameSent = TCP_FIN_FRAME;                        // time to say goodbye...
              TCPStartRetryTimer();
              TCPStateMachine = LAST_ACK;
            }
          break;
      }
    
      if (TransmitControl & SEND_FRAME2)
      {
        RequestSend(TxFrame2Size);
    
        if (Rdy4Tx())                                // NOTE: when using a very fast MCU,
        {                                            // maybe the CS8900 isn't ready yet
          CopyToFrame8900((unsigned char *)TxFrame2Mem, TxFrame2Size);
        }
        else
        {
          TCPStateMachine = CLOSED;
          SocketStatus = SOCK_ERR_ETHERNET;          // indicate an error to user
          TCPFlags = 0;                              // clear all flags, stop timers etc.
        }
    
        TransmitControl &= ~SEND_FRAME2;             // clear tx-flag
      }
    
      if (TransmitControl & SEND_FRAME1)
      {
        PrepareTCP_DATA_FRAME();                     // build frame w/ actual SEQ, ACK....
        RequestSend(TxFrame1Size);
      
        if (Rdy4Tx())                                // CS8900 ready to accept our frame?
        {                                            // (see note above)
          CopyToFrame8900((unsigned char *)TxFrame1Mem, TxFrame1Size);
        }
        else
        {
          TCPStateMachine = CLOSED;
          SocketStatus = SOCK_ERR_ETHERNET;          // indicate an error to user
          TCPFlags = 0;                              // clear all flags, stop timers etc.
        }
    
        TransmitControl &= ~SEND_FRAME1;             // clear tx-flag
      }
    }
    //------------------------------------------------------------------------------
    // easyWEB internal function
    // handles an incoming broadcast frame
    //------------------------------------------------------------------------------
    static void ProcessEthBroadcastFrame(void)
    {
      unsigned int TargetIP[2];
    
      // next two words MUST be read with High-Byte 1st (CS8900 AN181 Page 2)
      ReadHB1ST8900(RX_FRAME_PORT);                  // ignore RxStatus Word
      RecdFrameLength = ReadHB1ST8900(RX_FRAME_PORT);// get real length of frame 
        
      DummyReadFrame8900(6);                         // ignore DA (FF-FF-FF-FF-FF-FF)
      CopyFromFrame8900(&RecdFrameMAC, 6);           // store SA (for our answer)
    
      if (ReadFrameBE8900() == FRAME_ARP)            // get frame type, check for ARP
        if (ReadFrameBE8900() == HARDW_ETH10)        // Ethernet frame
          if (ReadFrameBE8900() == FRAME_IP)         // check protocol
            if (ReadFrameBE8900() == IP_HLEN_PLEN)   // check HLEN, PLEN
              if (ReadFrameBE8900() == OP_ARP_REQUEST)
              {
                DummyReadFrame8900(6);               // ignore sender's hardware address
                CopyFromFrame8900(&RecdFrameIP, 4);  // read sender's protocol address
                DummyReadFrame8900(6);               // ignore target's hardware address
                CopyFromFrame8900(&TargetIP, 4);     // read target's protocol address
                if ((MyIP[0] == TargetIP[0]) && (MyIP[1] == TargetIP[1]))  // is it for us?
                  PrepareARP_ANSWER();               // yes->create ARP_ANSWER frame
              }
    }
    //------------------------------------------------------------------------------
    // easyWEB internal function
    // handles an incoming frame that passed CS8900's address filter
    // (individual addressed = IA)
    //------------------------------------------------------------------------------
    static void ProcessEthIAFrame(void)
    {
      unsigned int TargetIP[2];
      unsigned char ProtocolType;
    
      // next two words MUST be read with High-Byte 1st (CS8900 AN181 Page 2)
      ReadHB1ST8900(RX_FRAME_PORT);                  // ignore RxStatus Word
      RecdFrameLength = ReadHB1ST8900(RX_FRAME_PORT);// get real length of frame 
      
      DummyReadFrame8900(6);                         // ignore DA
      CopyFromFrame8900(&RecdFrameMAC, 6);           // store SA (for our answer)
    
      switch (ReadFrameBE8900())                     // get frame type
      {
        case FRAME_ARP :                             // check for ARP
          if ((TCPFlags & (TCP_ACTIVE_OPEN | IP_ADDR_RESOLVED)) == TCP_ACTIVE_OPEN)
            if (ReadFrameBE8900() == HARDW_ETH10)         // check for the right prot. etc.
              if (ReadFrameBE8900() == FRAME_IP)
                if (ReadFrameBE8900() == IP_HLEN_PLEN)
                  if (ReadFrameBE8900() == OP_ARP_ANSWER)
                  {
                    TCPStopTimer();                       // OK, now we've the MAC we wanted ;-)
                    CopyFromFrame8900(&RemoteMAC, 6);     // extract opponents MAC
                    TCPFlags |= IP_ADDR_RESOLVED;
                  }
          break;
        case FRAME_IP :                                        // check for IP-type
          if ((ReadFrameBE8900() & 0xff00 ) == IP_VER_IHL)     // IPv4, IHL=5 (20 Bytes Header)
          {                                                    // ignore Type Of Service
            RecdIPFrameLength = ReadFrameBE8900();             // get IP frame's length
            ReadFrameBE8900();                                 // ignore identification
    
            if (!(ReadFrameBE8900() & (IP_FLAG_MOREFRAG | IP_FRAGOFS_MASK)))  // only unfragm. frames
            {
              ProtocolType = ReadFrameBE8900();                // get protocol, ignore TTL
              ReadFrameBE8900();                               // ignore checksum
              RecdFrameIP[0] = ReadFrame8900();                // get source IP
              RecdFrameIP[1] = ReadFrame8900();
              TargetIP[0] = ReadFrame8900();                   // get destination IP
              TargetIP[1] = ReadFrame8900();
    
              if ((MyIP[0] == TargetIP[0]) && (MyIP[1] == TargetIP[1]))  // is it for us?
                switch (ProtocolType)
                {
                  case PROT_ICMP :
                    ProcessICMPFrame();
                    break;
                  case PROT_TCP :
                    ProcessTCPFrame();
                    break;
                  case PROT_UDP :                              // not implemented!
                    break;
                }
            }      
          break;
        }
      }
    }
    //------------------------------------------------------------------------------
    // easyWEB internal function
    // we've just rec'd an ICMP-frame (Internet Control Message Protocol)
    // check what to do and branch to the appropriate sub-function
    //------------------------------------------------------------------------------
    static void ProcessICMPFrame(void)
    {
      unsigned int ICMPTypeAndCode;
    
      ICMPTypeAndCode = ReadFrameBE8900();           // get Message Type and Code
      ReadFrameBE8900();                             // ignore ICMP checksum
    
      switch (ICMPTypeAndCode >> 8)                  // check type
      {
        case ICMP_ECHO :                             // is echo request?
          PrepareICMP_ECHO_REPLY();                  // echo as much as we can...
          break;
      }
    }
    //------------------------------------------------------------------------------
    // easyWEB internal function
    // we've just rec'd an TCP-frame (Transmission Control Protocol)
    // this function mainly implements the TCP state machine according to RFC793
    //------------------------------------------------------------------------------
    static void ProcessTCPFrame(void)
    {
      unsigned int TCPSegSourcePort;                 // segment's source port
      unsigned int TCPSegDestPort;                   // segment's destination port
      unsigned long TCPSegSeq;                       // segment's sequence number
      unsigned long TCPSegAck;                       // segment's acknowledge number
      unsigned int TCPCode;                          // TCP code and header length
      unsigned char TCPHeaderSize;                   // real TCP header length
      unsigned int NrOfDataBytes;                    // real number of data
        
      TCPSegSourcePort = ReadFrameBE8900();                    // get ports
      TCPSegDestPort = ReadFrameBE8900();
    
      if (TCPSegDestPort != TCPLocalPort) return;              // drop segment if port doesn't match
    
      TCPSegSeq = (unsigned long)ReadFrameBE8900() << 16;      // get segment sequence nr.
      TCPSegSeq |= ReadFrameBE8900();
    
      TCPSegAck = (unsigned long)ReadFrameBE8900() << 16;      // get segment acknowledge nr.
      TCPSegAck |= ReadFrameBE8900();
    
      TCPCode = ReadFrameBE8900();                             // get control bits, header length...
    
      TCPHeaderSize = (TCPCode & DATA_OFS_MASK) >> 10;         // header length in bytes
      NrOfDataBytes = RecdIPFrameLength - IP_HEADER_SIZE - TCPHeaderSize;     // seg. text length
    
      if (NrOfDataBytes > MAX_TCP_RX_DATA_SIZE) return;        // drop, packet too large for us :'(
    
      if (TCPHeaderSize > TCP_HEADER_SIZE)                     // ignore options if any
        DummyReadFrame8900(TCPHeaderSize - TCP_HEADER_SIZE);
    
      switch (TCPStateMachine)                                 // implement the TCP state machine
      {                                                        // RFC793
        case CLOSED :
          if (!(TCPCode & TCP_CODE_RST))
          {
            TCPRemotePort = TCPSegSourcePort;                  // get remote TCP port
            
            RemoteMAC[0] = RecdFrameMAC[0];                    // save opponents MAC and IP
            RemoteMAC[1] = RecdFrameMAC[1];                    // for later use
            RemoteMAC[2] = RecdFrameMAC[2];
            RemoteIP[0] = RecdFrameIP[0];
            RemoteIP[1] = RecdFrameIP[1];
            
            if (TCPCode & TCP_CODE_ACK)                        // make the reset sequence
            {                                                  // acceptable to the other
              PrepareTCP_FRAME(TCPSegAck, 0, TCP_CODE_RST);    // TCP
            }
            else
            {
              TCPAckNr = TCPSegSeq + NrOfDataBytes;
              if (TCPCode & (TCP_CODE_SYN | TCP_CODE_FIN)) TCPAckNr++;
              PrepareTCP_FRAME(0, TCPAckNr, TCP_CODE_RST | TCP_CODE_ACK);
            }
          }
          break;
        case LISTENING :
          if (!(TCPCode & TCP_CODE_RST))                       // ignore segment containing RST
          {
            TCPRemotePort = TCPSegSourcePort;                  // get remote TCP port
    
            RemoteMAC[0] = RecdFrameMAC[0];                    // save opponents MAC and IP
            RemoteMAC[1] = RecdFrameMAC[1];                    // for later use
            RemoteMAC[2] = RecdFrameMAC[2];
            RemoteIP[0] = RecdFrameIP[0];
            RemoteIP[1] = RecdFrameIP[1];
    
            if (TCPCode & TCP_CODE_ACK)                        // reset a bad
            {                                                  // acknowledgement
              PrepareTCP_FRAME(TCPSegAck, 0, TCP_CODE_RST);
            }
            else if (TCPCode & TCP_CODE_SYN)
            {
              // initialize global connection variables
              TCPAckNr = TCPSegSeq + 1;                           // get remote ISN, next byte we expect
              TCPSeqNr = ((unsigned long)ISNGenHigh << 16) | TAR; // set local ISN
              TCPUNASeqNr = TCPSeqNr + 1;                         // one byte out -> increase by one
              PrepareTCP_FRAME(TCPSeqNr, TCPAckNr, TCP_CODE_SYN | TCP_CODE_ACK); // acknowledge connection request
              LastFrameSent = TCP_SYN_ACK_FRAME;
              TCPStartRetryTimer();
              TCPStateMachine = SYN_RECD;
            }
          }
          break;
        case SYN_SENT :
          // drop segment if its IP doesn't belong to current session
          if ((RemoteIP[0] != RecdFrameIP[0]) || (RemoteIP[1] != RecdFrameIP[1]))
            break;      
    
          // drop segment if port doesn't match
          if (TCPSegSourcePort != TCPRemotePort)
            break;   
          
          if (TCPCode & TCP_CODE_ACK)                // ACK field significant?
            if (TCPSegAck != TCPUNASeqNr)            // is our ISN ACKed?
            {
              if (!(TCPCode & TCP_CODE_RST))
              {
                PrepareTCP_FRAME(TCPSegAck, 0, TCP_CODE_RST);
              }
              break;                                 // drop segment
            }
    
          if (TCPCode & TCP_CODE_RST)                // RST??
          {
            if (TCPCode & TCP_CODE_ACK)              // if ACK was acceptable, reset
            {                                        // connection
              TCPStateMachine = CLOSED;
              TCPFlags = 0;                          // reset all flags, stop retransmission...
              SocketStatus = SOCK_ERR_CONN_RESET;
            }
            break;                                   // drop segment
          }
            
          if (TCPCode & TCP_CODE_SYN)                // SYN??
          {
            TCPAckNr = TCPSegSeq;                    // get opponents ISN
            TCPAckNr++;                              // inc. by one...
    
            if (TCPCode & TCP_CODE_ACK)
            {
              TCPStopTimer();                        // stop retransmission, other TCP got our SYN
              TCPSeqNr = TCPUNASeqNr;                // advance our sequence number
    
              PrepareTCP_FRAME(TCPSeqNr, TCPAckNr, TCP_CODE_ACK);        // ACK this ISN
              TCPStateMachine = ESTABLISHED;
              SocketStatus |= SOCK_CONNECTED;
              SocketStatus |= SOCK_TX_BUF_RELEASED;  // user may send data now :-)
            }
            else
            {
              TCPStopTimer();
              PrepareTCP_FRAME(TCPSeqNr, TCPAckNr, TCP_CODE_SYN | TCP_CODE_ACK);   // our SYN isn't ACKed yet,
              LastFrameSent = TCP_SYN_ACK_FRAME;               // now continue with sending
              TCPStartRetryTimer();                            // SYN_ACK frames
              TCPStateMachine = SYN_RECD;
            }
          }
          break;
        default :
          // drop segment if IP doesn't belong to current session
          if ((RemoteIP[0] != RecdFrameIP[0]) || (RemoteIP[1] != RecdFrameIP[1]))
            break;      
    
          // drop segment if port doesn't match        
          if (TCPSegSourcePort != TCPRemotePort)
            break;     
    
          // drop segment if it doesn't fall into the receive window
          if ((TCPSegSeq < TCPAckNr) || (TCPSegSeq >= TCPAckNr + MAX_TCP_RX_DATA_SIZE))
            break;
                
          if (TCPCode & TCP_CODE_RST)                // RST??
          {
            TCPStateMachine = CLOSED;                // close the state machine
            TCPFlags = 0;                            // reset all flags, stop retransmission...
            SocketStatus = SOCK_ERR_CONN_RESET;      // indicate an error to user
            break;
          }
    
          if (TCPCode & TCP_CODE_SYN)                // SYN??
          {
            PrepareTCP_FRAME(TCPSegAck, 0, TCP_CODE_RST);  // is NOT allowed here! send a reset,
            TCPStateMachine = CLOSED;                // close connection...
            TCPFlags = 0;                            // reset all flags, stop retransmission...
            SocketStatus = SOCK_ERR_REMOTE;          // fatal error!
            break;                                   // ...and drop the frame
          }
    
          if (TCPSegSeq != TCPAckNr)                 // drop if it's not the segment we expect,
          {                                          // and send an ACK
            PrepareTCP_FRAME(TCPUNASeqNr, TCPAckNr, TCP_CODE_ACK);
            break;
          }
    
          if (!(TCPCode & TCP_CODE_ACK)) break;      // drop segment if the ACK bit is off
    
          if (TCPSegAck == TCPUNASeqNr)              // is our last data sent ACKed?
          {
            TCPStopTimer();                          // stop retransmission
            TCPSeqNr = TCPUNASeqNr;                  // advance our sequence number
    
            switch (TCPStateMachine)                 // change state if necessary
            {
              case SYN_RECD :                        // ACK of our SYN?
                TCPStateMachine = ESTABLISHED;       // user may send data now :-)
                SocketStatus |= SOCK_CONNECTED;
                break;
              case ESTABLISHED :
                SocketStatus |= SOCK_TX_BUF_RELEASED;  // give TX buffer back
                break;
              case FIN_WAIT_1 :                      // ACK of our FIN?
                TCPStateMachine = FIN_WAIT_2;
    
                /*
                  The following code lines are not according to RFC793, but prevent from
                  being stuck in the FIN_WAIT_2 state when no FIN packet within a certain
                  timeframe will be received (RFC793 says there are two ways to leave this
                  state: 1. FIN is received or 2. user closes/resets the connection)
                */
    
                TCPStartFinTimer();                  // start TIME_WAIT timeout
                break;
              case CLOSING :                         // ACK of our FIN?
                TCPStateMachine = TIME_WAIT;
                TCPStartFinTimer();                  // start TIME_WAIT timeout
                break;
              case LAST_ACK :                        // ACK of our FIN?
                TCPStateMachine = CLOSED;
                TCPFlags = 0;                        // reset all flags, stop retransmission...
                SocketStatus &= SOCK_DATA_AVAILABLE; // clear all flags but data available
                break;
              case TIME_WAIT :
                // ACK a retransmission of remote FIN
                PrepareTCP_FRAME(TCPSegAck, TCPAckNr, TCP_CODE_ACK);  
                TCPRestartTimer();                   // restart TIME_WAIT timeout
                break;
            }
          }
    
          if ((TCPStateMachine == ESTABLISHED) ||
              (TCPStateMachine == FIN_WAIT_1) ||
              (TCPStateMachine == FIN_WAIT_2))
            if (NrOfDataBytes)                                 // data available?
              if (!(SocketStatus & SOCK_DATA_AVAILABLE))       // rx data-buffer empty?
              {
                DummyReadFrame8900(6);                         // ignore window, checksum, urgent pointer
                CopyFromFrame8900(RxTCPBufferMem, NrOfDataBytes);  // fetch data and
                TCPRxDataCount = NrOfDataBytes;                // ...tell the user...
                SocketStatus |= SOCK_DATA_AVAILABLE;           // indicate the new data to user
                TCPAckNr += NrOfDataBytes;
                PrepareTCP_FRAME(TCPSegAck, TCPAckNr, TCP_CODE_ACK);  // ACK rec'd data
              }
              else
                break;                               // stop processing here, we cannot send an
                                                     // acknowledge packet as the received data
                                                     // could not be passed to the app layer
                  
          if (TCPCode & TCP_CODE_FIN)                // FIN??
          {
            switch (TCPStateMachine)
            {
              case SYN_RECD :
              case ESTABLISHED :
                TCPStateMachine = CLOSE_WAIT;
                break;
              case FIN_WAIT_1 :                      
                TCPStateMachine = CLOSING;           // enter FIN_WAIT_2 (look above) and therefore
                SocketStatus &= ~SOCK_CONNECTED;     // TIME_WAIT
                break;
              case FIN_WAIT_2 :
                TCPStateMachine = TIME_WAIT;
                SocketStatus &= ~SOCK_CONNECTED;            
                TCPStartFinTimer();                  // start TIME_WAIT timeout
                break;
              case TIME_WAIT :
                TCPRestartTimer();                   // restart TIME_WAIT timeout
                break;
            }
            TCPAckNr++;                              // ACK remote's FIN flag
            
            PrepareTCP_FRAME(TCPSegAck, TCPAckNr, TCP_CODE_ACK);
          }
      }
    }
    //------------------------------------------------------------------------------
    // easyWEB internal function
    // prepares the TxFrame2-buffer to send an ARP-request
    //------------------------------------------------------------------------------
    static void PrepareARP_REQUEST(void)
    {
      // Ethernet
      ACCESS_UINT(TxFrame2Mem, ETH_DA_OFS) = 0xffff;  // we don't know opposites MAC!
      ACCESS_UINT(TxFrame2Mem, ETH_DA_OFS + 2) = 0xffff;
      ACCESS_UINT(TxFrame2Mem, ETH_DA_OFS + 4) = 0xffff;
      ACCESS_UINT(TxFrame2Mem, ETH_SA_OFS) = MyMAC[0];
      ACCESS_UINT(TxFrame2Mem, ETH_SA_OFS + 2) = MyMAC[1];
      ACCESS_UINT(TxFrame2Mem, ETH_SA_OFS + 4) = MyMAC[2];
      ACCESS_UINT(TxFrame2Mem, ETH_TYPE_OFS) = SWAPB(FRAME_ARP);
    
      // ARP
      ACCESS_UINT(TxFrame2Mem, ARP_HARDW_OFS) = SWAPB(HARDW_ETH10);
      ACCESS_UINT(TxFrame2Mem, ARP_PROT_OFS) = SWAPB(FRAME_IP); 
      ACCESS_UINT(TxFrame2Mem, ARP_HLEN_PLEN_OFS) = SWAPB(IP_HLEN_PLEN);
      ACCESS_UINT(TxFrame2Mem, ARP_OPCODE_OFS) = SWAPB(OP_ARP_REQUEST);
      ACCESS_UINT(TxFrame2Mem, ARP_SENDER_HA_OFS) = MyMAC[0];
      ACCESS_UINT(TxFrame2Mem, ARP_SENDER_HA_OFS + 2) = MyMAC[1];
      ACCESS_UINT(TxFrame2Mem, ARP_SENDER_HA_OFS + 4) = MyMAC[2];
      ACCESS_UINT(TxFrame2Mem, ARP_SENDER_IP_OFS) = MyIP[0];
      ACCESS_UINT(TxFrame2Mem, ARP_SENDER_IP_OFS + 2) = MyIP[1];
      ACCESS_UINT(TxFrame2Mem, ARP_TARGET_HA_OFS) = 0;
      ACCESS_UINT(TxFrame2Mem, ARP_TARGET_HA_OFS + 2) = 0;
      ACCESS_UINT(TxFrame2Mem, ARP_TARGET_HA_OFS + 4) = 0;
      ACCESS_UINT(TxFrame2Mem, ARP_TARGET_IP_OFS) = 0;
      ACCESS_UINT(TxFrame2Mem, ARP_TARGET_IP_OFS + 2) = 0;
    
      if (((RemoteIP[0] ^ MyIP[0]) & SubnetMask[0]) ||
          ((RemoteIP[1] ^ MyIP[1]) & SubnetMask[1]))
      {
        ACCESS_UINT(TxFrame2Mem, ARP_TARGET_IP_OFS) = GatewayIP[0];
        ACCESS_UINT(TxFrame2Mem, ARP_TARGET_IP_OFS + 2) = GatewayIP[1];
      }
      else
      {
        ACCESS_UINT(TxFrame2Mem, ARP_TARGET_IP_OFS) = RemoteIP[0];
        ACCESS_UINT(TxFrame2Mem, ARP_TARGET_IP_OFS + 2) = RemoteIP[1];
      }
    
      TxFrame2Size = ETH_HEADER_SIZE + ARP_FRAME_SIZE;
      TransmitControl |= SEND_FRAME2;
    }
    //------------------------------------------------------------------------------
    // easyWEB internal function
    // prepares the TxFrame2-buffer to send an ARP-answer (reply)
    //------------------------------------------------------------------------------
    static void PrepareARP_ANSWER(void)
    {
      // Ethernet
      ACCESS_UINT(TxFrame2Mem, ETH_DA_OFS) = RecdFrameMAC[0];
      ACCESS_UINT(TxFrame2Mem, ETH_DA_OFS + 2) = RecdFrameMAC[1];
      ACCESS_UINT(TxFrame2Mem, ETH_DA_OFS + 4) = RecdFrameMAC[2];
      ACCESS_UINT(TxFrame2Mem, ETH_SA_OFS) = MyMAC[0];
      ACCESS_UINT(TxFrame2Mem, ETH_SA_OFS + 2) = MyMAC[1];
      ACCESS_UINT(TxFrame2Mem, ETH_SA_OFS + 4) = MyMAC[2];
      ACCESS_UINT(TxFrame2Mem, ETH_TYPE_OFS) = SWAPB(FRAME_ARP);
    
      // ARP
      ACCESS_UINT(TxFrame2Mem, ARP_HARDW_OFS) = SWAPB(HARDW_ETH10);
      ACCESS_UINT(TxFrame2Mem, ARP_PROT_OFS) = SWAPB(FRAME_IP); 
      ACCESS_UINT(TxFrame2Mem, ARP_HLEN_PLEN_OFS) = SWAPB(IP_HLEN_PLEN);
      ACCESS_UINT(TxFrame2Mem, ARP_OPCODE_OFS) = SWAPB(OP_ARP_ANSWER);
      ACCESS_UINT(TxFrame2Mem, ARP_SENDER_HA_OFS) = MyMAC[0];
      ACCESS_UINT(TxFrame2Mem, ARP_SENDER_HA_OFS + 2) = MyMAC[1];
      ACCESS_UINT(TxFrame2Mem, ARP_SENDER_HA_OFS + 4) = MyMAC[2];
      ACCESS_UINT(TxFrame2Mem, ARP_SENDER_IP_OFS) = MyIP[0];
      ACCESS_UINT(TxFrame2Mem, ARP_SENDER_IP_OFS + 2) = MyIP[1];
      ACCESS_UINT(TxFrame2Mem, ARP_TARGET_HA_OFS) = RecdFrameMAC[0];
      ACCESS_UINT(TxFrame2Mem, ARP_TARGET_HA_OFS + 2) = RecdFrameMAC[1];
      ACCESS_UINT(TxFrame2Mem, ARP_TARGET_HA_OFS + 4) = RecdFrameMAC[2];
      ACCESS_UINT(TxFrame2Mem, ARP_TARGET_IP_OFS) = RecdFrameIP[0];
      ACCESS_UINT(TxFrame2Mem, ARP_TARGET_IP_OFS + 2) = RecdFrameIP[1];
    
      TxFrame2Size = ETH_HEADER_SIZE + ARP_FRAME_SIZE;
      TransmitControl |= SEND_FRAME2;
    }
    //------------------------------------------------------------------------------
    // easyWEB internal function
    // prepares the TxFrame2-buffer to send an ICMP-echo-reply
    //------------------------------------------------------------------------------
    static void PrepareICMP_ECHO_REPLY(void)
    {
      unsigned int ICMPDataCount;
    
      if (RecdIPFrameLength > MAX_ETH_TX_DATA_SIZE)  // don't overload TX-buffer
        ICMPDataCount = MAX_ETH_TX_DATA_SIZE - IP_HEADER_SIZE - ICMP_HEADER_SIZE;
      else
        ICMPDataCount = RecdIPFrameLength - IP_HEADER_SIZE - ICMP_HEADER_SIZE;
    
      // Ethernet
      ACCESS_UINT(TxFrame2Mem, ETH_DA_OFS) = RecdFrameMAC[0];
      ACCESS_UINT(TxFrame2Mem, ETH_DA_OFS + 2) = RecdFrameMAC[1];
      ACCESS_UINT(TxFrame2Mem, ETH_DA_OFS + 4) = RecdFrameMAC[2];
      ACCESS_UINT(TxFrame2Mem, ETH_SA_OFS) = MyMAC[0];
      ACCESS_UINT(TxFrame2Mem, ETH_SA_OFS + 2) = MyMAC[1];
      ACCESS_UINT(TxFrame2Mem, ETH_SA_OFS + 4) = MyMAC[2];
      ACCESS_UINT(TxFrame2Mem, ETH_TYPE_OFS) = SWAPB(FRAME_IP);
      
      // IP   
      ACCESS_UINT(TxFrame2Mem, IP_VER_IHL_TOS_OFS) = SWAPB(IP_VER_IHL);
      ACCESS_UINT(TxFrame2Mem, IP_TOTAL_LENGTH_OFS) =
        __swap_bytes(IP_HEADER_SIZE + ICMP_HEADER_SIZE + ICMPDataCount);
      ACCESS_UINT(TxFrame2Mem, IP_IDENT_OFS) = 0;
      ACCESS_UINT(TxFrame2Mem, IP_FLAGS_FRAG_OFS) = 0;
      ACCESS_UINT(TxFrame2Mem, IP_TTL_PROT_OFS) = SWAPB((DEFAULT_TTL << 8) | PROT_ICMP);
      ACCESS_UINT(TxFrame2Mem, IP_HEAD_CHKSUM_OFS) = 0;
      ACCESS_UINT(TxFrame2Mem, IP_SOURCE_OFS) = MyIP[0];
      ACCESS_UINT(TxFrame2Mem, IP_SOURCE_OFS + 2) = MyIP[1];
      ACCESS_UINT(TxFrame2Mem, IP_DESTINATION_OFS) = RecdFrameIP[0];
      ACCESS_UINT(TxFrame2Mem, IP_DESTINATION_OFS + 2) = RecdFrameIP[1];
      ACCESS_UINT(TxFrame2Mem, IP_HEAD_CHKSUM_OFS) = 
        CalcChecksum((unsigned char *)TxFrame2Mem + IP_VER_IHL_TOS_OFS, IP_HEADER_SIZE, 0);
    
      // ICMP
      ACCESS_UINT(TxFrame2Mem, ICMP_TYPE_CODE_OFS) = SWAPB(ICMP_ECHO_REPLY << 8);
      ACCESS_UINT(TxFrame2Mem, ICMP_CHKSUM_OFS) = 0;                // initialize checksum field
      CopyFromFrame8900((unsigned char *)TxFrame2Mem + ICMP_DATA_OFS, ICMPDataCount);  // get data to echo...
      ACCESS_UINT(TxFrame2Mem, ICMP_CHKSUM_OFS) = 
        CalcChecksum((unsigned char *)TxFrame2Mem + IP_DATA_OFS, ICMPDataCount +
          ICMP_HEADER_SIZE, 0);
    
      TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + ICMP_HEADER_SIZE + ICMPDataCount;
      TransmitControl |= SEND_FRAME2;
    }
    //------------------------------------------------------------------------------
    // easyWEB internal function
    // prepares the TxFrame2-buffer to send a general TCP frame
    // the TCPCode-field is passed as an argument
    //------------------------------------------------------------------------------
    static void PrepareTCP_FRAME(unsigned long seqnr, unsigned long acknr,
      unsigned int TCPCode)
    {
      // Ethernet
      ACCESS_UINT(TxFrame2Mem, ETH_DA_OFS) = RemoteMAC[0];
      ACCESS_UINT(TxFrame2Mem, ETH_DA_OFS + 2) = RemoteMAC[1];
      ACCESS_UINT(TxFrame2Mem, ETH_DA_OFS + 4) = RemoteMAC[2];
      ACCESS_UINT(TxFrame2Mem, ETH_SA_OFS) = MyMAC[0];
      ACCESS_UINT(TxFrame2Mem, ETH_SA_OFS + 2) = MyMAC[1];
      ACCESS_UINT(TxFrame2Mem, ETH_SA_OFS + 4) = MyMAC[2];
      ACCESS_UINT(TxFrame2Mem, ETH_TYPE_OFS) = SWAPB(FRAME_IP);
      
      // IP
      ACCESS_UINT(TxFrame2Mem, IP_VER_IHL_TOS_OFS) = SWAPB(IP_VER_IHL);
    
      if (TCPCode & TCP_CODE_SYN)                    // if SYN, we want to use the MSS option
        ACCESS_UINT(TxFrame2Mem, IP_TOTAL_LENGTH_OFS) =
          SWAPB(IP_HEADER_SIZE + TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE);
      else
        ACCESS_UINT(TxFrame2Mem, IP_TOTAL_LENGTH_OFS) =
          SWAPB(IP_HEADER_SIZE + TCP_HEADER_SIZE);
    
      ACCESS_UINT(TxFrame2Mem, IP_IDENT_OFS) = 0;
      ACCESS_UINT(TxFrame2Mem, IP_FLAGS_FRAG_OFS) = 0;
      ACCESS_UINT(TxFrame2Mem, IP_TTL_PROT_OFS) = SWAPB((DEFAULT_TTL << 8) | PROT_TCP);
      ACCESS_UINT(TxFrame2Mem, IP_HEAD_CHKSUM_OFS) = 0;
      ACCESS_UINT(TxFrame2Mem, IP_SOURCE_OFS) = MyIP[0];
      ACCESS_UINT(TxFrame2Mem, IP_SOURCE_OFS + 2) = MyIP[1];
      ACCESS_UINT(TxFrame2Mem, IP_DESTINATION_OFS) = RemoteIP[0];
      ACCESS_UINT(TxFrame2Mem, IP_DESTINATION_OFS + 2) = RemoteIP[1];
      ACCESS_UINT(TxFrame2Mem, IP_HEAD_CHKSUM_OFS) = 
        CalcChecksum((unsigned char *)TxFrame2Mem + IP_VER_IHL_TOS_OFS,
          IP_HEADER_SIZE, 0);
      
      // TCP
      ACCESS_UINT(TxFrame2Mem, TCP_SRCPORT_OFS) = __swap_bytes(TCPLocalPort);
      ACCESS_UINT(TxFrame2Mem, TCP_DESTPORT_OFS) = __swap_bytes(TCPRemotePort);
    
      WriteDWBE((unsigned char *)TxFrame2Mem + TCP_SEQNR_OFS, seqnr);
      WriteDWBE((unsigned char *)TxFrame2Mem + TCP_ACKNR_OFS, acknr);
    
      ACCESS_UINT(TxFrame2Mem, TCP_WINDOW_OFS) = SWAPB(MAX_TCP_RX_DATA_SIZE);    // data bytes to accept
      ACCESS_UINT(TxFrame2Mem, TCP_CHKSUM_OFS) = 0;  // initalize checksum
      ACCESS_UINT(TxFrame2Mem, TCP_URGENT_OFS) = 0;
    
      if (TCPCode & TCP_CODE_SYN)                    // if SYN, we want to use the MSS option
      {
        ACCESS_UINT(TxFrame2Mem, TCP_DATA_CODE_OFS) = SWAPB(0x6000 | TCPCode);   // TCP header length = 24
        ACCESS_UINT(TxFrame2Mem, TCP_DATA_OFS) = SWAPB(TCP_OPT_MSS);             // MSS option
        ACCESS_UINT(TxFrame2Mem, TCP_DATA_OFS + 2) = SWAPB(MAX_TCP_RX_DATA_SIZE);// max. length of TCP-data we accept
        ACCESS_UINT(TxFrame2Mem, TCP_CHKSUM_OFS) =
          CalcChecksum((unsigned char *)TxFrame2Mem + TCP_SRCPORT_OFS,
            TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE, 1);
        TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE +
          TCP_OPT_MSS_SIZE;
      }
      else
      {
        ACCESS_UINT(TxFrame2Mem, TCP_DATA_CODE_OFS) = SWAPB(0x5000 | TCPCode);   // TCP header length = 20
        ACCESS_UINT(TxFrame2Mem, TCP_CHKSUM_OFS) =
          CalcChecksum((unsigned char *)TxFrame2Mem + TCP_SRCPORT_OFS,
            TCP_HEADER_SIZE, 1);
        TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + TCP_HEADER_SIZE;
      }
    
      TransmitControl |= SEND_FRAME2;
    }
    //------------------------------------------------------------------------------
    // easyWEB internal function
    // prepares the TxFrame1-buffer to send a payload-packet
    //------------------------------------------------------------------------------
    static void PrepareTCP_DATA_FRAME(void)
    {
      // Ethernet
      ACCESS_UINT(TxFrame1Mem, ETH_DA_OFS) = RemoteMAC[0];
      ACCESS_UINT(TxFrame1Mem, ETH_DA_OFS + 2) = RemoteMAC[1];
      ACCESS_UINT(TxFrame1Mem, ETH_DA_OFS + 4) = RemoteMAC[2];
      ACCESS_UINT(TxFrame1Mem, ETH_SA_OFS) = MyMAC[0];
      ACCESS_UINT(TxFrame1Mem, ETH_SA_OFS + 2) = MyMAC[1];
      ACCESS_UINT(TxFrame1Mem, ETH_SA_OFS + 4) = MyMAC[2];
      ACCESS_UINT(TxFrame1Mem, ETH_TYPE_OFS) = SWAPB(FRAME_IP);
      
      // IP   
      ACCESS_UINT(TxFrame1Mem, IP_VER_IHL_TOS_OFS) = SWAPB(IP_VER_IHL);
      ACCESS_UINT(TxFrame1Mem, IP_TOTAL_LENGTH_OFS) =
        __swap_bytes(IP_HEADER_SIZE + TCP_HEADER_SIZE + TCPTxDataCount);
      ACCESS_UINT(TxFrame1Mem, IP_IDENT_OFS) = 0;
      ACCESS_UINT(TxFrame1Mem, IP_FLAGS_FRAG_OFS) = 0;
      ACCESS_UINT(TxFrame1Mem, IP_TTL_PROT_OFS) = SWAPB((DEFAULT_TTL << 8) | PROT_TCP);
      ACCESS_UINT(TxFrame1Mem, IP_HEAD_CHKSUM_OFS) = 0;
      ACCESS_UINT(TxFrame1Mem, IP_SOURCE_OFS) = MyIP[0];
      ACCESS_UINT(TxFrame1Mem, IP_SOURCE_OFS + 2) = MyIP[1];
      ACCESS_UINT(TxFrame1Mem, IP_DESTINATION_OFS) = RemoteIP[0];
      ACCESS_UINT(TxFrame1Mem, IP_DESTINATION_OFS + 2) = RemoteIP[1];
      ACCESS_UINT(TxFrame1Mem, IP_HEAD_CHKSUM_OFS) = 
        CalcChecksum((unsigned char *)TxFrame1Mem + IP_VER_IHL_TOS_OFS,
          IP_HEADER_SIZE, 0);
    
      // TCP
      ACCESS_UINT(TxFrame1Mem, TCP_SRCPORT_OFS) = __swap_bytes(TCPLocalPort);
      ACCESS_UINT(TxFrame1Mem, TCP_DESTPORT_OFS) = __swap_bytes(TCPRemotePort);
    
      WriteDWBE((unsigned char *)TxFrame1Mem + TCP_SEQNR_OFS, TCPSeqNr);
      WriteDWBE((unsigned char *)TxFrame1Mem + TCP_ACKNR_OFS, TCPAckNr);
      
      ACCESS_UINT(TxFrame1Mem, TCP_DATA_CODE_OFS) = SWAPB(0x5000 | TCP_CODE_ACK);  // TCP header length = 20
      ACCESS_UINT(TxFrame1Mem, TCP_WINDOW_OFS) = SWAPB(MAX_TCP_RX_DATA_SIZE);  // data bytes to accept
      ACCESS_UINT(TxFrame1Mem, TCP_CHKSUM_OFS) = 0;  // initalize checksum
      ACCESS_UINT(TxFrame1Mem, TCP_URGENT_OFS) = 0;
      ACCESS_UINT(TxFrame1Mem, TCP_CHKSUM_OFS) =
        CalcChecksum((unsigned char *)TxFrame1Mem + TCP_SRCPORT_OFS,
          TCP_HEADER_SIZE + TCPTxDataCount, 1);
    }
    //------------------------------------------------------------------------------
    // easyWEB internal function
    // calculates the TCP/IP checksum. if 'IsTCP != 0', the TCP pseudo-header
    // will be included.
    //------------------------------------------------------------------------------
    static unsigned int CalcChecksum(void *Start, unsigned int Count,
      unsigned char IsTCP)
    {
      unsigned long Sum = 0;
      unsigned int *pStart = Start;
    
      if (IsTCP)
      {                                              // if we've a TCP frame...
        Sum += MyIP[0];                              // ...include TCP pseudo-header
        Sum += MyIP[1];
        Sum += RemoteIP[0];
        Sum += RemoteIP[1];
        Sum += __swap_bytes(Count);                  // TCP header length plus data length
        Sum += SWAPB(PROT_TCP);
      }
    
      while (Count > 1)                              // sum words
      {                            
        Sum += *pStart++;
        Count -= 2;
      }
    
      if (Count)                                     // add left-over byte, if any
        Sum += *(unsigned char *)pStart;
      
      while (Sum >> 16)                              // fold 32-bit sum to 16 bits
        Sum = (Sum & 0xFFFF) + (Sum >> 16);
      
      return ~Sum;
    }
    //------------------------------------------------------------------------------
    // easyWEB internal function
    // starts the timer as a retry-timer (used for retransmission-timeout)
    //------------------------------------------------------------------------------
    static void TCPStartRetryTimer(void)
    {
      TCPTimer = 0;
      RetryCounter = MAX_RETRYS;
      TCPFlags |= TCP_TIMER_RUNNING;
      TCPFlags |= TIMER_TYPE_RETRY;
    }
    //------------------------------------------------------------------------------
    // easyWEB internal function
    // starts the timer as a 'TIME_WAIT'-timer (used to finish a TCP-session)
    //------------------------------------------------------------------------------
    static void TCPStartFinTimer(void)
    {
      TCPTimer = 0;
      TCPFlags |= TCP_TIMER_RUNNING;
      TCPFlags &= ~TIMER_TYPE_RETRY;  
    }
    //------------------------------------------------------------------------------
    // easyWEB internal function
    // restarts the timer
    //------------------------------------------------------------------------------
    static void TCPRestartTimer(void)
    {
      TCPTimer = 0;
    }
    //------------------------------------------------------------------------------
    // easyWEB internal function
    // stopps the timer
    //------------------------------------------------------------------------------
    static void TCPStopTimer(void)
    {
      TCPFlags &= ~TCP_TIMER_RUNNING;
    }
    //------------------------------------------------------------------------------
    // easyWEB internal function
    // if a retransmission-timeout occured, check which packet
    // to resend.
    //------------------------------------------------------------------------------
    static void TCPHandleRetransmission(void)
    {
      switch (LastFrameSent)
      {
        case ARP_REQUEST :
          PrepareARP_REQUEST();
          break;
        case TCP_SYN_FRAME :
          PrepareTCP_FRAME(TCPSeqNr, TCPAckNr, TCP_CODE_SYN);
          break;
        case TCP_SYN_ACK_FRAME :
          PrepareTCP_FRAME(TCPSeqNr, TCPAckNr, TCP_CODE_SYN | TCP_CODE_ACK);
          break; 
        case TCP_FIN_FRAME :
          PrepareTCP_FRAME(TCPSeqNr, TCPAckNr, TCP_CODE_FIN | TCP_CODE_ACK);
          break; 
        case TCP_DATA_FRAME :
          TransmitControl |= SEND_FRAME1;
          break;
      }
    }
    //------------------------------------------------------------------------------
    // easyWEB internal function
    // if all retransmissions failed, close connection and indicate an error
    //------------------------------------------------------------------------------
    static void TCPHandleTimeout(void)
    {
      TCPStateMachine = CLOSED;
    
      if ((TCPFlags & (TCP_ACTIVE_OPEN | IP_ADDR_RESOLVED)) == TCP_ACTIVE_OPEN)
        SocketStatus = SOCK_ERR_ARP_TIMEOUT;         // indicate an error to user
      else
        SocketStatus = SOCK_ERR_TCP_TIMEOUT;
    
      TCPFlags = 0;                                  // clear all flags
    }
    //------------------------------------------------------------------------------
    // easyWEB internal function
    // function executed every 0.262s by the MCU. used for the
    // inital sequence number generator (ISN) and the TCP-timer
    //------------------------------------------------------------------------------
    #pragma vector = TIMERA1_VECTOR
    __interrupt void TCPClockHandler(void)
    {
      if (TAIV == 10)                                // check for timer overflow, reset int.-flag
      {
        ISNGenHigh++;                                // upper 16 bits of initial sequence number
        TCPTimer++;                                  // timer for retransmissions
      }
    }
    

    6840.tcpip.h

    //------------------------------------------------------------------------------
    // Name: webside.c
    // Func: example HTML-code for easyweb.c
    // Ver.: 1.1
    // Date: January 2004
    // Auth: Andreas Dannenberg
    //       MSP430 Applications
    //       Texas Instruments Inc.
    // Rem.: -
    //------------------------------------------------------------------------------
    
    const unsigned char WebSide[] =
    {
      "<html>\r\n"
      "<head>\r\n"
      "<meta http-equiv=\"refresh\" content=\"5\">\r\n"
      "<title>easyWEB - dynamic Webside</title>\r\n"
      "</head>\r\n"
      "\r\n"
      "<body bgcolor=\"#3030A0\" text=\"#FFFF00\">\r\n"
      "<p><b><font color=\"#FFFFFF\" size=\"6\"><i>Hello World!</i></font></b></p>\r\n"
      "\r\n"
      "<p><b>This is a dynamic webside hosted by the embedded Webserver</b> <b>easyWEB.</b></p>\r\n"
      "<p><b>Hardware:</b></p>\r\n"
      "<ul>\r\n"
      "<li><b>MSP430F149, 8 MHz, 60KB Flash, 2KB SRAM</b></li>\r\n"
      "<li><b>CS8900A Crystal Ethernet Controller</b></li>\r\n"
      "</ul>\r\n"
      "\r\n"
      "<p><b>A/D Converter Value Port P6.7:</b></p>\r\n"
      "\r\n"
      "<table bgcolor=\"#ff0000\" border=\"5\" cellpadding=\"0\" cellspacing=\"0\" width=\"500\">\r\n"
      "<tr>\r\n"
      "<td>\r\n"
      "<table width=\"AD7%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\r\n"
      "<tr><td bgcolor=\"#00ff00\">&nbsp;</td></tr>\r\n"
      "</table>\r\n"
      "</td>\r\n"
      "</tr>\r\n"
      "</table>\r\n"
      "\r\n"
      "<table border=\"0\" width=\"500\">\r\n"
      "<tr>\r\n"
      "<td width=\"20%\">0V</td>\r\n"
      "<td width=\"20%\">0.4V</td>\r\n"
      "<td width=\"20%\">0.7V</td>\r\n"
      "<td width=\"20%\">1.1V</td>\r\n"
      "<td width=\"20%\">1.5V</td>\r\n"
      "</tr>\r\n"
      "</table>\r\n"
      "\r\n"
      "<p><b>MCU Temperature:</b></p>\r\n"
      "\r\n"
      "<table bgcolor=\"#ff0000\" border=\"5\" cellpadding=\"0\" cellspacing=\"0\" width=\"500\">\r\n"
      "<tr>\r\n"
      "<td>\r\n"
      "<table width=\"ADA%\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\r\n"
      "<tr><td bgcolor=\"#00ff00\">&nbsp;</td></tr> \r\n"
      "</table>\r\n"
      "</td>\r\n"
      "</tr>\r\n"
      "</table>\r\n"
      "\r\n"
      "<table border=\"0\" width=\"500\">\r\n"
      "<tr>\r\n"
      "<td width=\"20%\">0�C</td>\r\n"
      "<td width=\"20%\">10�C</td>\r\n"
      "<td width=\"20%\">20�C</td>\r\n"
      "<td width=\"20%\">30�C</td>\r\n"
      "<td width=\"20%\">40�C</td>\r\n"
      "</tr>\r\n"
      "</table>\r\n"
      "</body>\r\n"
      "</html>\r\n"
      "\r\n"
    };
    

    Regards,

    Manmesha.

  • Hi  Neil,

       Thanks for your reply. I agree (its similar way i am able to put the query..  :)     ). I will go through the links provided by u. But i need to stick to the hardware i have (MSP430F149+ CS8900).

    Will get back to you with some new queries. Thanks once again.

    Regards,

    Manmesha. 

  • manmesha patankar said:
    I want to develop a duplex communication between PC and MSP430

    HTTP is inherently a duplex communication - as exemplified by this very forum!

    manmesha patankar said:
    i.e. MSP430 should b able to act as a server as well as a client at times

    That is an entirely unnecessary over-compication!

    As already noted, it is entirely possible to exchange data in both directions between an HTTP Client and Server - without any messing about reversing the roles!

  • manmesha patankar said:
    /166/6840.tcpip.h]

     Here IP address is setup to 192.168.0.30 Netmask to a full C class subnet/24 and Gateway to 192.168.0.1, is this correct for your network and is host .30 address free for Andreas software?

     If you understand how tcpip work it is easy to patch this example to perform Telnet or other simple two way protocol, it required no more than 5 minute to do that but this is another question....

     If all is ok on your browser write the IP 192.168.0.30 and if network is on same subnet and all is ok you can see the home page with temperature relay and button status and also you can set on or off relay.

  • Hi Roberto,

         Thanks for your reply. The IP address, sub-net mask and the gateway are not the same as that of my actual network. I am already able to see the web page, get the data after every fixed interval and also able to save and process the data at the PC end.  There is no button or any such thing with witch i can turn ON/OFF the relay. (there is no provision with which i can send the data to the processor at present.) 

      My main aim is to b able to send data from PC to MSP kit. (data transmission from MSP to PC i have achieved already. ) I want to know is it possible with the same code. Also i need info about what software can i use at the PC end to transmit data. Pls help me in that.

    Regards,

    Manmesha.

  • Hi Roberto,

         Thanks for your reply. The IP address, sub-net mask and the gateway are not the same as that of my actual network. I am already able to see the web page, get the data after every fixed interval and also able to save and process the data at the PC end.  There is no button or any such thing with witch i can turn ON/OFF the relay. (there is no provision with which i can send the data to the processor at present.) 

      My main aim is to b able to send data from PC to MSP kit. (data transmission from MSP to PC i have achieved already. ) I want to know is it possible with the same code. Also i need info about what software can i use at the PC end to transmit data. Pls help me in that.

    Regards,

    Manmesha.

  • Hello,

    First of all you need to know there the bottleneck is. May be you can use wireshark on your PC to see if the PC appli sends (or tries to send) data to your board. And see which layer is bad....

    BR

    Mich

  • manmesha patankar said:
    My main aim is to b able to send data from PC to MSP kit. (data transmission from MSP to PC i have achieved already. ) I want to know is it possible with the same code. Also i need info about what software can i use at the PC end to transmit data. Pls help me in that.

    I do not support  idea to use Wristwatch CPU for Ethernet/IP communications. Whatever... Here's my two cents: If just "data transmission" needed, then TCP/IP protocol and webserver is huge overkill from footprint and implementation point of view. I would simply use connectionless Ethernet frame (formatted as UDP datagrams) receive/send, without ARP. PC side software - application-specific. Not that much Windows/Linux C coding needed to send UDP datagram and wait for an answer.

  • Ilmars said:

     I would simply use connectionless Ethernet frame (formatted as UDP datagrams) receive/send, without ARP. PC side software -

    UDP is over IP, so an IP adresse is needed, so arp is needed (except if P2P, so no network conflict)?

  • Mich said:
    UDP is over IP, so an IP adresse is needed, so arp is needed (except if P2P, so no network conflict)?

    Actually it depends on what exactly you want to build. In case you are building product for masses, then I would say that from very beginning you are doing it wrong. If you are building it for use in controlled environment by controlled users, then it's ok for user to be responsible to *not* make IP conflicts, to follow simple instructions like setting static ARP entries on PC and so on.

  • manmesha patankar said:
     Thanks for your reply. The IP address, sub-net mask and the gateway are not the same as that of my actual network. I am already able to see the web page, get the data after every fixed interval and also able to save and process the data at the PC end.  There is no button or any such thing with witch i can turn ON/OFF the relay. (there is no provision with which i can send the data to the processor at present.) 

     Hi, here for me and other we help but don't write code for free. From your writing you are a beginner so we can help you learn how to work and not to have ready to eat solution so:

     Learn how tcp/ip work

     Adjust all network subnet and mask according to network you are plugged in

     Add rule to your browser if you access network from a proxy server to resolve local address locally

     Learn from example adding some basic functionality

     ask again for help if you encounter some obscure part and need a guide.

     Don't ask to have your job solved for free we have to work to live for us.

  • Ilmars said:
    I do not support  idea to use Wristwatch CPU for Ethernet/IP communications. Whatever... Here's my two cents: If just "data transmission" needed, then TCP/IP protocol and webserver is huge overkill from footprint and implementation point of view. I would simply use connectionless Ethernet frame (formatted as UDP datagrams) receive/send, without ARP. PC side software - application-specific. Not that much Windows/Linux C coding needed to send UDP datagram and wait for an answer.

    wristwatch processor are low performance, so if an 8 bit can access tcpip or a huge spaghetti coding like windows can do, I see no problem to do with an advanced risc architecture like the on in MSP.

     Andreas project is too old and new version can be assembled with MSP430F249 to use DMA but again new series F5x can perform better and cost less, with a 25Mips  and dma also an 100Mbps ethernet can be accessed too. Again with new Rob project using wiz820 old olimex is outdated in both cost and performance.

  • Roberto Romano said:
    I see no problem to do with an advanced risc architecture like the on in MSP.

    I did not say "impossible" but "I don't support idea" instead. - Huge difference.

    Roberto Romano said:
    if an 8 bit can access tcpip

    Also there's huge difference between "can access" and "full support". I shall repeat - for limited run, specific use or just for educational purposes it's OK and possible to pair ultralowpower msp430 with old, venerable power-hungry Ethernet controller, run limited TCP/IP stack and handle some occasional HTTP request (praying that routers does not fragment and reorder IP frames, user does not want to run VLANs and so on).

    To prove world that you can do it - yes. To manufacture product based on such design decision - no.

**Attention** This is a public forum