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

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

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

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

#include "a2fxxxm3.h"

#include "mss_watchdog.h"
#include "mss_uart.h"
#include "mss_ethernet_mac.h"
#include "mss_rtc.h"
#include "mss_timer.h"

#include "lwip/sys.h"
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/ip.h"
#include "lwip/tcp.h"
#include "lwip/dhcp.h"
#include "netif/etharp.h"
#include "netif/loopif.h"

#include "ff.h"
#include "diskio.h"
#include "tftpd.h"

/**************************************************************************/
/* RTOS Includes */
/**************************************************************************/
extern void ethernetif_input( void * pvParameters );
extern void prvlwIPInit( void );

/**************************************************************************/
/* Preprocessor Macros*/
/**************************************************************************/
static uint16_t System_ticks = 0;

/* Simple periodic polling function */
#define PERIODIC(var,time,function) \
                                     if((System_ticks - var) > time) \
                                     {                               \
                                        var += time;                 \
                                       function;                     \
                                     }                               \
    

struct netif netif;
#if LWIP_HAVE_LOOPIF  
   struct netif netif_loop;
#endif

#define configCPU_CLOCK_HZ               ( ( unsigned long ) SystemFrequency )
#define configTICK_RATE_HZ               ( 100 )


#define portNVIC_SYSTICK_CTRL            ( ( volatile unsigned long *) 0xe000e010 )
#define portNVIC_SYSTICK_LOAD            ( ( volatile unsigned long *) 0xe000e014 )

#define SYS_TICK_CTRL_AND_STATUS_REG      0xE000E010
#define SYS_TICK_CONFIG_REG               0xE0042038
#define SYS_TICK_FCLK_DIV_32_NO_REF_CLK   0x31000000
#define ENABLE_SYS_TICK                   0x7

#define portNVIC_SYSTICK_CLK              0x00000004
#define portNVIC_SYSTICK_INT              0x00000002
#define portNVIC_SYSTICK_ENABLE           0x00000001

#define mainETH_TASK_PRIORITY            ( configMAX_PRIORITIES - 1)

/**************************************************************************/
/*Declaration of global variables*/
/**************************************************************************/
/**************************************************************************/
/*Extern Declarations*/
/**************************************************************************/
extern void init_mac(void);
void portlwIPInit( void );

/**************************************************************************/
/* Function to initialization all necessary hardware components for this*/
/* demo*/
/**************************************************************************/
FATFS fatfs;        /* File system object */
size_t
UART_Polled_Rx
(
   mss_uart_instance_t * this_uart,
   uint8_t * rx_buff,
   size_t buff_size
)
{
   size_t rx_size = 0U;
   while( rx_size < buff_size )
   {
      while ( this_uart->hw_reg_bit->LSR_DR != 0U  )
      {
         rx_buff[rx_size] = this_uart->hw_reg->RBR;
         ++rx_size;
      }
   }
   return rx_size;
}

void Timer1_IRQHandler( void )
{
   System_ticks++;
   /* Clear TIM1 interrupt */
   MSS_TIM1_clear_irq();
}


void init_system()
{
   uint32_t timer1_load_value;
   /* Disable the Watch Dog Timer */
   MSS_WD_disable( );
   /* Initialize and configure UART0. */
   MSS_UART_init
   (
      &g_mss_uart0,
      MSS_UART_57600_BAUD,
      MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT
   );
   SystemCoreClockUpdate();
   /* Timer 1 for 10ms */
   timer1_load_value = g_FrequencyPCLK0/1000;
   MSS_TIM1_init( MSS_TIMER_PERIODIC_MODE );
   MSS_TIM1_load_immediate( timer1_load_value );
   MSS_TIM1_start();
   MSS_TIM1_enable_irq();
} 
void Init_FS()
{
   long p2;
   FATFS *fs;
   /* File System  on SPI Flash Init */
   if(disk_initialize(0))
   {
      iprintf("Disk Initialization Failed: SPI interface Error \n\r");
   }
   else
   {
      f_mount(0, &fatfs);
      if(f_getfree("", (DWORD*)&p2, &fs))
      {
         /* Create the File System */
         if (f_mkfs(0, 0, 2048))
         {
            iprintf("File System Cann't be created \n\r");
         }
      }
   }
   MSS_RTC_init();
   MSS_RTC_configure( MSS_RTC_NO_COUNTER_RESET );
   MSS_RTC_start();
}


void show_menu()
{
   uint8_t   key = 0;
   iprintf( "\n");
   iprintf( "********* SmartFusion Play Menu **************\n\r" );
   iprintf( "********* 1.  TFTP *********************\n\r" );
   iprintf( "********* 2.  FAT FS *********************\n\r" );
   iprintf( "\n\r");

   UART_Polled_Rx(&g_mss_uart0, &key, 1);
   switch (key)
   {
      case '1':
      {
         show_ip();
         iprintf("PUT Command is supported\n\rUsage on host PC:\n\r");
         iprintf("tftp -i <board_ip_addr> PUT <filename.ext>\n\r");
         iprintf("Do you want to change Menu?\n\r please enter any key to show menu\n\r");
         break;
      }

      case '2':
      {
         iprintf("\n\rPlease enter any command followed by enter key\n fs - FS Status\n\r fl - FS Listing\n\r fo <filename> Open file\n\r");
         iprintf(" fn <new name> <old name> - Rename File\n\r fx <src_name> <dest_name> - File Copy\n\r fu <filename> - Remove file\n\r");
         iprintf(" fm - Format the SPI Flash\n\r");
         iprintf(" t <M D YYYY Hr Min > - To set the RTC time\n\r");
         fatfs_ops();
         iprintf("\n\r");
         iprintf("Do you want to change Menu?\n\r please enter any key to show menu\n\r");
         break;
      }
      default:
      {
         iprintf("Select Correct Option\n\r");
         show_menu();
         break;
      }
   }
}
/****************************************************************/
/* Entry to Main form user boot code                             */
/****************************************************************/
int main()
{
   uint16_t arp_timer = 0;
   uint16_t tcp_timer = 0;
   uint8_t   key = 0;
   uint8_t   rx_size =0;
   /* Initialization all necessary hardware components */
   init_system();
   /*--------------------------------------------------------------------------
    * Send greeting message over the UART.
   */
   printf("*** Welcome to SmartFusion ***\n\r");
   printf("*** FAT FS on SPI FLash, TFTP  on lwIP\n\r");
   Init_FS();
   init_mac();
   portlwIPInit();

   if (tftpd_init())
   {
      printf("TFTP Initialization failed\n\r");
   }
   printf("TFTP ports are live with above IP address\n\r");
   printf("If you wish to do the FAT FS commands then\n\r");
   printf("please enter any key to show menu\n\r");
   do
   {
      rx_size = MSS_UART_get_rx(&g_mss_uart0, &key, 1);
      if (rx_size)
      {
         show_menu();
         rx_size = 0;
      }
      PERIODIC(tcp_timer, TCP_TMR_INTERVAL, tcp_tmr());
      PERIODIC(arp_timer, ARP_TMR_INTERVAL, etharp_tmr());
      if(MSS_MAC_rx_pckt_size())
      {
         ethernetif_input(NULL);
      }
   }while( 1 );
   return 0;
}
