text: //*****************************************************************************
  //
  // enet_lwip.c - Sample WebServer Application using lwIP.
  //
  // Copyright (c) 2007-2013 Texas Instruments Incorporated.  All rights reserved.
  // Software License Agreement
  // 
  // Texas Instruments (TI) is supplying this software for use solely and
  // exclusively on TI's microcontroller products. The software is owned by
  // TI and/or its suppliers, and is protected under applicable copyright
  // laws. You may not combine this software with "viral" open-source
  // software in order to form a larger program.
  // 
  // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
  // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
  // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
  // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
  // DAMAGES, FOR ANY REASON WHATSOEVER.
  // 
  // This is part of revision 10636 of the EK-LM3S6965 Firmware Package.
  //
  //*****************************************************************************
  
  #include "inc/hw_ints.h"
  #include "inc/hw_memmap.h"
  #include "inc/hw_nvic.h"
  #include "inc/hw_types.h"
  #include "driverlib/ethernet.h"
  #include "driverlib/flash.h"
  #include "driverlib/gpio.h"
  #include "driverlib/interrupt.h"
  #include "driverlib/sysctl.h"
  #include "driverlib/systick.h"
  #include "utils/locator.h"
  #include "utils/lwiplib.h"
  #include "utils/uartstdio.h"
  #include "utils/ustdlib.h"
  #include "httpserver_raw/httpd.h"
  #include "drivers/rit128x96x4.h"
  
  //*****************************************************************************
  //
  //! \addtogroup example_list
  //! <h1>Ethernet with lwIP (enet_lwip)</h1>
  //!
  //! This example application demonstrates the operation of the Stellaris
  //! Ethernet controller using the lwIP TCP/IP Stack configured to operate as
  //! an HTTP file server (web server).  DHCP is used to obtain an Ethernet
  //! address.  If DHCP times out without obtaining an address, AUTOIP will be
  //! used to obtain a link-local address.  The address that is selected will be
  //! shown on the OLED display.
  //!
  //! The file system code will first check to see if an SD card has been plugged
  //! into the microSD slot.  If so, all file requests from the web server will
  //! be directed to the SD card.  Otherwise, a default set of pages served up
  //! by an internal file system will be used.  Source files for the internal
  //! file system image can be found in the ``fs'' directory.  If any of these
  //! files are changed, the file system image (lmi-fsdata.h) should be
  //! rebuilt using the command:
  //!
  //! ./../../tools/bin/makefsfile -i fs -o lmi-fsdata.h -r -h -q
  //!
  //! For additional details on lwIP, refer to the lwIP web page at:
  //! http://savannah.nongnu.org/projects/lwip/
  //
  //*****************************************************************************
  
  //*****************************************************************************
  //
  // Defines for setting up the system clock.
  //
  //*****************************************************************************
  #define SYSTICKHZ               100
  #define SYSTICKMS               (1000 / SYSTICKHZ)
  #define SYSTICKUS               (1000000 / SYSTICKHZ)
  #define SYSTICKNS               (1000000000 / SYSTICKHZ)
  
  //*****************************************************************************
  //
  // Interrupt priority definitions.  The top 3 bits of these values are
  // significant with lower values indicating higher priority interrupts.
  //
  //*****************************************************************************
  #define SYSTICK_INT_PRIORITY    0x80
  #define ETHERNET_INT_PRIORITY   0xC0
  
  //*****************************************************************************
  //
  // External Application references.
  //
  //*****************************************************************************
  extern void fs_init(void);
  extern void fs_tick(unsigned long ulTickMS);
  
  //*****************************************************************************
  //
  // The error routine that is called if the driver library encounters an error.
  //
  //*****************************************************************************
  #ifdef DEBUG
  void
  __error__(char *pcFilename, unsigned long ulLine)
  {
  }
  #endif
  
  //*****************************************************************************
  //
  // Display an lwIP type IP Address.
  //
  //*****************************************************************************
  void
  DisplayIPAddress(unsigned long ipaddr, unsigned long ulCol,
                   unsigned long ulRow)
  {
      char pucBuf[16];
      unsigned char *pucTemp = (unsigned char *)&ipaddr;
  
      //
      // Convert the IP Address into a string.
      //
      usprintf(pucBuf, "%d.%d.%d.%d", pucTemp[0], pucTemp[1], pucTemp[2],
               pucTemp[3]);
  
      //
      // Display the string.
      //
      RIT128x96x4StringDraw(pucBuf, ulCol, ulRow, 15);
  }
  
  //*****************************************************************************
  //
  // Required by lwIP library to support any host-related timer functions.
  //
  //*****************************************************************************
  void
  lwIPHostTimerHandler(void)
  {
      static unsigned long ulLastIPAddress = 0;
      unsigned long ulIPAddress;
  
      ulIPAddress = lwIPLocalIPAddrGet();
  
      //
      // If IP Address has not yet been assigned, update the display accordingly
      //
      if(ulIPAddress == 0)
      {
          static int iColumn = 6;
  
          //
          // Update status bar on the display.
          //
          RIT128x96x4Enable(1000000);
          if(iColumn < 12)
          {
              RIT128x96x4StringDraw("< ", 0, 24, 15);
              RIT128x96x4StringDraw("*",iColumn, 24, 7);
          }
          else
          {
              RIT128x96x4StringDraw(" *",iColumn - 6, 24, 7);
          }
  
          iColumn++;
          if(iColumn > 114)
          {
              iColumn = 6;
              RIT128x96x4StringDraw(" >", 114, 24, 15);
          }
          RIT128x96x4Disable();
      }
  
      //
      // Check if IP address has changed, and display if it has.
      //
      else if(ulLastIPAddress != ulIPAddress)
      {
          ulLastIPAddress = ulIPAddress;
          RIT128x96x4Enable(1000000);
          RIT128x96x4StringDraw("                       ", 0, 16, 15);
          RIT128x96x4StringDraw("                       ", 0, 24, 15);
          RIT128x96x4StringDraw("IP:   ", 0, 16, 15);
          RIT128x96x4StringDraw("MASK: ", 0, 24, 15);
          RIT128x96x4StringDraw("GW:   ", 0, 32, 15);
          DisplayIPAddress(ulIPAddress, 36, 16);
          ulIPAddress = lwIPLocalNetMaskGet();
          DisplayIPAddress(ulIPAddress, 36, 24);
          ulIPAddress = lwIPLocalGWAddrGet();
          DisplayIPAddress(ulIPAddress, 36, 32);
          RIT128x96x4Disable();
      }
  }
  
  //*****************************************************************************
  //
  // The interrupt handler for the SysTick interrupt.
  //
  //*****************************************************************************
  void
  SysTickIntHandler(void)
  {
      //
      // Call the lwIP timer handler.
      //
      lwIPTimer(SYSTICKMS);
  
      //
      // Run the file system tick handler.
      //
      fs_tick(SYSTICKMS);
  }
  
  //*****************************************************************************
  //
  // This example demonstrates the use of the Ethernet Controller.
  //
  //*****************************************************************************
  
  int
  main(void)
  {
      unsigned long ulUser0, ulUser1;
      unsigned char pucMACArray[8];
  
      //
      // Set the clocking to run directly from the crystal.
      //
      SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
                     SYSCTL_XTAL_8MHZ);
  
      //
      // Initialize the UART for debug output.
      //
      SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
      GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
      UARTStdioInit(0);
  
      //
      // Initialize the OLED display.
      //
      RIT128x96x4Init(1000000);
      RIT128x96x4StringDraw("Ethernet with lwIP", 12, 0, 15);
  
      //
      // Enable and Reset the Ethernet Controller.
      //
      SysCtlPeripheralEnable(SYSCTL_PERIPH_ETH);
      SysCtlPeripheralReset(SYSCTL_PERIPH_ETH);
  
      //
      // Enable Port F for Ethernet LEDs.
      //  LED0        Bit 3   Output
      //  LED1        Bit 2   Output
      //
      SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
      GPIOPinTypeEthernetLED(GPIO_PORTF_BASE, GPIO_PIN_2 | GPIO_PIN_3);
  
      //
      // Configure SysTick for a periodic interrupt.
      //
      SysTickPeriodSet(SysCtlClockGet() / SYSTICKHZ);
      SysTickEnable();
      SysTickIntEnable();
  
      //
      // Enable processor interrupts.
      //
      IntMasterEnable();
  
      //
      // Initialize the file system.
      //
      RIT128x96x4Disable();
      fs_init();
  
      //
      // Configure the hardware MAC address for Ethernet Controller filtering of
      // incoming packets.
      //
      // For the LM3S6965 Evaluation Kit, the MAC address will be stored in the
      // non-volatile USER0 and USER1 registers.  These registers can be read
      // using the FlashUserGet function, as illustrated below.
      //
      FlashUserGet(&ulUser0, &ulUser1);
      if((ulUser0 == 0xffffffff) || (ulUser1 == 0xffffffff))
      {
          //
          // We should never get here.  This is an error if the MAC address has
          // not been programmed into the device.  Exit the program.
          //
          RIT128x96x4Enable(1000000);
          RIT128x96x4StringDraw("MAC Address", 0, 16, 15);
          RIT128x96x4StringDraw("Not Programmed!", 0, 24, 15);
          while(1)
          {
          }
      }
  
      //
      // Convert the 24/24 split MAC address from NV ram into a 32/16 split MAC
      // address needed to program the hardware registers, then program the MAC
      // address into the Ethernet Controller registers.
      //
      pucMACArray[0] = ((ulUser0 >>  0) & 0xff);
      pucMACArray[1] = ((ulUser0 >>  8) & 0xff);
      pucMACArray[2] = ((ulUser0 >> 16) & 0xff);
      pucMACArray[3] = ((ulUser1 >>  0) & 0xff);
      pucMACArray[4] = ((ulUser1 >>  8) & 0xff);
      pucMACArray[5] = ((ulUser1 >> 16) & 0xff);
  
      //
      // Initialze the lwIP library, using DHCP.
      //
      lwIPInit(pucMACArray, 0, 0, 0, IPADDR_USE_DHCP);
  
      //
      // Setup the device locator service.
      //
      LocatorInit();
      LocatorMACAddrSet(pucMACArray);
      LocatorAppTitleSet("EK-LM3S6965 enet_lwip");
  
      //
      // Indicate that DHCP has started.
      //
      RIT128x96x4Enable(1000000);
      RIT128x96x4StringDraw("Waiting for IP", 0, 16, 15);
      RIT128x96x4StringDraw("<                   > ", 0, 24, 15);
      RIT128x96x4Disable();
  
      //
      // Initialize a sample httpd server.
      //
      httpd_init();
  
      //
      // Set the interrupt priorities.  We set the SysTick interrupt to a higher
      // priority than the Ethernet interrupt to ensure that the file system
      // tick is processed if SysTick occurs while the Ethernet handler is being
      // processed.  This is very likely since all the TCP/IP and HTTP work is
      // done in the context of the Ethernet interrupt.
      //
      IntPriorityGroupingSet(4);
      IntPrioritySet(INT_ETH, ETHERNET_INT_PRIORITY);
      IntPrioritySet(FAULT_SYSTICK, SYSTICK_INT_PRIORITY);
  
          UARTprintf("enet_lwip\n");
  
      //
      // Loop forever.  All the work is done in interrupt handlers.
      //
      while(1)
      {
      }
  }
  