/****************************************************************************
	Startovaci aplikace. Ukolem je provest inicializaci vsech aplikaci v OS
	a zinicializovat spojeni s WiFi modulem. 

*****************************************************************************/
#include "Applications.h"
#include "OS.h"
#include "stdafx.h"
#include "Drivers.h"
#include "GLCD.h"

#define WIFI_RESPOND_DELAY 5000				//Maximalni cas pro odpoved modulu

/****************************************************************************
	Makro pro osetreni prechodu mezi stavy wifi modulu 

*****************************************************************************/
#define SWS_WAIT_FOR_FINISH()	if (WifiBusy() == YES)\
								{\
                                  protectStamp = GetTimeStamp();\
                                  LedOn(LED_4);\
                                  if (GetElapsedTime(wifiStartupStamp) > WIFI_RESPOND_DELAY)\
                                  {\
                                    startUpWifiState = SWS_FAILURE;\
                                    myConnectionState = CONNECTION_ERROR;\
                                  }\
                                  break;\
								}\
								if (WifiOK() == NO)\
								{\
                                  LedOff(LED_4);\
                                  startUpWifiState = SWS_FAILURE;\
                                  myConnectionState = CONNECTION_ERROR;\
                                  DebugOut("ERROR\r\n");\
                                  break;\
								}\
                                if (GetElapsedTime(protectStamp) < 100)\
                                  break;\
                                LedOff(LED_4);\
                                wifiStartupStamp = GetTimeStamp();\
								DebugOut("OK\r\n"); 


STARTUP_STATE startUpState = STARTUP_APPLICATIONS;		//stav aplikace

STARTUP_WIFI_STATE startUpWifiState = SWS_WIFI_FRESH;	//stav wifi modulu

char establishAttempsCounter = 0;						//pocitadlo neuspesnych pokusu

char attempsCounter = 0;								//druhe pocitadlo pokusu

TIME_STAMP wifiStartupStamp;							//casova znamka pro zjisteni uplynuteho casu

static TIME_STAMP protectStamp;							//Ochranna casova znamka pro lepsi casove oddeleni dvou prikazu pro modul

/****************************************************************************
	Funkce posle vsem aplikacim v OS prikaz k inicializaci

	Vstup: 
		neni

	Vystup
		neni

*****************************************************************************/
void InitApplications(void)
{
	SendTaskMessage(KEYBOARD,&DEFAULT_MSG_INIT);				//Klavesnice
	SendTaskMessage(MAIN_MENU,&DEFAULT_MSG_INIT);				//Hlavni menu
	SendTaskMessage(STATUS_BAR,&DEFAULT_MSG_INIT);				//Stavovy panel
	SendTaskMessage(CONSOLE,&DEFAULT_MSG_INIT);					//Konzole
	SendTaskMessage(DIALOG,&DEFAULT_MSG_INIT);					//Spravce dialogu
	SendTaskMessage(SPECIALS,&DEFAULT_MSG_INIT);				//Specialni klavesnice
	SendTaskMessage(NET_SETUP,&DEFAULT_MSG_INIT);				//Manazer nastaveni site
	SendTaskMessage(NETWORK_NAMES,&DEFAULT_MSG_INIT);			//Detektor okolnich siti
	SendTaskMessage(CONNECTOR,&DEFAULT_MSG_INIT);				//Spravce pripojeni
	SendTaskMessage(DESKTOP,&DEFAULT_MSG_INIT);					//Plocha+touchpad
	SendTaskMessage(ABOUT,&DEFAULT_MSG_INIT);					//About aplikace
	SendTaskMessage(TIME_SETUP,&DEFAULT_MSG_INIT);				//Nastaveni casu
	SendTaskMessage(SERIAL_SETUP,&DEFAULT_MSG_INIT);			//Nastaveni seriove linky
	SendTaskMessage(BACKLIGHT_SETUP,&DEFAULT_MSG_INIT);			//Nastaveni podsvetleni
}

/****************************************************************************
	Spusteni OS

	Vstup: 
		neni

	Vystup
		neni

*****************************************************************************/
void StartOS(void)
{
	SendTaskMessage(MAIN_MENU,&DEFAULT_MSG_RUN);
}

