/************************************************************************/
/*  FILE        : main.c												*/
/*  DESCRIPTION : Main Program											*/
/*																		*/
/*																		*/
/************************************************************************/


#include "includes.h"


// povoleni WDT musi byt primo zapisem do FLASH na adresu 0xffdb
const long OFS2 __attribute__ ((section (".ofs2"))) = 0x0F000000;	

tUChar ramBuffer[RAM_BUFFER_SIZE];	// globalni buffer
													
extern tsTitle		cfgstitle;		// prostor v RAM pro strukturu TITLE 
extern tsConstant 	cfgsystem; 		// prostor v RAM pro strukturu CONSTANT 

//unsigned long userAppAddr;   // obsahuje adresu zacatku USER APLIKACE

 
/****************************************************************************************************************
*	Variables
****************************************************************************************************************/
/*
 A p p l i c a t i o n    C o n t r o l l    B l o c k
In application cotroll block are storage informations about system status. The structure contain
information about system errores, cycles of timers, RS232(485) buffers, display etc.
*/
tsAppCB			 appCB;		// application control block
tsEEPROM		 EEPROM;		// pristup a mapovani EEPROM
tsOPER			 OPER;		// operacni globalni provenne uchovavane v EEPROM
tsEDK 			 EDK;
tsPOW 			 POW;
//tsHWconfig		 HWconfig;
tsRD3_packet	 RD3_packet;


// nutno mapovat do sdilene oblasti kvuli predavani parametru
__attribute__ ((section (".shared"))) 
tsBOOTLOADER	 BOOT;


// globani promena
extern tUChar gDataType[MAX_MESSAGE_LEN-SYS_HEADER_LEN-2];		// uchovava datovy obsah pro zpracovani DLL, RDI

// *************************************************************************
// Seznam dostupnych funci pro dany typ zarizeni pro volani z fronty uloh
// kody funkci jsou definovany jako "REQUIREMENTS AND TASKS" v main.h
// *************************************************************************
   const pFunc function[] = 
	{
	  EmptyFunc,			// 0 - prazdna funkce

// systemove funkce zarizeni
	  ResetService,			// 1 - reset jednotky podle nastaveni BootMode
      GpioService,			// 2 - obsluha lokalnich IO
	  AdcService,			// 3 - obsluha analogovych vstupu
	  DipService,			// 4 - obsluha DIP prepinace	
	  ReadCardId,			// 5 - cteni ID karty
	  EdkBusTimer,			// 6 - volani funkce BusTimer
	  SyncOutput,			// 7 - generuje synchronizacni signal 
	  CheckOpto,			// 8 - detekce optozavory
	  ReadDIP,				// 9 - nacitani DIP prepinace	  	  

// API funkce GILD protokolu
	  AckSciMessage,			// 10 - Odeslani ACK paketu pres seriovou linku
	  ProcessExtData,			// 11 - Obsluha prichozich dat o zmenach stavu v systemu, vstupy i vystupy z jinych jednotek. taky cteni karty na cteckach
	  StvSciMessage,			// 12 - Odeslani SYS_DATA_INF paketu pres seriovou linku
	  ReaderSciMessage,			// 13 - Odeslani paketu SYS_STATE_READER 
	  ChangeSciMessage,			// 14 - Odeslani paketu SYS_STATE_ChANGE
	  StateSciMessage,			// 15 - Odeslani paketu SYS_STATE_INFO
	  ErrorSciMessage,			// 16 - Odeslani paketu SYS_STATE_ERROR
	  MeasureSciMessage, 		// 17 - Odeslani paketu SYS_STATE_MEASURE
	  InfoSciMessage,		 	// 18 - Odeslani SYS_MESSSAGE_INFO pres seriovou linku
	  DllSciMessage,		  	// 19 - 
	  CfgSciMessage,			// 20 - odeslani SYS_DATA_CFG
	};



// *************************************************************************
// A r r a y    o f    r e q u i r e m e n t s ( t a s k s )
// *************************************************************************
/*
Variable reqBuffer[XY] contain information about requirement from system or service. 
The first 4 bit signed number priority of requirement. (4 level of task priority)
In the other 12 bit is coded number of requirement = 4096 possibility of requirement

| PRIORITY_BIT_3 | PRIORITY_BIT_2 | PRIORITY_BIT_1 | PRIORITY_BIT_0 | R_BIT_11 | R_BIT_10 | R_BIT_9 | R_BIT_8 |
| R_BIT_7 | R_BIT_6 | R_BIT_5 | R_BIT_4 | R_BIT_3 | R_BIT_2 | R_BIT_1 | R_BIT_0 |
	
The maximum number of requirement which can stay in the front is given by macro MAX_REQ
*/
tsReq reqBuffer[MAX_REQ+1]; // requirements buffer




