/**************************************************************************
 * (c) Copyright 2009 Actel Corporation.  All rights reserved.
 *
 *  Application demo for Smartfusion
 *
 *
 * Author : Actel Application Team
 * Rev     : 1.0.0.3
 *
 **************************************************************************/

/**************************************************************************/
/* Standard Includes */
/**************************************************************************/

#include <stdio.h>
#include <stdlib.h>

/**************************************************************************/
/* Driver Includes */
/**************************************************************************/

#include "../drivers/mss_ethernet_mac/mss_ethernet_mac.h"
#include "../drivers/mac/tcpip.h"
#include "conf_eth.h"

#include "ff.h"
#include "lwip/tcp.h"

#include "cpu_types.h"
//#include "webpages.h"

/**************************************************************************/
/* RTOS Includes */
/**************************************************************************/


/**************************************************************************/
/*Web Server Includes */
/**************************************************************************/

/**************************************************************************/
/* Definitions for Ethernet test */
/**************************************************************************/

#define OPEN_IP
#define BUF                       ((struct uip_eth_hdr *)&uip_buf[0])
#ifndef DEFAULT_NETMASK0
#define DEFAULT_NETMASK0          255
#endif

#ifndef DEFAULT_NETMASK1
#define DEFAULT_NETMASK1          255
#endif

#ifndef DEFAULT_NETMASK2
#define DEFAULT_NETMASK2          0
#endif

#ifndef DEFAULT_NETMASK3
#define DEFAULT_NETMASK3          0
#endif
#define TCP_PKT_SIZE              1600
#define IP_ADDR_LEN               4
#define PHY_ADDRESS               1
#define DHCP_ATTEMPTS             4
#define USER_RX_BUFF_SIZE         1600

/**************************************************************************/
/* Extern Declarations */
/**************************************************************************/
extern unsigned char              my_ip[4];
extern unsigned int               num_pkt_rx;
extern unsigned char              ip_known;
extern unsigned char              my_ip[IP_ADDR_LEN];
extern unsigned char              tcp_packet[TCP_PKT_SIZE];
extern unsigned char              dhcp_ip_found;
extern float                            real_voltage_value;
extern float                            real_current_value;
extern float                            real_temperature_value;
extern float                            real_temperature_value_tc;
extern float                            real_temperature_value_tk;
extern float                            real_temperature_value_tf;



volatile unsigned char            oled_on_irq = 0;
volatile unsigned char            sw1_menu_scroll = 0;
volatile unsigned char            sw2_select = 0;
volatile unsigned char            led_on = 0;
volatile unsigned char            analog_mode = 0;
volatile unsigned char            hyper_teminal_on = 0;
volatile unsigned char            webServerFlag = 0;

unsigned char appdata[5120];

char ethAddr[6] = {0xaa,0xbb,0xcc,0x66,0x55,0x44};
uint8_t                                     PRINT_MENU_var = 1;

/**************************************************************************/
/* Function to show IP address on OLED and UART */
/**************************************************************************/

void show_ip()
{
    char *textStr;
//    printf( "\n\rSuccessfully requested IP addr \n\r" );

    if((my_ip[0] == 192) &&
       (my_ip[1]==168)   &&
       (my_ip[2]==0)     &&
       (my_ip[3]==14))
    {
        printf( "\nBoard Static IP address: " );
        textStr = "Browse Static IP:";
    }
    else
    {
        printf( "\nBoard Dynamic IP address: " );
        textStr = "Browse Dynamic IP:";
    }
    printf( "%d.%d.%d.%d \n", my_ip[0], my_ip[1], my_ip[2], my_ip[3] );

//    sprintf(ipStr,"%d.%d.%d.%d     ",my_ip[0], my_ip[1], my_ip[2], my_ip[3]);

//    menu_show(textStr, ipStr);
}

