/****************************************************************************
	Aplikace pro nastaveni seriove linky zarizeni.

*****************************************************************************/
#ifdef PCSIM
	#include "stdafx.h"
#endif

#include "Applications.h"
#include "GRAPHICS.h"
#include "OS.h"
#include "GLCD.h"
#include "Drivers.h"


TScreen SerialSetupScreen;													//Obrazovka aplikace
TScreenObject serialSetupScreenObjects[SERIAL_SETUP_OBJECT_COUNT];			//Objekty aplikace
TApplicationInternal SerialSetupInternal;									//Ridici objekt aplikace

/****************************************************************************
	Fonty aplikace

*****************************************************************************/
FONT SerialSetupDivisorFont = {RGB_CYAN,FONT_SMALL,RGB_DARK_GRAY};
FONT SerialSetupShowerFont = {RGB_BLUE,FONT_SMALL,RGB_LIGHT_GRAY};
FONT SerialSetupScreenFont = {RGB_CYAN,FONT_SMALL,RGB_DARK_BLUE};
FONT SerialSetupChngFont = {RGB_RED,FONT_SMALL,RGB_LIGHT_BLUE};

/****************************************************************************
	Parametry objektu

*****************************************************************************/
TScreenObjectParams SerialSetupParams = {SERIAL_SETUP_XC-SERIAL_SETUP_XA,SERIAL_SETUP_YC-SERIAL_SETUP_YA,&SerialSetupScreenFont};
TScreenObjectParams SerialSetupDivisorParams = {SERIAL_SETUP_DIVISOR_WIDTH,SERIAL_SETUP_DIVISOR_HEIGHT,&SerialSetupDivisorFont};
TScreenObjectParams SerialSetupShowFieldParams = {SERIAL_SETUP_SHOW_FIELD_WIDTH,SERIAL_SETUP_SHOW_FIELD_HEIGHT,&SerialSetupShowerFont};
TScreenObjectParams SerialSetupShowChngParams = {TIME_SETUP_SHOW_FIELD_WIDTH,TIME_SETUP_SHOW_FIELD_HEIGHT,&SerialSetupChngFont};
TScreenObjectParams SerialSetupShowFieldSmallParams = {TIME_SETUP_SHOW_FIELD_WIDTH,TIME_SETUP_SHOW_FIELD_HEIGHT,&SerialSetupShowerFont};

int SerialSetupResult = -1;											//Vysledek aplikace

int baudRates[5] = {9600, 19200, 38400, 57600, 115200};				//Seznam dovolenych rychlosti

char stopBits = 1;													//Pocet stop bitu

char *parityNames[] = {"N","L","N","S"};							//Typy parity - nazvy

SERIAL_PARITY parityBit = SERIAL_PARITY_NONE;						//Paritni bit

char baudIndex = 0;													//Vybrana rychlost

ANSWER serialSetupUnsavedChanges = NO;								//Ulozene zmeny...

#ifdef PCSIM
	unsigned char U3LCR = (SERIAL_PARITY_EVEN << 3)|(0<<2);			//Definice pro simulator
#endif


/****************************************************************************
	Akce prirazena tlacitku ukonceni

	Vstup: 
		obj:			instance objektu
		message:		parametr volani

	Vystup
		neni

*****************************************************************************/
void SerialSetupCallback(TScreenObject* obj ,OBJECT_MESSAGE message)
{
	SerialSetupInternal.State = SERIAL_SETUP_STOP;
}

void ReadSerialParams(void);			//Hlavicka funkce

