/* ------------------------------------------------------------------------------------------------ */
/* FILE :		Demo_110-113_STM3220G_ATOLLIC.c															*/
/*																									*/
/* CONTENTS :																						*/
/*				Demo for the ST microelectronics STM3220G evaluation board							*/
/*																									*/
/*				Compared to Demos #10->13, Demos #110->113 use the CMSIS OS API						*/
/*																									*/
/*				Demo #110 - Webserver using netconn with memory base file system					*/
/*				Demo #111 - Webserver using BSD sockets with memory base file system				*/
/*				Demo #112 - Webserver using netconn with micro-SD FatFS								*/
/*				Demo #113 - Webserver using BSD sockets with micro-SD FatFS							*/
/*																									*/
/*				Serial port settings:																*/
/*							Baud Rate: 115200														*/
/*							Data bits:      8														*/
/*							Stop bits:      1														*/
/*							Parity:      none														*/
/*							Flow Ctrl:   none														*/
/*							Emulation:   none														*/
/*																									*/
/*				For demo #12 and #13:																*/
/*				*** serial port cannot be used														*/
/*					Because the UART shares the same pins as the SD/MMC card cage, it is not		*/
/*					possible to use the UART.  So, the demo needs to operate through semi-hosting.	*/
/*					The terminal I/O is used as it is the input/output for semi-hosting.			*/
/*					In the Debug environment, pull down the "View: tab and select "Terminal I/O".	*/
/*					Keep the default settings of the terminal I/O.									*/
/*																									*/
/*																									*/
/* Copyright (c) 2013-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.3 $																				*/
/*	$Date: 2014/04/28 21:32:15 $																	*/
/*																									*/
/* ------------------------------------------------------------------------------------------------ */

#if (((OS_DEMO) < 110) || ((OS_DEMO) > 113))
	#error "Wrong OS_DEMO value" 
#endif

#include "WebServer.h"

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

#define BAUDRATE			   115200				/* Serial port baud rate						*/
#define SYS_FREQ			120000000				/* Processor clock frequency					*/

#define BG_COLOR			(((0xFC>>3)<<11)|((0x39>>2)<<5)|(0x02>>3))
#define FG_COLOR			LCD_COLOR_BLACK

#define DHCP_TASK_PRIO   	osPriorityNormal		/* Priority of the DHCP task					*/
#define LED_TASK_PRIO    	osPriorityLow			/* Priority of the LED flashing task			*/

#define USE_FAT_FS	(((OS_DEMO)==112)||((OS_DEMO)==113))
#define USE_SOCKET	(((OS_DEMO)==111)||((OS_DEMO)==113))
#define USE_UART	(!(USE_FATFS))

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

extern   u32_t G_IPnetDefGW;
extern   u32_t G_IPnetDefIP;
extern   u32_t G_IPnetDefNM;
extern   int   G_IPnetStatic;

USART_InitTypeDef USART_InitStructure;

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

int G_TaskLed3off;

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

int  GetKey(void);									/* Non-blocking keyboard input					*/
void TaskLed3(const void *Arg);
void TaskMain(const void *Arg);

extern void ETH_IRQHandler(void);					/* Ethernet I/F interrupt handler				*/
extern void EXTI15_10_IRQHandler(void);				/* Ethernet I/F interrupt handler				*/
extern void SD_ProcessDMAIRQ(void);					/* micro SD I/F interrupt handler				*/
extern void SD_ProcessIRQSrc(void);					/* micro SD I/F interrupt handler				*/

osThreadDef(LwIP_DHCP_task, DHCP_TASK_PRIO, 1, 2048);
osThreadDef(TaskLed3, LED_TASK_PRIO,  1, 1024);
osThreadDef(TaskMain, osPriorityRealtime, 1, 2048);

osThreadId G_TaskMainID;


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

int main(void)
{

/* ------------------------------------------------ */
/* Processor clock set-up							*/

	SystemInit();

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

  #if (USE_UART)
	USART_InitStructure.USART_BaudRate            = BAUDRATE;
	USART_InitStructure.USART_WordLength          = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits            = USART_StopBits_1;
	USART_InitStructure.USART_Parity              = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode                = USART_Mode_Rx | USART_Mode_Tx;

	STM_EVAL_COMInit(COM1, &USART_InitStructure);
  #endif

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

	puts("\n\n");

/* ------------------------------------------------ */
/* LCD set-up										*/

	STM322xG_LCD_Init();
	LCD_Clear(BG_COLOR);
	LCD_SetColors(FG_COLOR, BG_COLOR);

	DISPLAY(Line0, " Abassi/CMSIS Demo ");

/* ------------------------------------------------ */
/* LEDs & push button set-up						*/

	STM_EVAL_LEDInit(MY_LED_0);
	STM_EVAL_LEDInit(MY_LED_1);
	STM_EVAL_LEDInit(MY_LED_2);
	STM_EVAL_LEDInit(MY_LED_3);

	if (IOE_Config() != IOE_OK) {
		DISPLAY(Line4, (uint8_t *)"IO Expander FAILED ");
		DISPLAY(Line5, (uint8_t *)" Please Reset the  ");
		DISPLAY(Line6, (uint8_t *)"   board and start ");
		DISPLAY(Line7, (uint8_t *)"    again          ");
		while(1);
	}

	STM_EVAL_PBInit(MY_BUTTON_0, BUTTON_MODE_GPIO);
	STM_EVAL_PBInit(MY_BUTTON_1, BUTTON_MODE_GPIO);
	STM_EVAL_PBInit(MY_BUTTON_2,    BUTTON_MODE_GPIO);

/* ------------------------------------------------ */
/* Start Abassi / CMSIS RTOS API					*/

	osKernelStart(osThread(TaskMain), (void *)1234);

	for(;;);
}

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