/**************************************************************************/
/* Function to Initialize the MAC, setting the MAC address and */
/* fetches the IP address */
/**************************************************************************/
void init_mac()
{
    uint32_t time_out = 0;
    int32_t mac_cfg;
    int32_t i;
    int32_t rx_size;
    uint8_t rx_buffer[USER_RX_BUFF_SIZE];
    MSS_MAC_init(PHY_ADDRESS );
    /*
     * Configure the MAC.
     */
    mac_cfg = MSS_MAC_get_configuration();

    mac_cfg &= ~( MSS_MAC_CFG_STORE_AND_FORWARD | MSS_MAC_CFG_PASS_BAD_FRAMES );
    mac_cfg |=
    MSS_MAC_CFG_RECEIVE_ALL |
    MSS_MAC_CFG_PROMISCUOUS_MODE |
    MSS_MAC_CFG_FULL_DUPLEX_MODE |
    MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE |
    MSS_MAC_CFG_THRESHOLD_CONTROL_00;
    MSS_MAC_configure(mac_cfg );
    MSS_MAC_set_mac_address((uint8_t *)ethAddr);
    tcp_init();

    ip_known = 0;
    num_pkt_rx = 0;
    time_out = 0;
    for (i = 0; i < 1600; i++)
    {
        rx_buffer[i] = 0;
    }

    /* Logic to get the open IP address */
#ifdef OPEN_IP
    do
    {
        send_bootp_packet(0);
        do
        {
            rx_size = MSS_MAC_rx_pckt_size();
            time_out++;
            if(dhcp_ip_found)
                break;
         }while ( rx_size == 0 && (time_out < 3000000));
         MSS_MAC_rx_packet( rx_buffer, USER_RX_BUFF_SIZE, MSS_MAC_BLOCKING );
         num_pkt_rx++;
         process_packet( rx_buffer );
    }while((!dhcp_ip_found) && (time_out < 7000000));
#endif

    show_ip();
}
#if 0
uint32_t mac_cfg;
void init_mac()
{
	uint32_t time_out = 0;
	int32_t i;
	int32_t rx_size;
    uint8_t rx_buffer[USER_RX_BUFF_SIZE];
    
	unsigned char MacAddress[6];

	   /* Default MAC addr. */
    MacAddress[0] = ETHERNET_CONF_ETHADDR0;
    MacAddress[1] = ETHERNET_CONF_ETHADDR1;
	MacAddress[2] = ETHERNET_CONF_ETHADDR2;
	MacAddress[3] = ETHERNET_CONF_ETHADDR3;
	MacAddress[4] = ETHERNET_CONF_ETHADDR4;
	MacAddress[5] = ETHERNET_CONF_ETHADDR5;
   

    MSS_MAC_init(PHY_ADDRESS );
	/*
	 * Configure the MAC.
	 */
	mac_cfg = MSS_MAC_get_configuration();

	mac_cfg &= ~( MSS_MAC_CFG_STORE_AND_FORWARD | MSS_MAC_CFG_PASS_BAD_FRAMES );
//	mac_cfg &= ~(MSS_MAC_CFG_PASS_BAD_FRAMES );
	mac_cfg |=
          MSS_MAC_CFG_RECEIVE_ALL |
          MSS_MAC_CFG_PROMISCUOUS_MODE |
          MSS_MAC_CFG_FULL_DUPLEX_MODE |
          MSS_MAC_CFG_TRANSMIT_THRESHOLD_MODE |
          MSS_MAC_CFG_THRESHOLD_CONTROL_00;

	MSS_MAC_configure(mac_cfg );

	MSS_MAC_set_mac_address((uint8_t *)MacAddress);

	ip_known = 0;
	num_pkt_rx = 0;
	time_out = 0;
	for (i = 0; i < 1600; i++)
	{
		rx_buffer[i] = 0;
	}
	
#ifdef OPEN_IP
	do{

    	send_bootp_packet(0);
    	do {		    		
			rx_size = MSS_MAC_rx_pckt_size();
			time_out++;
			if(dhcp_ip_found)
			   break;//goto here;
    	}while ( rx_size == 0 && (time_out < 3000000));
		MSS_MAC_rx_packet( rx_buffer, USER_RX_BUFF_SIZE, MSS_MAC_BLOCKING );
		num_pkt_rx++;		
		process_packet( rx_buffer );
    }while((!dhcp_ip_found) && (time_out < 7000000));
#endif
	MSS_MAC_configure(mac_cfg );
    show_ip();
} // End of ethernet
#endif

struct http_state {
  char *file;
  u16_t left;
  u8_t retries;
};

/*-----------------------------------------------------------------------------------*/
static void
conn_err(void *arg, err_t err)
{
  struct http_state *hs;

  LWIP_UNUSED_ARG(err);

  hs = arg;
  mem_free(hs);
}
/*-----------------------------------------------------------------------------------*/
static void
close_conn(struct tcp_pcb *pcb, struct http_state *hs)
{
  tcp_arg(pcb, NULL);
  tcp_sent(pcb, NULL);
  tcp_recv(pcb, NULL);
  mem_free(hs);
  tcp_close(pcb);
}
/*-----------------------------------------------------------------------------------*/
static void
send_data(struct tcp_pcb *pcb, struct http_state *hs)
{
  err_t err;
  u16_t len;

  /* We cannot send more data than space available in the send
     buffer. */     
  if (tcp_sndbuf(pcb) < hs->left) {
    len = tcp_sndbuf(pcb);
  } else {
    len = hs->left;
  }

  do {
    err = tcp_write(pcb, hs->file, len, 0);
    if (err == ERR_MEM) {
      len /= 2;
    }
  } while (err == ERR_MEM && len > 1);

  if (err == ERR_OK) {
    hs->file += len;
    hs->left -= len;
    /*  } else {
    printf("send_data: error %s len %d %d\n", lwip_strerr(err), len, tcp_sndbuf(pcb));*/
  }
}