/****************************************************************************
	Postovni schranka aplikace

	Vstup: 
		msg:			zprava

	Vystup
		neni

*****************************************************************************/
RESULT SSMsgBox(MESSAGE * msg)
{
	POSITION* tmpPosition = 0;
	int tmp = 0;
	switch (msg->msg)
	{
	case RUN:
		DebugOut("SerialSetup RUN command received.\n");
		if (SerialSetupInternal.State == SERIAL_SETUP_READY)					//Pokud je aplikace zinicializovana
		{
			SerialSetupResult = -1;												//Vysledek aplikace
			SerialSetupInternal.State = SERIAL_SETUP_RESTART;					//Pripravit aplikaci na spusteni
			serialSetupUnsavedChanges = NO;										//existuji neulozene zmeny
			ReadSerialParams();													//Precteni parametru seriove linky
			return PASSED;
		}
		DebugOut("SerialSetup could not be run.\n");
		return FAILED;
				
		break;
	case INIT:
		if (SerialSetupInternal.State == SERIAL_SETUP_NOT_INITIALIZED)			//Pokud neni aplikace inicializovana
		{
			DebugOut("SerialSetup INIT command received.\n");
			SerialSetupInternal.State = SERIAL_SETUP_INITIALIZE;				//Pripravit se na inicializaci
			return PASSED;
		}
		break;
	case GET_STATE:
		return (RESULT)SerialSetupInternal.State;								//Vraci stav aplikace
		break;
	case GET_RESULT:
		return (RESULT)SerialSetupResult;										//Vraci vysledek z aplikace
		break;
	case APP_CLICK:
		SerialSetupInternal.ClickPosition.isFresh = YES;						//Bylo prijato kliknuti pro aplikaci
		tmpPosition = (POSITION*)msg->data;										//zkopirovani pozice kliknuti
		SerialSetupInternal.ClickPosition.x = tmpPosition->x;
		SerialSetupInternal.ClickPosition.y = tmpPosition->y;
		DebugOut("SerialSetup click received.\n");
		return PASSED;
		break;
	default:
		break;
		
	}
	return FAILED;
}

/****************************************************************************
	Vykresleni objektu s komunikacni rychlosti

	Vstup: 
		obj:				instance objektu
		message:			parametr kresleni

	Vystup
		neni

*****************************************************************************/
void DrawSerialSetupBaudrate(TScreenObject* obj ,OBJECT_MESSAGE message)
{
	DrawButtonShape(obj,message);				//Vykresleni tvaru objektu
	LCD_Goto_XY(obj->x+7, obj->y-2);			//presun na pozici vypisu
	LCD_Set_Font_Size(FONT_MINIMAL);			//nastaveni velikosti fontu
	LCD_printf(obj->caption);					//vypis nadpisu
	LCD_Set_Font_Size(FONT_SMALL);				//nastaveni fontu
	switch(baudIndex)							//Podle aktualni rychlosti se presun na pozici v tlacitku a vypis rychlost
	{
	case 0:
		LCD_Goto_XY(obj->x+15, obj->y+15);
		break;
	case 1:
	case 2:
	case 3:
		LCD_Goto_XY(obj->x+10, obj->y+15);
		break;
	case 4:
		LCD_Goto_XY(obj->x+5, obj->y+15);
		break;
	

	}
	LCD_printf((unsigned char*)int2char(baudRates[baudIndex]));
	LCD_printf((unsigned char*)"bps");
}

/****************************************************************************
	Vykresleni objektu pro zobrazeni stop bitu a parity

	Vstup: 
		obj:				instance objektu
		message:			zprava

	Vystup
		neni

*****************************************************************************/
void DrawSerialSetupProps(TScreenObject* obj ,OBJECT_MESSAGE message)
{
	DrawDataButtonSkelet(obj,message);								//Vykresleni tvaru objektu
	switch(obj->id)
	{
	case SERIAL_SETUP_SHOW_STOPS:									
		LCD_Goto_XY(obj->x+22, obj->y+15);							//Stop bity
		LCD_printf((unsigned char*)int2char(stopBits));
		break;
	case SERIAL_SETUP_SHOW_PARITY:
		LCD_Goto_XY(obj->x+22, obj->y+15);							//Parita
		LCD_printf((unsigned char*)parityNames[parityBit]);			
		break;
	}
}

