/******************************************************************************
*	main_EDK.c
*
*   hlavni smycka rozdelovani udalosti pro zarizeni EDK
*
*******************************************************************************/

#include "includes.h"


extern tsEDK 		EDK;
extern tsAppCB  	appCB;
extern tsBOOTLOADER	BOOT;

tsCARD gCard;

	
/******************************************************************************
//	Init_HW_Specific_Variables
//
//  inicializace promenych podle typu zarizeni
******************************************************************************/
void Init_HW_Specific_Variables(void)
{
  EDK.output |= EDK_OUT_LED_RED;			// klidovy stav, sviti LED RED
  EDK.output &= ~EDK_OUT_BUZZER;			// Buzzer off
  
  #if defined INTERFACE_RS || defined INTERFACE_RD3
    saveLastLedState();						// nastavit default stav sviti cervena LED
  #endif

  EDK.input.state &= ~EDK_IN_CONFIG;		// konfiguracni propojka neaktivni  
  EDK.input.state &= ~EDK_IN_INPUT1;		// vstup IN1 neaktivni
  EDK.input.state &= ~EDK_IN_INPUT2;		// vstup IN2 neaktivni
  
  // GR_EXT8
  EDK.input.state &= ~EDK_IN_INPUT3;		// vstup IN3 neaktivni
  EDK.input.state &= ~EDK_IN_INPUT4;		// vstup IN4 neaktivni
  EDK.input.state &= ~EDK_IN_INPUT5;		// vstup IN5 neaktivni
  EDK.input.state &= ~EDK_IN_INPUT6;		// vstup IN6 neaktivni
  EDK.input.state &= ~EDK_IN_INPUT7;		// vstup IN7 neaktivni
  EDK.input.state &= ~EDK_IN_INPUT8;		// vstup IN8 neaktivni
         	
  EDK.input.lastState = EDK.input.state;	// zalohovat posledni stav

  EDK.counter.sync_out = SYNC_OUT_DIVIDER_PRESET;			// inicializace SYNC OUT
  EDK.counter.optocoupler = EDK_PRESET_OPTOCOUPLER_TIME;	// filtrace OPTOCOUPLER

  EDK.counter.input1 = EDK_PRESET_INPUT1_TIME;				// filtrace vstupu
  EDK.counter.input2 = EDK_PRESET_INPUT2_TIME;	
  
  // prvni mereni teplomeru odlozit az po startu systemu - bezpecny limit 
  EDK.counter.temperature_check_interval = EDK_TEMPERATURE_CHECK_TIME;

  // inicilaizovat interval odesilani zpravy SYS_MEASURE - bude nastaveno dale
  EDK.counter.temperature_send_interval = 0;

					  	
//  EDK.sys_flag |= FLAG_OFFLINE_LED;  		// indikovat offline rezim	
  



  #if defined ACS_NO_SYNCHRO
    EDK.sys_flag |= FLAG_READ_CARD;					// zmena hrany, povolit 1x nacist kartu
    EDK.sys_flag &= ~FLAG_SEND_EDK_PACKET;			// smazat flag zadost o odeslani
  #endif
   
   my_memset ((tUChar*)&gCard, 0, sizeof(gCard) );	// inicializoat celou strukturu gcard


}		
		


/************************************************************************************/
// AdcService - mereni ADC pro variantu EDK
// zpracovani analogovych vstupu - prepocet hodnot teplota/napeti/proud
// vlastni mereni ADC probiha na pozadi (interrupt _ad_converter() )
// !!Nepouzivat standartni matematicke operace v C, jinak compiler linkuje 12kB knihovnu!!
/************************************************************************************/
void AdcService(void)
{
  tULong temp;
  tULong temp2;
  tUInt  volt;

    #ifdef USE_VOLT
      appCB.adc.buffer[0] =  (ad2.word & 0x03ff);			// conversion result of AN10 - VIN
	
  	  // prepocet napajeciho napeti 
  	  temp = mul32(ConvertToVolts(appCB.adc.buffer[0]), VDIV_RATIO);
  	  temp = div32(temp,1000);
  	  temp += VDIV_CORR_VCC;
	  
	  temp = div32(temp,100);				// prevest na volty a zaokrouhlit na jedno desetine mmisto

  	  volt = temp;
	  EDK.sensor[SENSOR_VOLT].raw = (signed int)volt;
	  	  
     // Init_ADC(ADC_PORT_0, ADC_MODE_REPEAT_0, ADC_NO_SWEEP, ADC_INT);		
	 // adinsel.byte = (adinsel.byte & 0xF0) | AN_CH7;						// set channel AN7
    #endif
    
}