/*****************************************************************************************************************
*	HW_Start
*
*****************************************************************************************************************/
int HW_Start (void)
{
// ctecky ADC prevodnik pouzivaji jen na nacteni JUMPERU	
	#ifdef CORE_EDK													
      Init_ADC(ADC_PORT_0, ADC_MODE_ONE_SHOT, ADC_NO_SWEEP, ADC_NO_INT);	// vychozi nastaceni one-shot pro osahani JUMPERU		

	#ifndef GR_EXT8
	  ReadConfigJumpers();													// nacte konfiguracni propojky urcujici funkci ctecky
    #endif
																				// prepnuti na ADC na periodicke mereni AN10 - vstupni napeti 12V VIN
	  Init_ADC(ADC_PORT_1, ADC_MODE_REPEAT_0, ADC_NO_SWEEP, ADC_INT);		
	  adinsel.byte = (adinsel.byte & 0xF0) | AN_CH2;						// set channel AN10 (8+2)
	#endif

// zroj POW inicializuje ADC pro trvale mereni na portu 1
	#ifdef CORE_POW													
      Init_ADC(ADC_PORT_1, ADC_MODE_REPEAT_SWEEP, ADC_SWEEP_4PIN, ADC_INT);	
	#endif
	
	
	InitGPIO();	

	IRQ_Init();

// prozatim pro POW neobsluhovat linku
#ifndef CORE_POW		
	SCI_Init();
#endif

//	WDT_Init(WDT_HARD_RESET);
	WDT_Init(WDT_SOFT_RESET);
}