/****************************************************************************
	Vykresleni tlacitek se spikami

	Vstup:
		obj:			instance objektu
		message:		parametr kresleni

	Vystup
		neni

*****************************************************************************/
void DrawSerialSetupChangers(TScreenObject* obj ,OBJECT_MESSAGE message)
{
	DrawButtonShape(obj,message);			//Vykresleni tvaru
	switch (obj->id)
	{
	case SERIAL_SETUP_BAUDRATE_UP:
		LCD_Goto_XY(obj->x+40,obj->y+10);	//podle ID objektu - nahoru
		LCD_printf((unsigned char *)">");
		break;
	case SERIAL_SETUP_BAUDRATE_DOWN:
		LCD_Goto_XY(obj->x+10,obj->y+10);	//dolu
		LCD_printf((unsigned char *)"<");
		break;
	}
}


/****************************************************************************
	Odezvy tlacitek pro zmenu hodnoty

	Vstup: 
		obj:			instance objektu
		message:		parametr volani

	Vystup
		neni

*****************************************************************************/
void SerialSetupChangersCallback(TScreenObject* obj ,OBJECT_MESSAGE message)
{
	serialSetupUnsavedChanges = YES;					//vznikaji neulozene zmeny
	switch (obj->id)
	{
	case SERIAL_SETUP_BAUDRATE_UP:
		baudIndex = (baudIndex >= 4?0:baudIndex+1);		//posun v poli komunikacnich rychlosti nahoru
		
		break;
	case SERIAL_SETUP_BAUDRATE_DOWN:
		baudIndex = (baudIndex <= 0?4:baudIndex-1);		//dolu
		
		break;
	}
	SerialSetupInternal.Screen->UpdateObject(SERIAL_SETUP_SHOW_BAUDRATE);		//Aktualizace
}

/****************************************************************************
	Odezvy tlacitek pro zmenu hodnoty

	Vstup: 
		obj:			instance objektu
		message:		parametr volani

	Vystup
		neni

*****************************************************************************/
void SerialSetupStopParityCallback(TScreenObject* obj ,OBJECT_MESSAGE message)
{
	serialSetupUnsavedChanges = YES;
	switch(obj->id)
	{
	case SERIAL_SETUP_SHOW_PARITY:
		if (parityBit == SERIAL_PARITY_ODD)
			parityBit = SERIAL_PARITY_NONE;
		else
			parityBit = (SERIAL_PARITY)((char)parityBit+1);
		
		break;
	case SERIAL_SETUP_SHOW_STOPS:
		stopBits = (stopBits == 1?2:1);
		break;
	}
	SerialSetupInternal.Screen->UpdateObject(obj->id);

}

/****************************************************************************
	Odezva ukoncovaciho tlacitka

	Vstup: 
		obj:			instance objektu
		message:		parametr volani

	Vystup
		neni

*****************************************************************************/
void serialSetupExitCallback(TScreenObject* obj ,OBJECT_MESSAGE message)
{

		SerialSetupInternal.State = TIME_SETUP_STOP;
}

/****************************************************************************
	Odezva ukladaciho tlacitka

	Vstup: 
		obj:			instance objektu
		message:		parametr volani

	Vystup
		neni

*****************************************************************************/
void SerialSetupSaveCallback(TScreenObject* obj ,OBJECT_MESSAGE message)
{
  UART3Initialize(baudRates[baudIndex],stopBits,parityBit);		//Nastavit UART
  SerialSetupInternal.State = SERIAL_SETUP_STOP;				//Ukoncit aplikaci
}


