/**************************************************************************
 * (c) Copyright 2010 Microsemi Corporation.  All rights reserved.
 *
 *  Modbus TCP Server on lwIP TCP/IP stack with freeRTOS Application demo
 *  for SmartFusion
 *
 *
 * Author : Corporate Application Team
 * Rev    : 1.0
 *
 **************************************************************************/

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

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

/**************************************************************************/
/* RTOS Includes */
/**************************************************************************/
#include "FreeRTOS.h"
#include "task.h"

/**************************************************************************/
/* FreeModbus includes */
/**************************************************************************/
#include "mb.h"

/**************************************************************************/
/* lwIP TCP/IP Stack Includes */
/**************************************************************************/
#include "cpu_types.h"
#include "conf_eth.h"
#include "lwip/api.h"

/**************************************************************************/
/* Firmware Includes */
/**************************************************************************/

#include "./drivers/mss_watchdog/mss_watchdog.h"
#include "./drivers/mss_ethernet_mac/mss_ethernet_mac.h"
#include "./drivers/mss_ace/mss_ace.h"
#include "tcpip.h"
/**************************************************************************/
/* Static functions */
/**************************************************************************/
extern void init_modbus_regs( void );
static void init_systick( void );

/**************************************************************************/
/* Definitions & Variables */
/**************************************************************************/
#define PPP_AUTH_ENABLED        0
#define PPP_USER                "freemodbus"
#define PPP_PASS                "insecure"

#define PHY_ADDRESS             1

extern unsigned char            my_ip[4];
uint32_t                        mac_cfg;
extern unsigned int             num_pkt_rx;
extern unsigned char            ip_known;
extern unsigned char            dhcp_ip_found;

#define USER_RX_BUFF_SIZE       1600
#define OPEN_IP                 1
#define PROG                    "FreeModbus"


extern void demolwIPInit( void );

void show_ip()
{
    iprintf( "Successfully requested IP addr \n\r" );

    if( (my_ip[0] == 192) && (my_ip[1]==168)&& (my_ip[2]==0) && (my_ip[3]==14))
    {
        iprintf( "Static IP address: " );
    }
    else
    {
        iprintf( "Dynamic/Open IP address: " );
    }
    iprintf( "%d.%d.%d.%d \n\r", my_ip[0], my_ip[1], my_ip[2], my_ip[3] );
}

void init_mac()
{
    uint32_t time_out = 0;
    int32_t i;
    int32_t rx_size;
    uint8_t rx_buffer[USER_RX_BUFF_SIZE];

    portCHAR 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_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
    show_ip();
} // End of ethernet


void vMBServerTask( void *arg )
{
    eMBErrorCode    xStatus;

    for( ;; )
    {
        if( eMBTCPInit( MB_TCP_PORT_USE_DEFAULT ) != MB_ENOERR )
        {
            iprintf("can't initialize modbus stack!\r\n");
        }
        else if( eMBEnable(  ) != MB_ENOERR )
        {
            iprintf("can't enable modbus stack!\r\n");
        }
        else
        {
            do
            {
                xStatus = eMBPoll(  );
            }
            while( xStatus == MB_ENOERR );
        }
        iprintf("Disabling modbus stack!\r\n");

        ( void )eMBDisable(  );
        iprintf("Closing modbus stack!\r\n");
        ( void )eMBClose(  );
    }
}


/*
 * Initialize MSS SysTick timer (10ms period)
 */

static void init_systick( void )
{
//    ( void )SystemCoreClockUpdate(  );
    ( void )SysTick_Config( SystemCoreClock / 100 );
}


int main( void )
{
    MSS_WD_disable();
    iprintf("SmartFusion Modbus Demo\n\r");
    iprintf("Initializing the MAC and getting IP Address\n\r");

    ACE_init();
    ( void )init_modbus_regs(  );
    init_mac();

    /* Setup lwIP. & Starts the vMBServerTask after TCP Task is created */
    demolwIPInit();

    /* Enabling the M3 SysTick TImer in SF */
    /* *(volatile unsigned long *)0xE000E010 = 0x7;
       *(volatile unsigned long *)0xE0042038 = 0x31000000; */
    init_systick( );
    /* Starts the FreeRTOS Scheduler */
    vTaskStartScheduler();
    iprintf("Should Never Come here\n\r");
    return 0;
}