/************************************************************************************/
// TimerA_Application
/************************************************************************************/
void TimerA_Application(void)
{
   GUINTRECORD   PT_ADR;
   tUInt curState;
   tUInt dataType;
  
  
	// obsluha virtualniho casovace 100ms
   if (appCB.timer100ms.overflow)
    {
	  appCB.timer100ms.overflow = 0;

	//************************
	// citac delky svitu LED 
	//************************
  if (!(EDK.sys_flag & FLAG_BLOCK_LED_TIMER))
   {
     if (EDK.led.value && EDK.led.mask && EDK.counter.led_time)
      {
	    if (EDK.counter.led_time >1)				// rozliseni delky svitu LED na 100ms
	     {
		   if (EDK.led.value != 0xff)				// pokud je led.value 0xFF tak to znamena trvale sepnuti a citac nebezi
  	        {
  	          EDK.counter.led_time--;
		    }
	     }
        else if (EDK.counter.led_time==1) 		// citac vyprsel - provest jen 1x v posledni cyklu
	     {
	       EDK.counter.led_time--;				// dekrementovat do 0 aby se citac zastavil 
	       EDK.io_flag |= FLAG_LED_TIMEOUT;		// nastavit flag ze uplynul nastaveny interval
	     }
	  }
   }
	 
		 
	//************************
	// citac delky pipnuti
	//************************
//	  if (BUZZER_PIN_IS_ON)						// aktivace odpoctu casu podminena aktivaci piskace
//	   {
	     if (EDK.counter.buzzer_time > 1)		// rozliseni delky svitu LED na 100ms
	      {
  	        EDK.counter.buzzer_time--;
	      }
  	     else if (EDK.counter.buzzer_time == 1)	// citac vyprsel - provest jen 1x v posledni cyklu
	      {	
		    EDK.counter.buzzer_time--;			// dekrementovat do 0 aby se citac zastavil 
	        EDK.io_flag |= FLAG_BUZZER_TIMEOUT;	// nastavit flag ze uplynul nastaveny interval
	      }
//	   }

	//************************
	// citac delky sepnuti rele 
	//************************
	  if (EDK.counter.relay >1)					// rozliseni delky sepnuti rele na 100ms
	   {
  	     EDK.counter.relay--;
	   }
  	  else if (EDK.counter.relay==1) 			// citac delky sepnuti rele vyprsel - provest jen 1x v posledni cyklu
	   {
	     EDK.output &= ~EDK_OUT_RELAY;			// rele off
		 EDK.counter.relay--;					// dekrementovat do 0 aby se citac zastavil

 		#if defined  DEMO_REZIM					// soucasne s docasovanim rele inicializovat i LED
		 EDK.output &= ~EDK_OUT_LED_GRN;	
	     EDK.output |= EDK_OUT_LED_RED;	
		 GpioService();	
		#endif
		

		 // ukonceni rezimu FOLOW musi byt tady!
		#if defined INTERFACE_RS
  		 if (EDK.io_flag & FLAG_RED_FOLLOW_MODE)	// pokud LED_RED ma kopirovat stav rele
   		  {
	       EDK.io_flag &= ~FLAG_RED_FOLLOW_MODE;	// zrusit FOLLOW mode
		   RestoreIdleLedState();					// obnovit stav LED
   		  }

		 // ukonceni rezimu FOLOW musi byt tady!
  		 if (EDK.io_flag & FLAG_GRN_FOLLOW_MODE)	// pokud LED_GRN ma kopirovat stav rele
   		  {
	        EDK.io_flag &= ~FLAG_GRN_FOLLOW_MODE;	// zrusit FOLLOW mode
		    RestoreIdleLedState();					// obnovit stav LED
   		  }

		  // pouze pro variantu RS - generovat paket - vypnuto rele po docasovani
			 PT_ADR.X = 0x81;				// adresa 1.rele
			 curState = 0x00;				// rele vypnuto		
	 		 AddReq(PRIORITY_SYS_MESSAGE | ADD_MULTIPLE | PROCESS_SCI_STATE_CHANGE, curState, (tUInt *)&PT_ADR.X);	
		  #endif
	   }		// konec else if (EDK.counter.relay==1)
	   

		// osahani optozavory, interval je definovan v kroku 100ms x EDK_PRESET_OPTOCOUPLER_TIME
		// pozor u varianty EHS s teplomerem je nutne resit kolizi prostupu!
		  //#if !defined THERMO_DIGITAL
		    AddReq(PRIORITY_TASK_MID | PROCESS_OPTO_TAMPER, 0,0);	
		  //#endif
	
	}   // konec if (appCB.timer100ms.overflow)




	//************************************
	// obsluha virtualniho casovace 1sec
	//************************************
	if (appCB.timer1sec.overflow)
	 {
	    appCB.timer1sec.overflow = 0;
		appCB.cycles1sec++;						// univerzalni sekundovy citac 
		appCB.cycles200ms = 0;

		// rezim spusteni aplikace po zapnuti
		if (appCB.mode & UNIT_START_MODE)		
		 {
		   if (appCB.cycles1sec >= PRESET_UNIT_START_DELAY)								// pockat na nabeh CL700 definovanou dobu
			{
			  appCB.mode &= ~UNIT_START_MODE;											// zrusit flag
		      
			  AddReq(PRIORITY_SYS_MESSAGE | PROCESS_SCI_MESSAGE_INFO, UNIT_START, 0);	// hlasit zapnuti zarizeni
			  
		      // ma byt zapojeno cidlo ale neni, hlasit ERROR
			  if (appCB.sensor.presence_error)
			   {
				  appCB.sensor.presence_error = 0;
				  AddReq(PRIORITY_TASK_LOW | PROCESS_SCI_MESSAGE_INFO, UNIT_SENSOR_FAIL, 0);   // task LOW aby nepredbehlo UNIT_START 
			   }

			}
		 }

		// jeste je nahozen po startu blokujici flag, tak pockat jeste nutnou dobu nez vsechny zarizeni nalince odpovi UNIT_START
		// a pak uvolnit odesilani paketu MEASURE
		if (EDK.sys_flag & FLAG_BLOCK_MEASURE_PACKET)
		{
		  if (appCB.cycles1sec >= PRESET_BLOCK_MEASURE_PACKET_DELAY)		// pockat a uvolnit odesilani MEASURE paketu
			EDK.sys_flag &= ~FLAG_BLOCK_MEASURE_PACKET;
		}

		// rezim blokovani posilani MEASURE paketu, pokud se nacita sbernice
		if (EDK.sys_flag & FLAG_PROCESS_STV_CMD)
		 {
		   if (appCB.cycles1sec >= PRESET_UNIT_START_DELAY)		// pockat stejnou dobu jao po startu, to by melo stacit...
		  	EDK.sys_flag &= ~FLAG_PROCESS_STV_CMD;				// smazat flag a odblokovat pakety MEASURE
		 }
	 
	
		// INKREMENTOVAT CITAC PRO DETEKCI PRERUSENI KOMUNIKACE S TERMINALEM
		// pouze pokud jeste nepretekl a je aktivoovan rezim hlidani
		if (!(EDK.sys_flag & FLAG_OFFLINE_MODE) && (EDK.config.check_offline) )
		 {
			 EDK.counter.comm_timeout++;				// citac pro detekci vypadku komunikace
		 }
	   
		// detekce vypadku komunikace s terminalem
		#if defined INTERFACE_RS || defined CORE_POW	// plati pro zdroj a EDK_RS
	     #ifndef  DEMO_REZIM
		  if (EDK.config.check_offline)					// hlidat komunikaci?
		   {
		    if (!(EDK.sys_flag & FLAG_OFFLINE_MODE))	// aby se opakovane nenastavoval FLAG pokud uz je nastaven
		     {
			   if (EDK.counter.comm_timeout >= PRESET_COMMUNICATION_TIMEOUT)	// neobdrzen paket od terminalu dele nez TIMEOUT
		 	    {
			     EDK.sys_flag |= FLAG_OFFLINE_MODE;		// vypadla komunikace s terminalem
				 SetOfflineLedState();
			    }
		     }
		   }		
	      #endif	// konec demorezim

		  
	  
		  // mereni napajeciho napeti 12V
		  AddReq(PRIORITY_TASK_LOW | PROCESS_ADC, 0,0); 	
		  CheckPowerSupply();							// overit zmerenou hodnotu, jestli je v limitu,
		  												// pokud ne, odesle paket
		  
		  // perioda odesilani measure paketu
		  // ... navazata na nastavene limity MAX a MIN DELTA
		  // mereni a zpracovani uvolneno az po nabehu zarizeni, az odesle paket UNIT_START
		  if (!(appCB.mode & UNIT_START_MODE) && !(EDK.sys_flag & FLAG_PROCESS_STV_CMD) && !(EDK.sys_flag & FLAG_BLOCK_MEASURE_PACKET) )
		   {
			  // mereni teploty
 			  ReadTemperature();							// paket MEASURE se posila na vyzadani
			
			  //todo....	
			  // mereni dalsich cidel
			  
			  
 		      // zpracovani cidel				
			  ProcessSensors();
		   }

		#endif
		
		
		
		#ifdef EDK_USE_DIP
		  AddReq(PRIORITY_TASK_LOW | READ_DIP_SWITCH, 0,0);		// nacitani DIP switche
		#endif
		

	// osetreni chyby UARTU		 
	UART_ClearErrors();

		 
			 
	// citac periody osahavani karty v rezimu EHS
	if (EDK.counter.ehs_check_interval)
	 {
	  	EDK.counter.ehs_check_interval--;			// dekremenovat pokud je co
	 }
		 
							 
	// citac periody osahavani teplomeru DALLAS
	if (EDK.hwspec_low & HWSPEC_LOW_TEMPERATURE)	// pokud je aktivni teplomer, tak nacitat teplotu z cidla
	 {
		// pokud je nastaven interval loopinp, tak generovat paket MEASURE	
		if (EDK.config.loopinp)
		 {	
	       if (!EDK.counter.temperature_send_interval--)
		    {
	          EDK.counter.temperature_send_interval = EDK.config.loopinp;

          	  SendActiveAnalogIoPacket(PACKET_MULTICAST);
		    }
		 }
	 }

}   // konec 	if (appCB.timer1sec.overflow)
	
	

	//************************************
	// obsluha virtualniho casovace 5msec
	//************************************
    if (appCB.timer5ms.overflow)
	 {
		appCB.timer5ms.overflow = 0;
		AddReq(PRIORITY_TASK_HIGH | PROCESS_GPIO, 0,0);							// update GPIO
     }  


	// plati pouze pro rezim EDK, cteni karty ridi terminal AL 	
   #ifdef INTERFACE_EDK				
	if (!(EDK.input.state & EDK_IN_WGOUT))										// neplati pokud je vystup WIEGAND
	 {
	   if (!gCard.isbusy && !EDK.counter.buzzer_time && (EDK.sys_flag&FLAG_READ_CARD))	// aby se zabranilo opakovanemu volani funkce pokud probiha
	    {																		// pokud je aktivni pipak tak se nevolat kvuli pulsovani 
	      AddReq(PRIORITY_TASK_LOW | READ_CARD_ID, 0,0);						// pokud je povoleno cteni karty od signalu SYN
	    }																		// zaloz pozadavek na cteni karty
	 }
   #endif		// konec #ifdef INTERFACE_EDK




	//************************************
	// obsluha virtualniho casovace 20ms
	//************************************
	if (appCB.timer20ms.overflow)
	 {
	    appCB.timer20ms.overflow = 0;
	 }
		

	//************************************
	// obsluha virtualniho casovace 200ms
	//************************************
	// generuje synchronizacni signal do svorky IN1
	if (appCB.timer200ms.overflow)
	 {
	    // indikace nahravani boot kodu - zvlastni rezim
		appCB.timer200ms.overflow = 0;

		// zapnout/vypnout indikaci BOOT rezimu
		if (appCB.mode & UNIT_BOOT_MODE)
		 {
		   EDK.output &= ~EDK_OUT_LED_RED;
		   EDK.output ^= EDK_OUT_LED_GRN;
		 }
		// indikace v normalnim rezimu
		else
		 {
		   // nutno jeste vyloucit OFFLINE a QUITE rezim 
		 /*  if ( !(EDK.sys_flag & FLAG_OFFLINE_MODE) && !(BusControl.BusState & BUS_QUIET) )
		    {
	          if (EDK.led.value )//RestoreIdleLedState();					// obnovit stav LED
		     // EDK.output &= ~EDK_OUT_LED_GRN;
		     // EDK.output |= EDK_OUT_LED_RED;
			}*/
		 }
	 
	 			
	    // indikace QUITE modu, blikne LED kazdou sekundu na 200ms, protoze obsluha 200ms to nize shodi
		if (BusControl.BusState & BUS_QUIET)
		 {
		   if (!appCB.cycles200ms)
		    {
			  EDK.output |= EDK_OUT_LED_GRN;
			}
		   else
		    {
			  EDK.output &= ~EDK_OUT_LED_GRN;
			}
					  
		   appCB.cycles200ms++;
		 }	   
	 
	 }


	//************************************
	// obsluha virtualniho casovace 10ms
	//************************************
	// nacitani vstupu IN1+IN2 a generovani synchronizacniho signalu do svorky IN1
	if (appCB.timer10ms.overflow)
	 {
	    appCB.timer10ms.overflow = 0;
 		#ifndef INTERFACE_EDK									// neplati pro variantu EDK
		  AddReq(PRIORITY_TASK_LOW | PROCESS_SYNC_OUTPUT, 0,0);	// generuje SYNC signal
		#endif  
	 }


}			// konec fce