/****************************************************************************
	Inicializace aplikace

	Vstup: 
		neni

	Vystup
		neni

*****************************************************************************/
RESULT serialSetupInitialize(void)
{
	SerialSetupScreen.Init(SERIAL_SETUP_OBJECT_COUNT,serialSetupScreenObjects,&SerialSetupScreenFont,NO);			//Inicializace obrazovky
	
	SerialSetupInternal.Init(SERIAL_SETUP,SERIAL_SETUP_XA,SERIAL_SETUP_YA,SERIAL_SETUP_XC,SERIAL_SETUP_YC,&SerialSetupScreen,0,YES);	//Inicializace ridici struktury
	
	if (SerialSetupInternal.Screen == 0)
	{
		return FAILED;
	}

	/****************************************************************************
		Inicializace objektu

	*****************************************************************************/
	SerialSetupScreen.objects[SERIAL_SETUP_DIVISOR].Init(	SERIAL_SETUP_DIVISOR_LEFT,
															SERIAL_SETUP_DIVISOR_TOP,
															BACKGROUND,
															SERIAL_SETUP_DIVISOR,
															STR_SERIAL_SETUP_LONG,
															OBJECT_ENABLED,
															&SerialSetupDivisorParams,
															0,
															&DrawTextBoxShadowed);

	SerialSetupScreen.objects[SERIAL_SETUP_SHOW_BAUDRATE].Init( SERIAL_SETUP_DIVISOR_LEFT+SERIAL_SETUP_SHOW_FIELD_LEFT,
															SERIAL_SETUP_DIVISOR_TOP+25,
															BACKGROUND,
															SERIAL_SETUP_SHOW_BAUDRATE,
															(unsigned char*)"Bitrate:",
															OBJECT_ENABLED,
															&SerialSetupShowFieldParams,
															0,
															&DrawSerialSetupBaudrate);

	SerialSetupScreen.objects[SERIAL_SETUP_BAUDRATE_DOWN].Init( SERIAL_SETUP_DIVISOR_LEFT+SERIAL_SETUP_SHOW_FIELD_LEFT-SERIAL_SETUP_SHOW_FIELD_WIDTH/4,
															SERIAL_SETUP_DIVISOR_TOP+25,
															BUTTON,
															SERIAL_SETUP_BAUDRATE_DOWN,
															0,
															OBJECT_ENABLED,
															&SerialSetupShowChngParams,
															&SerialSetupChangersCallback,
															&DrawSerialSetupChangers);

		SerialSetupScreen.objects[SERIAL_SETUP_BAUDRATE_UP].Init( SERIAL_SETUP_DIVISOR_LEFT+SERIAL_SETUP_SHOW_FIELD_LEFT+3*SERIAL_SETUP_SHOW_FIELD_WIDTH/4,
															SERIAL_SETUP_DIVISOR_TOP+25,
															BUTTON,
															SERIAL_SETUP_BAUDRATE_UP,
															0,
															OBJECT_ENABLED,
															&SerialSetupShowChngParams,
															&SerialSetupChangersCallback,
															&DrawSerialSetupChangers);

		SerialSetupScreen.objects[SERIAL_SETUP_SHOW_STOPS].Init( SERIAL_SETUP_DIVISOR_LEFT+SERIAL_SETUP_SHOW_FIELD_LEFT+10*SERIAL_SETUP_SHOW_FIELD_WIDTH/6,
															SERIAL_SETUP_DIVISOR_TOP+25,
															BUTTON,
															SERIAL_SETUP_SHOW_STOPS,
															(unsigned char*)"Stops:",
															OBJECT_ENABLED,
															&SerialSetupShowFieldSmallParams,
															&SerialSetupStopParityCallback,
															&DrawSerialSetupProps);

		SerialSetupScreen.objects[SERIAL_SETUP_SHOW_PARITY].Init( SERIAL_SETUP_DIVISOR_LEFT+SERIAL_SETUP_SHOW_FIELD_LEFT+15*SERIAL_SETUP_SHOW_FIELD_WIDTH/6,
															SERIAL_SETUP_DIVISOR_TOP+25,
															BUTTON,
															SERIAL_SETUP_SHOW_PARITY,
															(unsigned char*)"Parity:",
															OBJECT_ENABLED,
															&SerialSetupShowFieldSmallParams,
															&SerialSetupStopParityCallback,
															&DrawSerialSetupProps);

		SerialSetupScreen.objects[SERIAL_SETUP_END].Init( SERIAL_SETUP_DIVISOR_LEFT+8*SERIAL_SETUP_DIVISOR_WIDTH/10-11,
															SERIAL_SETUP_DIVISOR_TOP+75,
															BUTTON,
															SERIAL_SETUP_END,
															STR_CANCEL,
															OBJECT_ENABLED,
															&PARAMS_BTN_CANCEL,
															&serialSetupExitCallback,
															&DrawButton);

		SerialSetupScreen.objects[SERIAL_SETUP_SAVE].Init( SERIAL_SETUP_DIVISOR_LEFT+SERIAL_SETUP_SHOW_FIELD_LEFT-SERIAL_SETUP_SHOW_FIELD_WIDTH/4,
															SERIAL_SETUP_DIVISOR_TOP+75,
															BUTTON,
															SERIAL_SETUP_SAVE,
															STR_SAVE,
															OBJECT_ENABLED,
															&PARAMS_BTN_OK,
															&SerialSetupSaveCallback,
															&DrawButton);
	return PASSED;
}

