/* ------------------------------------------------------------------------------------------------ */
/* FILE :		Demo_10-13_CY5_A9_GCC.c																*/
/*																									*/
/* CONTENTS :																						*/
/*				Demo for the Zynq ZedBoard															*/
/*																									*/
/*				Demo #10 - Webserver using netconn with memory base file system						*/
/*				Demo #11 - Webserver using BSD sockets with memory base file system					*/
/*				Demo #12 - Webserver using netconn with MMC FatFS									*/
/*				Demo #13 - Webserver using BSD sockets with MMC FatFS								*/
/*																									*/
/*				Serial port settings:																*/
/*							Baud Rate: 115200														*/
/*							Data bits:      8														*/
/*							Stop bits:		1														*/
/*							Parity:      none														*/
/*							Flow Ctrl:   none														*/
/*							Emulation:   none														*/
/*																									*/
/*																									*/
/* Copyright (c) 2014, Code-Time Technologies Inc. All rights reserved.								*/
/*																									*/
/* Code-Time Technologies retains all right, title, and interest in and to this work				*/
/*																									*/
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS							*/
/* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF										*/
/* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL							*/
/* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR								*/
/* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,							*/
/* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR							*/
/* OTHER DEALINGS IN THE SOFTWARE.																	*/
/*																									*/
/*																									*/
/*	$Revision: 1.10 $																				*/
/*	$Date: 2014/03/12 16:59:36 $																	*/
/*																									*/
/* ------------------------------------------------------------------------------------------------ */

#if (((OS_DEMO) < 10) || ((OS_DEMO) > 13))
	#error "Wrong OS_DEMO value" 
#endif

#include "WebServer.h"
#include "xparameters.h"
#include "xuartps_hw.h"

/* ------------------------------------------------ */

#define BAUDRATE	115200							/* Serial port baud rate						*/
#define SYS_FREQ	666666667						/* Processor clock frequency: 666 MHz			*/

#define DHCP_TASK_PRIO   	(OX_PRIO_MIN-1)			/* Priority of the DHCP task					*/
#define LED_TASK_PRIO    	(OX_PRIO_MIN-1)			/* Priority of the LED flashing task			*/

#define USE_FAT_FS	(((OS_DEMO)==12)||((OS_DEMO)==13))
#define USE_SOCKET	(((OS_DEMO)==11)||((OS_DEMO)==13))

/* ------------------------------------------------ */

#if (USE_FAT_FS)
  DIR      g_Dir;
  FATFS    g_FileSys;
#endif

XGpio G_GpioButton;									/* Buttons gpio descriptor						*/
XGpio G_GpioLed;									/* LEDs gpio descriptor							*/
XGpio G_GpioSwitch;									/* Switches gpio descriptor						*/

/* ------------------------------------------------ */

int  GetKey(void);									/* Non-blocking keyboard input					*/
void EMACintHndl(void);								/* Emac interrupt, call XEmacsPS with argument	*/
extern void XEmacPs_IntrHandler(void *XEmacPsPtr);	/* Xilinxs EMAC interrupt handler				*/
int  __putchar(int);
void TIMERinit(unsigned int Reload);
void TaskLed7(void);

/* ------------------------------------------------------------------------------------------------ */