/*****************************************************************************************************************
*	m a i n
*
*
* The main function contain the initialization of MCU, APP and cover main loop also
*
*****************************************************************************************************************/
int main(void);
int main(void)
{
  char temp;
  tUInt status;
  char *ptr8;

	ALL_InterruptDisable;

	HW_Start();    

  //----------------------------------------------------------------------------
  // zatim se nebudou zpravovavat zadne udalosti dokud neprobehne inicializace
	appCB.mode = 0;
	appCB.mode |= SYSBUSY_MASK;			// blokovat frontu uloh do provedeni inicializace HW
	appCB.mode |= UNIT_START_MODE;		// zmenit rezim na start po zapnuti, kvuli generovani paketu UNIT_START
	
	// blokovat odesilani measure paketu, do doby nez vsechny zarizeni na lince poslou UNIT_START
	EDK.sys_flag |= FLAG_BLOCK_MEASURE_PACKET;	

	// pro odeslani satvu sensoru po zapnuti
	EDK.sys_flag |= FLAG_AIO_FIRST_SEND;

  //----------------------------------------------------------------------------
  // inicializace timeru
	Init_Timer_Variables();		// inicializace promenych virt. casovacu

    Init_TimerA();          	// initialize timer
    
//    Init_TimerB();          	// initialize timer

	Init_TimerC();

  //----------------------------------------------------------------------------
	Init_HW_Specific_Variables();
	
	 
  #ifdef INTERFACE_RS		// inicializovat pouze pro variantu RS
  	DataInitVar();			// nutne volat az venku z InitMCU() jinak se vymaze ukazatel ve strukture hlavicky
  #endif


// pro ladeni zapisu SN z konzole
#ifdef DEBUG_WRITE_SN
 ClearDF(BLOCK_A);	
#endif

  



  #if defined CORE_EDK ||  defined CORE_POW	
    my_memset((unsigned char *)&cfgsystem, 0x00, (short)sizeof( tsConstant)); 
 	InitAPP();				// inicializuje S/n, popisky atd.. do dataflash, nacte pak do struktur v RAM
	InitConst(1);			// inicializace a vytvoreni MAC adresy, pokud je zapsano seriove cislo, pokud ne pouzije se default adresa
    CheckBootMode();		// volat az po nacteni constant z dataflash
  #endif

	 
	appCB.mode &= ~SYSBUSY_MASK;			// spustit normalni provadeni uloh REQ
		   
	//RX_InterruptEnable;

	Init_TimerE();							// timer E slouzi ke spousteni externiho WDT

  	ALL_InterruptEnable;

	// tohle ma smysl pouze pro EDK ctecky, nikoliv pro zdroj
	#ifdef CORE_EDK	
	
	#ifndef GR_EXT8
	  ReaderInit();									// inicializace cteciho cipu RFID + detekce jestli je pripojen EMMARIN (pripad teplomeru)
	  LED_test();									// po zapnuti kratce bliknou vsechny LED
	#endif

	
	//-----------------------------------------------------------------------------------------------------
	// tady nasleduje pripojovani mericich periferii, zatim mame napeti, teplotu, ale muzou byt dalsi.....
	AddVirtualModul(MODUL_VCC);						// pridat periferii jako modul, VCC je vzdy 
	       
	// inicializace merice teploty pokud je pripojen - zavede se do rovnez do tabulky jako modul	
	#ifndef GR_EXT8
	status = Init_DigitalThermometer();				// inicializace teplomeru
	if (status == NO_ERROR)							// detekovan teplomer? 
	 {											 	// pokud ano, tak nastavit bit identifikace HWSPEC_LOW
	   EDK.hwspec_low |= HWSPEC_LOW_TEMPERATURE;
	   appCB.sensor.first_sample = 1;				// nastavit flag prvni mereni

	   AddVirtualModul(MODUL_TEMP);					// pridat pripojenou periferii jako modul 
	 }
	else											// chyba nacteni teplotniho cidla
	 {												// pokud se jedna o variantu pouze teplomer, tak musi byt cislo pripojeno
	   // hlasit jen pro typ ETS4
	   if (EDK.hwspec_low &	HWSPEC_LOW_TEMPERATURE)	// pokud pripojeno neni, tak se jedna o chzbu a nutno to hlasit 
	    {
		  appCB.sensor.presence_error = 1;			// zajisti odeslani paketu ERROR, ale az po startu jednotky
	    }
	 }
	#endif
	
	// nacteni ulozene konfigurace inputTable z dataFlash
	Read_InputConfig();
	//-----------------------------------------------------------------------------------------------------
	#endif

  RX_InterruptEnable;
	



#if defined DEMO_REZIM
  EDK.sys_flag |= FLAG_OFFLINE_MODE;	
#endif





		  
//************************************************************//
// H L A V N I   A P L I K A C N I  S M Y C K A
//************************************************************//

  for EVER // main loop
   {
	 ClearWDT();
	
// virtualni citace zakladaji pozadavky do fronty uloh, nelze provadet v interruptu 
	TimerA_Application();	

// -----------------------------------------------------------------
// obsluha dat ze seriove linky
// musi probihat co nejrychlej aby nedoslo k preplneni prijimaciho buferu
	ParseSciRxData();
	
// -----------------------------------------------------------------
// zpracovani udalosti ulozenych pozadavku v REQbufer
// tato smycka musi reagovat v real-timu, ma zasadni vliv na celkové plneni reg_bufferu.
			
	if( !(appCB.mode&SYSBUSY_MASK) ) 				// system busy - neprovadet obsluhu fronty uloh
 	 {
	FindHighPriReq();		// number of high priority task in front is storage in appCB.task
			
	if (reqBuffer[appCB.task].requirement) // looking for the highest priority requirement
	 {
		if ((reqBuffer[appCB.task].requirement & TASK_MASK) < NUM_OF_FUNC) 
	 	 {
		   //  appCB.error = 0;
		   (*function [reqBuffer[appCB.task].requirement & TASK_MASK ] ) ();	// when found some requirement done it				
		   ClearWDT();
		 }
	    else
	     {
		   appCB.error = ERR_TASK_MISMATCH;
		   while (1);					// vyvola SWReset
		 }

//	    RemReq(appCB.task);	// remove reuirement when done
	    RemReq(reqBuffer[appCB.task].requirement);	// remove reuirement
	}

	if (appCB.error)	// when some error was generated
			  ErrorService();	// do the error service
	 
	 }	// KONEC if( !(appCB.mode&SYSBUSY_MASK)



// -----------------------------------------------------------------
// osetreni pro klid na lince, ored nastavenim je nutne odeslat ACK
// -----------------------------------------------------------------
	if (EDK.sys_flag & FLAG_ACK_BUS_QUIET)
	{
 	  EDK.sys_flag &= ~FLAG_ACK_BUS_QUIET;	// smazat pomocny flag
	  BusControl.BusState |= BUS_QUIET;		// nastavit BUS_QUIET
	}
									 

// -----------------------------------------------------------------
// osetreni systemovych chyb 		
// -----------------------------------------------------------------
	if (appCB.error)	
	  {
		ErrorService();				// do the error service
	  }

   } 	// end of for EVER


}	// end of main()