/****************************************************************************
	Nacteni parametru serioveho portu

	Vstup: 
		neni

	Vystup
		neni

*****************************************************************************/
void ReadSerialParams(void)
{
	unsigned char tmpLcr = U3LCR;
	stopBits = ((tmpLcr >> 2)&1)+1;
	parityBit = (SERIAL_PARITY)((tmpLcr >> 3)&7);
}

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

	Vstup: 
		neni

	Vystup
		neni

*****************************************************************************/
void AppSerialSetup(void)
{
	switch (SerialSetupInternal.State)
	{
	case SERIAL_SETUP_NOT_INITIALIZED:
		break;
	case SERIAL_SETUP_INITIALIZE:
		SerialSetupInternal.State = SERIAL_SETUP_READY;							//Prechod do dalsiho stavu
		if (serialSetupInitialize() !=PASSED)									//Inicializace aplikace
		{
			DebugOut("SerialSetup could not be initialized. Falling to error.\n");
			SerialSetupInternal.State = SERIAL_SETUP_ERROR;						//Neuspesna aplikace
			break;
		}
		DebugOut("SerialSetup initialized.\n");
		break;
	case SERIAL_SETUP_RESTART:
		SerialSetupInternal.Startup();											//Akce nezbytne pro start

		SerialSetupInternal.State = SERIAL_SETUP_DRAW;							//Prechod do dalsiho stavu
		break;
	case SERIAL_SETUP_DRAW:
		SerialSetupInternal.Screen->Draw();										//Vykresleni aplikace
		SerialSetupInternal.State = SERIAL_SETUP_ACTIVE;						//Prechod do dalsiho stavu
		break;
	case SERIAL_SETUP_ACTIVE:
		SerialSetupInternal.ProceedClick();										//Zpracovani dalsiho kliknuti
		break;
	case SERIAL_SETUP_WAITING:
		switch(SerialSetupInternal.TryToResume())								//Cekani na navrat ze spustene aplikace
		{
		case KEYBOARD:
			break;
		case DIALOG:
			if ((ANSWER)SendTaskMessage(DIALOG,&DEFAULT_MSG_GET_RESULT)==YES)	//Navrat z dialogu
			{

				SerialSetupInternal.State =SERIAL_SETUP_STOP;					//Pokud je odpoved ANO, ukonci
			}
			break;
		case NONE:
			break;
		default:
			DebugOut("Returned to SerialSetup from unknown application.\n");
			break;
		}
		break;
	case SERIAL_SETUP_READY:
		break;
	case SERIAL_SETUP_STOP:
		SerialSetupInternal.Stop();												//Akce nezbytne pro korektni ukonceni
		break;
	case SERIAL_SETUP_ERROR:
		break;
	default:
		break;
	}
}