void TaskMain(const void *Arg)
{
char AddrTxt[32];									/* String to print the IP address				*/
int  ii;											/* General purpose								*/
int  LastWait;										/* Last elapse time (to update display)			*/
int  Prio = 0;										/* Priority of the timer tick interrupt			*/
int *TimerBase;										/* Systick timer registers base address			*/
char TimeMsg[] = "    DHCP in 5s.     ";			/* Message line to refresh every seconds		*/
int  WaitTime;										/* Elapsed time waiting for key pressed			*/

	G_TaskMainID  = osThreadGetId();				/* Needed by NetAddr.c and httpserver-xxxx.c	*/
	G_TaskLed3off = 0;								/* CGI_SSI controls the LEDs. No suspend in		*/
													/* CMSIS, so use a flag instead					*/
/* ------------------------------------------------ */
/* SysTick Set-up									*/

	TimerBase = (int *)0xE000E000;
	((volatile int *)0xE000Ed20)[0] = (((volatile int *)0xE000Ed20)[0] & 0x1FFFFFFF)
	                                |   ((Prio & 7) << 29);
	TimerBase[5] = (((SYS_FREQ/100000) * OS_TIMER_US)/10)-1;
	TimerBase[4] = 0x7;								/* internal clock / int & enable				*/

/* ------------------------------------------------ */
/* Attach the interrupt handlers					*/

	OSisrInstall(-1, TIMtick);						/* Install the OS timer tick function			*/
	OSisrInstall(61, ETH_IRQHandler);				/* Install the Ethernet interrupt				*/
	OSisrInstall(40, EXTI15_10_IRQHandler);			/* Install the I/O pin on Ethernet interrupt	*/

/* ------------------------------------------------ */
/* micro SD file system mounting					*/

  #if (USE_FAT_FS)
	OSisrInstall(49, SD_ProcessIRQSrc);				/* Install the micro SD interrupt				*/
	OSisrInstall(59, SD_ProcessDMAIRQ);				/* Install the micro SD DMA interrupt			*/

	if (FR_OK != f_mount(&g_FileSys, "0", 1)) {
		DISPLAY(Line5, "Cannot mount volume ");
		DISPLAY(Line6, "  on the micro SD   ");
		DISPLAY(Line8, "      Make sure     ");
		DISPLAY(Line9, " JP22 is not fitted ");
		for(;;);
	}

	if (FR_OK != f_opendir(&g_Dir, "/")) {
		DISPLAY(Line5, "Cannot mount volume ");
		DISPLAY(Line6, "  on the micro SD   ");
		DISPLAY(Line8, "      Make sure     ");
		DISPLAY(Line9, " JP22 is not fitted ");
		for(;;);
	}
 #endif

	OSeint(1);

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

	G_IPnetStatic = 0;								/* By default, use DHCP							*/
	G_IPnetDefIP  = IP4_INT32(IP_ADDR0,      IP_ADDR1,      IP_ADDR2,      IP_ADDR3);
	G_IPnetDefNM  = IP4_INT32(NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
	G_IPnetDefGW  = IP4_INT32(GATEWAY_ADDR0, GATEWAY_ADDR1, GATEWAY_ADDR2, GATEWAY_ADDR3);

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

	DISPLAY(Line1, "  lwIP  Webserver   ");
  #if (USE_SOCKET)
	DISPLAY(Line2, "  with BSD sockets  ");
  #else
	DISPLAY(Line2, "    with netconn    ");
  #endif
  #if (USE_FAT_FS)
	DISPLAY(Line3, "  using uSD FAT FS  ");
  #else
	DISPLAY(Line3, "   using memory FS  ");
  #endif
	DISPLAY(Line5, "Will use DHCP unless");
	DISPLAY(Line6, "key pressed on UART ");
	DISPLAY(Line7, " switch / joystick  ");
	DISPLAY(Line9, &TimeMsg[0]);

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

  #if (USE_UART)
	printf("\n\nDefault settings:\n");
	printf("IP address : "); PrtAddr(&AddrTxt[0], G_IPnetDefIP); puts(&AddrTxt[0]);
	printf("Net Mask   : "); PrtAddr(&AddrTxt[0], G_IPnetDefNM); puts(&AddrTxt[0]);
	printf("Gateway    : "); PrtAddr(&AddrTxt[0], G_IPnetDefGW); puts(&AddrTxt[0]);
	printf("\nType any key to use the static IP address\n\n");
  #endif
	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[12] = '0'+LastWait;
		  #if (USE_UART)
			printf("\r%s", &TimeMsg[0]);
		  #endif
			LCD_DisplayStringLine(Line9, (uint8_t*)&TimeMsg[0]);
		}
		G_IPnetStatic = GetKey()					/* Check if user pressed a key					*/
		              | (0 != STM_EVAL_PBGetState(BUTTON_WAKEUP))
		              | (0 == STM_EVAL_PBGetState(BUTTON_TAMPER))
		              | (0 == STM_EVAL_PBGetState(BUTTON_KEY))
		              | (0 != IOE_JoyStickGetState());
	} while((ii < 5000)								/* Check for 5 seconds							*/
	  &&    (G_IPnetStatic == 0));					/* Or until a key is pressed					*/
  #if (USE_UART)
	printf("\r                             \n");	/* Erase the remaining time from UART screen	*/
  #endif

	LCD_ClearLine(Line1);
	LCD_LINE(Line2, "  lwIP  Webserver   ");
  #if (USE_SOCKET)
	LCD_LINE(Line3, "  with BSD sockets  ");
  #else
	LCD_LINE(Line3, "    with netconn    ");
  #endif
  #if (USE_FAT_FS)
	LCD_LINE(Line4, "  using uSD FAT FS  ");
  #else
	LCD_LINE(Line4, "  using memory FS   ");
  #endif
	LCD_ClearLine(Line5);
	LCD_ClearLine(Line6);
	LCD_ClearLine(Line7);
	LCD_ClearLine(Line9);

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

	ETH_BSP_Config();
	LwIP_Init();
	http_server_init();

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

	if (G_IPnetStatic == 0) {
		osThreadCreate(osThread(LwIP_DHCP_task), NULL);
	}

	osThreadCreate(osThread(TaskLed3), NULL);

	osSignalWait(3, osWaitForever);					/* Wait for Ethernet & file system to be ready	*/

	osMutexWait(G_OSmutex, 0);
	puts("The Webserver is ready");
	osMutexRelease(G_OSmutex);

	for( ;; ) {
		osThreadTerminate(osThreadGetId());
	}
}

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