/****************************************************************************
	Stavovy automat pro korektni nastartovani a zinicializovani wifi modulu

	Vstup: 
		neni

	Vystup
		neni

*****************************************************************************/
void StartWiFi(void)
{
	switch(startUpWifiState)
	{
	case SWS_WIFI_FRESH:
		DebugOut("Starting module...");
        wifiStartupStamp = GetTimeStamp();					//ziskani casove znamky
		myConnectionState = CONNECTION_DISCONNECTED;		//nastaveni stavu pripojeni
		WifiSendCommand(DRV_WIFI_TEST);						//odeslani prikazu ke zjisteni stavu modulu
		startUpWifiState = SWS_TEST_CONNECTION;				//prechod do dalsiho stavu
		break;
	case SWS_TEST_CONNECTION:
		if (WifiBusy() == YES)								//Pokud je modul zaneprazdnen
		{	if (GetElapsedTime(wifiStartupStamp) > 1000)	//pokud je zaneprazdnen moc dlouho
			{
				establishAttempsCounter++;					//Inkrementuj citac pokusu
				if (establishAttempsCounter <= 5)			//pokud nedosahl maximalni hodnoty
				{
					WifiSendCommand((unsigned char*) "+++");//Posli prikaz k ukonceni SerialNet modu
					wifiStartupStamp = GetTimeStamp();		//Vyzvedni novou casovou znamku
				}
				else										//jinak
				{
					startUpWifiState = SWS_FAILURE;			//selhani modulu
					myConnectionState = CONNECTION_ERROR;	//chyba spojeni
				}
			}
			break;
		}
		if (WifiOK() == NO)									//Pokud neni wifi v poradku
		{
			if (attempsCounter++ < 3)						//inkrementuj pocitadlo
			{
				startUpWifiState = SWS_WIFI_FRESH;			//a pokus se znovu navazat spojeni
			}
			else											//jinak
			{
				startUpWifiState = SWS_FAILURE;				//selhani modulu
				myConnectionState = CONNECTION_ERROR;		//chyba spojeni
			}
			break;
		}
		DebugOut("OK\r");
		wifiStartupStamp = GetTimeStamp();					//Nova casova znamka
		WifiSendCommand(DRV_WIFI_ECHO_OFF);					//Odesli prikaz k vypnuti echa
		startUpWifiState = SWS_ECHO;						//prejdi do dalsiho stavu
		break;
	case SWS_ECHO:		
		SWS_WAIT_FOR_FINISH();								//vyckej na dokonceni prikazu
		WifiSendCommand(DRV_WIFI_GET_RECENT);				//Odesli prikaz ke zjisteni stavu pripojeni
		startUpWifiState = SWS_GET_RECENT;					//prejdi do dalsiho stavu
		break;
	case SWS_GET_RECENT:
		SWS_WAIT_FOR_FINISH();								//Cekej na dokonceni
		if (wifiBuffer[0] == 'I' && wifiBuffer[1] == '/')	//otestuj prvni bajty v bufferu
		{
			
			myConnectionState = CONNECTION_DISCONNECTED;	//sit neni pripojena
		}
		else
		{
			char i = 0;										
			while(wifiBuffer[i] != ',')						//nacti z vraceneho prikazu nazev site
			{
				mySSID[i] = wifiBuffer[i];					
				i++;
			}
			myConnectionState = CONNECTION_CONNECTED;		//Nastav stav pripojeni na PRIPOJEN
			
		}
		startUpWifiState = SWS_PASSED;						//Prejdi do dalsiho stavu
		break;
	case SWS_FAILURE:
                LedOff(LED_4);								//Selhani modulu
		break;
	case SWS_PASSED:
                LedOff(LED_4);								//Uspech
		break;
	}
}

TIME_STAMP hardwareStart;									//zpozdeni pro ustaleni hardwaru


/****************************************************************************
	Ridici smycka startovaci aplikace

	Vstup: 
		neni

	Vystup
		neni

*****************************************************************************/
void StartUpDriver(void)
{
	switch(startUpState)
	{
	case STARTUP_APPLICATIONS:
		LCD_printf((unsigned char*)"Starting applications...");
		InitApplications();										//Inicializace aplikaci
		startUpState = STARTUP_HARDWARE;						//prechod do dalsiho stavu
		LCD_printf((unsigned char*)"OK\r");
		LCD_printf((unsigned char*)"Starting hardware...");

		hardwareStart = GetTimeStamp();							//Vyzvednuti casove znamky pro zpozdeni

		break;
	case STARTUP_HARDWARE:
		if (GetElapsedTime(hardwareStart) < 1000)				//Zpozdeni 1s
		{
			break;
		}
		startUpState = STARTUP_WIFI;							//Prechod do dalsiho stavu
		LCD_printf((unsigned char*)"OK\r");
		LCD_printf((unsigned char*)"Starting Wifi...");
		break;
	case STARTUP_WIFI:
		StartWiFi();											//Start wifi modulu
		if (startUpWifiState == SWS_PASSED)
		{
			LCD_printf((unsigned char*)"OK\r");
			startUpState = STARTUP_OS;							//Prechod do dalsiho stavu
		}
		if (startUpWifiState == SWS_FAILURE)
		{
			LCD_printf((unsigned char*)"ERROR\r");
			startUpState = STARTUP_OS;							//Prechod do dalsiho stavu
		}
		
		break;
	case STARTUP_OS:
		LCD_printf((unsigned char*)"Starting OS...");
		StartOS();												//Spusteni menu
		startUpState = STARTUP_COMPLETE;						//Prechod do dalsiho stavu
		break;
	case STARTUP_COMPLETE:
		
		break;
	}
}