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

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

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

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

#include "core10100_ahbapb.h"
#include "../BSP/mac/tcpip.h"

/**************************************************************************/
/* System Memory Map */
/**************************************************************************/

#include "platform.h"

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

#include "FreeRTOS.h"
#include "semphr.h"

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

#include "uip.h"
#include "uip_arp.h"
#include "httpd.h"

/**************************************************************************/
/* 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;
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;
extern unsigned char              oled_string[20];

char ethAddr[6] = {0xaa,0xbb,0xcc,0x66,0x55,0x44};
uint8_t                                     PRINT_MENU_var = 1;
extern volatile unsigned char inWebTask;
extern xSemaphoreHandle webSemHndl;

extern void menu_show(char *, char *);

extern mac_instance_t g_mac;

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

void show_ip()
{
    char ipStr[20], *textStr;
    printf( "Successfully requested IP addr \n\r" );

    if((my_ip[0] == 192) &&
       (my_ip[1]==168)   &&
       (my_ip[2]==0)     &&
       (my_ip[3]==14))
    {
        printf( "Static IP address: " );
        textStr = "Browse Static IP:";
    }
    else
    {
        printf( "Dynamic IP address: " );
        textStr = "Browse Dynamic IP:";
    }
    printf( "%d.%d.%d.%d \n\r", 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];
    MAC_init(&g_mac, CORE10100_BASE_ADDR ,PHY_ADDRESS );
    /*
     * Configure the MAC.
     */
    mac_cfg = MAC_get_configuration(&g_mac);

    mac_cfg &= ~( MAC_CFG_STORE_AND_FORWARD | MAC_CFG_PASS_BAD_FRAMES | MAC_CFG_TRANSMIT_THRESHOLD_MODE );
    mac_cfg |=
    MAC_CFG_RECEIVE_ALL |
    MAC_CFG_PROMISCUOUS_MODE |
    MAC_CFG_FULL_DUPLEX_MODE |
//    MAC_CFG_TRANSMIT_THRESHOLD_MODE |
    MAC_CFG_THRESHOLD_CONTROL_00;
    MAC_configure(&g_mac, mac_cfg );
    MAC_set_mac_address(&g_mac,(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 = MAC_rx_pckt_size(&g_mac);
            time_out++;
            if(dhcp_ip_found)
                break;
         }while ( rx_size == 0 && (time_out < 3000000));
        MAC_rx_packet( &g_mac, rx_buffer, USER_RX_BUFF_SIZE, MAC_BLOCKING );
         num_pkt_rx++;
         process_packet( rx_buffer );
    }while((!dhcp_ip_found) && (time_out < 7000000));
#endif

    show_ip();
}

/**************************************************************************/
/* Function for uIP initialization */
/**************************************************************************/

void uIP_init()
{
    uip_ipaddr_t ipaddr;
    static struct uip_eth_addr sTempAddr;

    /* init tcp/ip stack */
    uip_init();
    uip_ipaddr(ipaddr, my_ip[0], my_ip[1], my_ip[2], my_ip[3]);
    uip_sethostaddr(ipaddr);

    uip_ipaddr(ipaddr,
               DEFAULT_NETMASK0,
               DEFAULT_NETMASK1,
               DEFAULT_NETMASK2,
               DEFAULT_NETMASK3);
    uip_setnetmask(ipaddr);

    /* set mac address */
    sTempAddr.addr[0] = ethAddr[0];
    sTempAddr.addr[1] = ethAddr[1];
    sTempAddr.addr[2] = ethAddr[2];
    sTempAddr.addr[3] = ethAddr[3];
    sTempAddr.addr[4] = ethAddr[4];
    sTempAddr.addr[5] = ethAddr[5];

    uip_setethaddr(sTempAddr);

    /* init application */
    httpd_init();
}

/**************************************************************************/
/*  Function to create web Task */
/**************************************************************************/
void web_task(void *para)
{
    long lPeriodicTimer, lARPTimer, lPacketLength;
    unsigned long ulTemp;

    while(1)
    {
        /* This semaphore will wait for the user input to run webserver */
        xSemaphoreTake( webSemHndl, portMAX_DELAY ) ;

        init_mac();
        uIP_init();

        lPeriodicTimer = 0;
        lARPTimer = 0;

        while(1)
        {
            lPacketLength = MAC_rx_packet( &g_mac, uip_buf, sizeof(uip_buf), MAC_BLOCKING);
            if(lPacketLength > 0)
            {
                /*  Set uip_len for uIP stack usage.*/
                uip_len = (unsigned short)lPacketLength;

                /*  Process incoming IP packets here.*/
                if(BUF->type == htons(UIP_ETHTYPE_IP))
                {
                    uip_arp_ipin();
                    uip_input();

                    /*  If the above function invocation resulted in data that
                         should be sent out on the network, the global variable
                         uip_len is set to a value > 0.*/

                    if(uip_len > 0)
                    {
                        uip_arp_out();
                        MAC_tx_packet( &g_mac, uip_buf, uip_len, MAC_NONBLOCKING);
                        uip_len = 0;
                    }
                }

                /*  Process incoming ARP packets here. */

                else if(BUF->type == htons(UIP_ETHTYPE_ARP))
                {
                    uip_arp_arpin();

                    /*  If the above function invocation resulted in data that
                         should be sent out on the network, the global variable
                         uip_len is set to a value > 0  */

                    if(uip_len > 0)
                    {
                    	MAC_tx_packet( &g_mac, uip_buf, uip_len, MAC_NONBLOCKING);
                        uip_len = 0;
                    }
                }
            }

            for(ulTemp = 0; ulTemp < UIP_CONNS; ulTemp++)
            {
                uip_periodic(ulTemp);
                /* If the above function invocation resulted in data that
                    should be sent out on the network, the global variable
                    uip_len is set to a value > 0 */

                if(uip_len > 0)
                {
                    uip_arp_out();
                    MAC_tx_packet( &g_mac, uip_buf, uip_len, MAC_NONBLOCKING);
                    uip_len = 0;
                }
            }

            uip_arp_timer();

            if(!inWebTask)
                break;
        }
    }
}
