/* ------------------------------------------------------------------------------------------------ */
/* FILE :		Demo_110-113_STM_P407_ATOLLIC.c														*/
/*																									*/
/* CONTENTS :																						*/
/*				Demo for the Olimex STM32-P407 evaluation board (RS232_1 port)						*/
/*																									*/
/*				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														*/
/*																									*/
/*																									*/
/* 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.3 $																				*/
/*	$Date: 2014/04/28 21:32:17 $																	*/
/*																									*/
/* ------------------------------------------------------------------------------------------------ */

#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	168000000						/* Processor clock frequency					*/

#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))

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

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

USART_InitTypeDef USART_InitStructure;
extern FontType_t Terminal_9_12_6;

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


int G_TaskLed3off;

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

int  GetKey(void);
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										*/

	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);

	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			*/

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

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

	GLCD_PowerUpInit(NULL);
	GLCD_Backlight(BACKLIGHT_ON);
	DelayResolution100us(3000U);

	GLCD_SetFont(&Terminal_9_12_6, FG_COLOR, BG_COLOR);

	GLCD_SetWindow(0,0, GLCD_HORIZONTAL_SIZE-1, GLCD_VERTICAL_SIZE-1);
	GLCD_TextSetPos(0,0);
	GLCD_print("\f \r");

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

	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);
	STM_EVAL_PBInit(MY_BUTTON_3, BUTTON_MODE_GPIO);
	STM_EVAL_PBInit(MY_BUTTON_4, BUTTON_MODE_GPIO);
	STM_EVAL_PBInit(MY_BUTTON_5, BUTTON_MODE_GPIO);
	STM_EVAL_PBInit(MY_BUTTON_6, BUTTON_MODE_GPIO);

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

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

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

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

	for(;;);
}

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

void TaskMain(const void *Arg)
{
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	*/

	OSeint(1);

/* ------------------------------------------------ */
/* 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
	putchar('\n');
	DISPLAY(Line5, "Will use DHCP unless");
	DISPLAY(Line6, "key pressed on UART ");
	DISPLAY(Line7, " switch / joystick  ");
	LCD_LINE(Line9, &TimeMsg[0]);

/* ------------------------------------------------ */
/* 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[12] = '0' + LastWait;
			LCD_LINE(Line9, &TimeMsg[0]);
			printf("\r%s", &TimeMsg[0]);
		}
		G_IPnetStatic = GetKey()					/* Check if user pressed a key					*/
		              |	(Bit_SET   == STM_EVAL_PBGetState(BUTTON_WAKEUP))
		              |	(Bit_RESET == STM_EVAL_PBGetState(BUTTON_TAMPER));
	} while((ii < 5000)								/* Check for 5 seconds							*/
	  &&    (G_IPnetStatic == 0));					/* Or until a key is pressed					*/

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

	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(Line8);
	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(LED3);
		}
	}
}

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

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

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

void TIMcallBack(void)
{
	return;
}

/* ------------------------------------------------------------------------------------------------ */
/*																									*/
/* 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);
}

/* EOF */