void TaskLed3(const void *Arg)
{
	Arg    = Arg;

	for( ;; ) {
		osDelay(250);
		if (G_TaskLed3off == 0) {
			STM_EVAL_LEDToggle(LED4);
		}
	}
}

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

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

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

void TIMcallBack(void)
{
	return;
}

#if (USE_UART)
/* ------------------------------------------------------------------------------------------------ */
/*																									*/
/* UART functions needed by the Peripheral library to access the UART								*/
/*																									*/
/* ------------------------------------------------------------------------------------------------ */

#if !defined(_write_r)
_ssize_t _write_r (struct _reent *rreenn, int fd, const void *vbuf, size_t len)
{
const char *buf;
int   size;

	size = len;
	buf  = vbuf;
	while (size > 0) {
		if (*buf == '\n') {
			while (USART_GetFlagStatus(EVAL_COM1, USART_FLAG_TXE) == RESET);
			USART_SendData(EVAL_COM1, '\r');
		}
		while (USART_GetFlagStatus(EVAL_COM1, USART_FLAG_TXE) == RESET);
		USART_SendData(EVAL_COM1, *buf);
		buf++;
		size--;
	}

	return(len);
}
#endif
/* ------------------------------------------------------------------------------------------------ */

#if !defined(_read_r)
_ssize_t  _read_r(struct _reent *rreenn, int fd, void *vbuf, size_t size)
{
int len;
char *buf;

	buf = vbuf;
	len = 1;
	while(USART_GetFlagStatus(EVAL_COM1, USART_FLAG_RXNE) == RESET);
	*buf = USART_ReceiveData(EVAL_COM1) & 0xFF;
	if(EVAL_COM1->SR & (USART_FLAG_ORE | USART_FLAG_PE | USART_FLAG_FE) ) {
		len = 0;
	}
	return(len);
}
#endif

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

int GetKey(void)
{
int RetVal;

	RetVal = 0;
	if (EVAL_COM1->SR & USART_FLAG_RXNE) {
		RetVal = 0xFF & USART_ReceiveData(EVAL_COM1);
	}

	return(RetVal);
}

#endif

/* EOF */