/*-----------------------------------------------------------------------------------*/
static err_t
http_poll(void *arg, struct tcp_pcb *pcb)
{
  struct http_state *hs;

  hs = arg;

  /*  printf("Polll\n");*/
  if (hs == NULL) {
    /*    printf("Null, close\n");*/
    tcp_abort(pcb);
    return ERR_ABRT;
  } else {
    ++hs->retries;
    if (hs->retries == 4) {
      tcp_abort(pcb);
      return ERR_ABRT;
    }
    send_data(pcb, hs);
  }

  return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static err_t
http_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
{
  struct http_state *hs;

  LWIP_UNUSED_ARG(len);

  hs = arg;

  hs->retries = 0;

  if (hs->left > 0) {
    send_data(pcb, hs);
  } else {
    close_conn(pcb, hs);
  }

  return ERR_OK;
}

void delay(int x)
{
	int ii;
	for(ii=0; ii<x; ii++)
		;
}
extern void ace_task(void);

void update_multimeter_page()
{
	ace_task();
	snprintf((char *)appdata, 1200,
"<HTML><HEAD><TITLE>Actel SmartFusion Webserver</TITLE>"
"<META http-equiv=Content-Type content=\"text/html; charset=windows-1252\">"
"<META http-equiv=Refresh content=2>"
"<BODY>"
"<FORM action=realdata.shtm method=get>"
"<TABLE class=tbl_text cellSpacing=1 cellPadding=1 width=\"800%\" align=center>"
"<TBODY>"
"  <TR>"
"    <TD align=middle colSpan=2 td <></TD>"
"  <TR>"
"    <TD align=middle colSpan=2><B>Real Time Data"
"  Display<B></B></B></TD></TR></TBODY></TABLE>"
"<TABLE class=tbl_text width=\"400%\" align=center border=1>"
"<TBODY>"
"<TR>"
"<TD align=middle width=\"70%\"><FONT size=-1><B>Channel/Quantity</B></FONT></TD>"
"<TD align=middle><FONT size=-1><B>Value</B></FONT></TD></TD></TR>"
"<TR>"
" <TD>Potentiometer Voltage</TD>"
"<TD align=middle>"
"%.2f V"
"</TD></TR>"
"<TR>"
" <TD>Potentiometer Current</TD>"
"<TD align=middle>"
"%.2f mA"
"</TD></TR>"
"<TR>"
" <TD>External Temperature in Celcius</TD>"
"<TD align=middle>"
"%.2f C"
"</TD></TR>"
"<TR>"
" <TD>External Temperature in Fahrenheit</TD>"
"<TD align=middle>"
"%.2f F"
"</TD></TR>"	
"<TR>"
" <TD>External Temperature in Kelvin</TD>"
"<TD align=middle>"
"%.2f K"
"</TD></TR></TBODY></TABLE>"
"<TABLE align=center>"
" <TBODY>"
"<form>"
"<input type = \"Button\" value = \"Home\" onclick = \"window.location.href='index.html'\">"
"</form>"
"</table></form>\n" 
"</body></html>\n \0", real_voltage_value, real_current_value, real_temperature_value_tc,real_temperature_value_tf,real_temperature_value_tk);

}

/*-----------------------------------------------------------------------------------*/
static err_t
http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
	  int i, res;
	  unsigned int s1;
	  FIL file1;
	  char *data;
	  struct http_state *hs;
	  //unsigned char Buff[10240];
      unsigned char *buffPtr = appdata;
      char *tempStrPtr;
      unsigned char oled_string[20];
      unsigned char c;
      
	  hs = (struct http_state *)arg;

	  if (err == ERR_OK && p != NULL) {

	    /* Inform TCP that we have taken the data. */
	    tcp_recved(pcb, p->tot_len);
	    
	    if (hs->file == NULL)
	    {
	       hs->left = 0;
	       data = (char *)p->payload;
           //iprintf("%s\n",data);
	       if (strncmp(data, "GET ", 4) == 0)
	       {

	    	   if( !strncmp( data, "GET /TextTerminal.html?s=", 25 )) 
               {
                   tempStrPtr = data + 25; 
                   for (i = 0; i < 20; i++)
                   {
                       c = *tempStrPtr++;
                       if (c == ' ')
                            break;
                       if (c == '+')
                       {
                          c = ' ';
                       } 
                       else if (c == '%') {
                            unsigned char temp1,temp2;
                            temp1=(*tempStrPtr++);
                            temp2=(*tempStrPtr++);
                            c = hex_digits_to_byte(temp1,temp2);
                        }
                        oled_string[i] = c;
                    }
                    oled_string[i] = '\0';
                
                    iprintf("STRING Submitted: %s\n",oled_string);
               }
      	       else if( !strncmp( data, "GET /realdata.shtml", 19 ) )
	  	       {
	  	           update_multimeter_page();
	  	    	   hs->file = (char *)appdata;
	  			   hs->left = 1200 /*sizeof(appdata)*/;
	  	       }
	  	       else if( !strncmp( data, "GET /mul.shtml", 14) )
	  	       {
	  	           update_multimeter_page();
	  	    	   hs->file = (char *)appdata;
	  			   hs->left = 1200/*sizeof(appdata)*/;
	  	       }
	  	       else
	  	       {
                   s1 = 0;
	  	    	   for(i = 0; i < 40; i++)
	               {
	                   if (((char *)data + 4)[i] == ' ' ||
	                       ((char *)data + 4)[i] == '\r' ||
	                       ((char *)data + 4)[i] == '\n')
	                   {
	                       ((char *)data + 4)[i] = 0;
	                       break;
	                   }
	               }

	               if (*(char *)(data + 4) == '/' &&
	                   *(char *)(data + 5) == 0)
	               {
	                   res = f_open(&file1, "index.html", FA_OPEN_EXISTING | FA_READ);
	               } 
	               else
	               {
	        	       res = f_open(&file1,(char *)data + 5, FA_OPEN_EXISTING | FA_READ);
	               }
	               
	               if(res)
	               {
	                   if(f_open(&file1, "404.html", FA_OPEN_EXISTING | FA_READ))
	            	       iprintf("Files are not present in SPI Flash %s\n\r", (data + 5));
	               }
	               else
	               {
           	           res = f_read(&file1, buffPtr, sizeof(appdata), &s1);
           	           iprintf("File size =%d\n\r", s1);
                       f_close(&file1);
           	           
	               }

                   hs->file = (char *)appdata;
		           hs->left = s1;
	  	       }
		       pbuf_free(p);
               send_data(pcb, hs);
               /* Tell TCP that we wish be to informed of data that has been
	              successfully sent by a call to the http_sent() function. */
               tcp_sent(pcb, http_sent);
	       }
	       else
	       {
	           pbuf_free(p);
	           close_conn(pcb, hs);
	       }
	   }
#if 1
	   else
	   {
	       pbuf_free(p);
	   }
#endif
	}

	if (err == ERR_OK && p == NULL)
	{
	    close_conn(pcb, hs);
    }
	return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
static err_t
http_accept(void *arg, struct tcp_pcb *pcb, err_t err)
{
  struct http_state *hs;

  LWIP_UNUSED_ARG(arg);
  LWIP_UNUSED_ARG(err);

  tcp_setprio(pcb, TCP_PRIO_MIN);

  /* Allocate memory for the structure that holds the state of the
     connection. */
  hs = (struct http_state *)mem_malloc(sizeof(struct http_state));

  if (hs == NULL) {
    printf("http_accept: Out of memory\n");
    return ERR_MEM;
  }

  /* Initialize the structure. */
  hs->file = NULL;
  hs->left = 0;
  hs->retries = 0;

  /* Tell TCP that this is the structure we wish to be passed for our
     callbacks. */
  tcp_arg(pcb, hs);

  /* Tell TCP that we wish to be informed of incoming data by a call
     to the http_recv() function. */
  tcp_recv(pcb, http_recv);

  tcp_err(pcb, conn_err);
  
  tcp_poll(pcb, http_poll, 4);
  return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
void
httpd_init(void)
{
  struct tcp_pcb *pcb;

  pcb = tcp_new();
  tcp_bind(pcb, IP_ADDR_ANY, 80);
  pcb = tcp_listen(pcb);
  tcp_accept(pcb, http_accept);
}
/*-----------------------------------------------------------------------------------*/