int main(void)
{
int  ii;											/* General purpose								*/
int  LastWait;										/* Last elapse time (to update display)			*/
char TimeMsg[] = "  DHCP in 5s.     ";				/* Message line to refresh every seconds		*/
int  WaitTime;										/* Elapsed time waiting for key pressed			*/

/* ------------------------------------------------ */
/* UART set-up										*/

	setvbuf(stdin,  NULL, _IONBF, 0);				/* By default, Newlib library flush the I/O		*/
	setvbuf(stdout, NULL, _IONBF, 0);				/* buffer when full or when new-line			*/

	putchar('\r');
	putchar('\n');
	putchar('\r');
	putchar('\n');

	while (0 != GetKey());							/* Remove stuff left in the UART RX buffer		*/

/* ------------------------------------------------ */
/* Start Abassi										*/

	OSstart();

/* ------------------------------------------------ */
/* LED & switches setup								*/

	XGpio_Initialize(&G_GpioLed, XPAR_LED_DEVICE_ID);
	XGpio_SetDataDirection(&G_GpioLed, 1, 0);
	XGpio_DiscreteWrite(&G_GpioLed, 1, 0);			/* Turn off all the LEDs						*/

	XGpio_Initialize(&G_GpioButton, XPAR_BUTTON_DEVICE_ID);
	XGpio_SetDataDirection(&G_GpioButton, 1, 0xFFFFFFFF);

	XGpio_Initialize(&G_GpioSwitch, XPAR_SWITCH_DEVICE_ID);
	XGpio_SetDataDirection(&G_GpioSwitch, 1, 0xFFFFFFFF);

/* ------------------------------------------------ */
/* SysTick Set-up									*/

	OSisrInstall(29, TIMtick);						/* Install the OS timer tick function			*/
	TIMERinit(((((SYS_FREQ/2)/100000)*OS_TIMER_US)/(10)));
	GICenable(29, 128, 1);							/* Private timer interrupt ID is 29 prio=mid	*/

/* ------------------------------------------------ */
/* Attach the Ethernet interrupt handler			*/

	OSisrInstall(54, EMACintHndl);					/* Install the Ethernet interrupt				*/
	GICenable(54, 128, 1);							/* Enable the Ethernet interrupt				*/

/* ------------------------------------------------ */
/* MMC file system mounting							*/

  #if (USE_FAT_FS)
	MMCreset();
	OSisrInstall(56, MMCintHndl);					/* Install the MMC driver interrupt handler		*/
	GICenable(56, 128, 1);
  #endif

	OSeint(1);

/* ------------------------------------------------ */
/* Allow user selection static or dynamic address	*/

	puts("  lwIP  Webserver   ");
  #if (USE_SOCKET)
	puts("  with BSD sockets  ");
  #else
	puts("    with netconn    ");
  #endif
  #if (USE_FAT_FS)
	puts("   using MMC FAT FS ");
  #else
	puts("   using memory FS  ");
  #endif
	puts("Will use DHCP unless");
	puts("key pressed on UART ");
	puts(" or button pressed  ");

/* ------------------------------------------------ */
/* Default static Addresses & Mask					*/

	NetAddr_Init();

/* ------------------------------------------------ */
/* UART prompt and key pressed check				*/

	WaitTime = G_OStimCnt;
	LastWait = -1;
	do {
		ii = (1000*(G_OStimCnt-WaitTime))
		   / OS_TICK_PER_SEC;
		if (LastWait != (5999-ii)/1000) {
			LastWait = (5999-ii)/1000;
			TimeMsg[10] = '0' + LastWait;
			printf("\r%s", &TimeMsg[0]);
		}

		G_IPnetStatic = GetKey()					/* Check if user pressed a key					*/
		              | (0 != BUTTON_ALL());		/* or a press button							*/
	} while((ii < 5000)								/* Check for 5 seconds							*/
	  &&    (G_IPnetStatic == 0));					/* Or until a key is pressed					*/

	printf("\r                             \r\n");	/* Erase the remaining time from UART screen	*/


/* ------------------------------------------------ */
/* EMAC & lwIP initialization						*/

	LwIP_Init();
	http_server_init();


/* ------------------------------------------------ */
/* DHCP task creation								*/

	if (G_IPnetStatic == 0) {						/* If static address requested, DHCP not needed	*/
		TSKcreate("DHCP Client", DHCP_TASK_PRIO, 4096, LwIP_DHCP_task, 1);
	}

	TSKcreate("LED 7", LED_TASK_PRIO, 2048, TaskLed7, 1);

  #if ((OX_EVENTS) != 0)
	EVTwait(3, 0, -1);								/* Wait for Ethernet & file system to be ready	*/
  #endif

	MTXlock(G_OSmutex, -1);
	puts("The Webserver is ready");
	MTXunlock(G_OSmutex);

	for( ;; ) {
		TSKselfSusp();
	}
}

/* ------------------------------------------------------------------------------------------------ */

void TaskLed7(void)
{
int Toggle;

	Toggle = 0;
	for( ;; ) {
		if(Toggle == 0) {
			LED_OFF(MY_LED_7);
		}
		else {
			LED_ON(MY_LED_7);
		}
		Toggle = !Toggle;
		TSKsleep(OS_MS_TO_TICK(250));
	}
}

/* ------------------------------------------------------------------------------------------------ */

void IdleTask(void)
{
	for(;;) {
		 __asm(" wfi");
	}
}

/* ------------------------------------------------------------------------------------------------ */

void TIMcallBack(void)
{
	return;
}

/* ------------------------------------------------------------------------------------------------ */

void EMACintHndl(void)
{
XScuGic_Config           *CfgPtr;
XScuGic_VectorTableEntry *TablePtr;
extern XScuGic_Config     XScuGic_ConfigTable[];

	CfgPtr   = &XScuGic_ConfigTable[0];
	TablePtr = &(CfgPtr->HandlerTable[54]);
	if (NULL != TablePtr->Handler) {
		TablePtr->Handler(TablePtr->CallBackRef);
	}

	return;
}

/* ------------------------------------------------------------------------------------------------ */
/* Private timer set-up																				*/
/* ------------------------------------------------------------------------------------------------ */

void TIMERinit(unsigned int Reload)
{

volatile unsigned int *TimReg;

	TimReg    = COREgetPeriph();					/* Private timer is at base of Peripherals		*/
	TimReg   += 0x600/sizeof(unsigned int);
	TimReg[2] = 0;									/* Disable timer & interrupts					*/
	TimReg[0] = Reload;								/* Private timer load value						*/
	TimReg[1] = Reload;								/* Start the count at reload value				*/
													/* Private timer control register				*/
	TimReg[2] = (0<<8)								/* Prescaler = /1								*/
	          | (1<<2)								/* Interrupt enable								*/
	          | (1<<1)								/* Auto-reload									*/
	          | (1<<0);								/* Timer enable									*/

	return;
}

/* ------------------------------------------------------------------------------------------------ */

int GetKey(void)
{
int RetVal;

	RetVal = 0;
	if (XUartPs_IsReceiveData(STDIN_BASEADDRESS)) {
		RetVal = XUartPs_RecvByte(STDIN_BASEADDRESS);
	}

	return(RetVal);
}

/* EOF */

