#include "includes.h"

  unsigned char emPos;
  unsigned char emDta, eprb, eMask;
  unsigned char em_pdta, StartCount;
  unsigned int  tmoutx;
  unsigned int  tmout;

// pracovni buffer SN
  #define CBUFF_SIZE	11			// z karty se nacte 11 bajtu!
  unsigned char  c_buf[CBUFF_SIZE];  

// v pripade pozadavku na nucene ukonceni funkce
  #define EMMARIN_ESCAPE() {  EMCTRL_PIN = 1; ALL_TimersInterruptEnable; return(READER_NO_TAG); } 


// ****************************************************************************
// EmmarinInitReader
// identifikace jestli je osayen EMMARIn cteci cip
// ****************************************************************************
tUInt EmmarinInitReader(void)
{
  tUInt loop;
  
  loop = 5;						// provest 5x tuto smycku detekce
  
  while (loop--)
   {
     EMCTRL_PIN = 1;				// nastavit log.1 na EMCTRL pin 
     tmoutx = EM_CHANGE_TIME;		// chvili pockat, ne moc dlouho, at cip nezacne neco posilat
     while(--tmoutx);	
  
     if (EMDATA)					// na datovem pinu je to same co na EMCTRL, je to asi propojene	
      {
 	    EMCTRL_PIN = 0;
  	    tmoutx = EM_CHANGE_TIME;	// chvili pockat
  	    while(--tmoutx);	
      }   
	else return (NO_ERROR);			// pokud cteci cip je osazen, urovne nebudou stejne
   }

 return (READER_TAG_ERROR);			// urovne se shodovaly, hlasit nejakou chybu, znamena to neni cteci cip EMMARIN
  
}


   
// ****************************************************************************
// Emmarin_Read
// cteni karet Emmarin
// return: OK=0x01,  No CARD=0x00, a dale chybove kody del definice 
// ****************************************************************************
unsigned char Emmarin_Read(char *pdta)
{                                        
  if (!(BusControl.BusState & BUS_FREE))		// cist kartu jen kdyz je volna sbernice
   {
	 return(READER_NO_TAG); //return;
   }

  
  ALL_TimersInterruptDisable;	 

  EMCTRL_PIN = 0;
  tmoutx = EM_START_TIMEOUT;					// pockat nez se aktivuje RF obvod - max.20ms!
  while(--tmoutx);								

  // overit pozadavek na ukonceni funkce, kvuli synchronizaci
  if (!(EDK.sys_flag & FLAG_READ_CARD))
   {
  	  EMMARIN_ESCAPE();	
   }


  StartCount = 0;
  tmout = EM_CHANGE_TIME;
  tmoutx = EM_TIMEOUT_EX;

  em_pdta = EMDATA;   

  while(--tmoutx)
  {
    emDta = EMDATA;  
    emPos = EMDATA;

    // overit pozadavekna ukonceni funkce, kvuli synchronizaci
	if (!(EDK.sys_flag & FLAG_READ_CARD))
	 {
	    EMMARIN_ESCAPE();	
	 }
	
    if(emDta > em_pdta)                     	// nabezna hrana = '0'
     {  
       em_pdta = EMDATA;
       tmout = EM_WAIT_NEXT;                    // pockat 300 uS na zacatek dalsiho bitu

       do { if( EMDATA != em_pdta) break; }
	    while(--tmout);  						// bit se zmenil az po 300us to je OK
				
       if(tmout==0)                         	// vyprsel timeout
         { 
           StartCount = 1;                      // synchronizace zacatku na nabeznou hranu
         }

        tmout = EM_CHANGE_TIME;  
     }  
   


    if(emDta < em_pdta)                 	// sestupna hrana = '1'
     {
       if(StartCount)	StartCount++;   	// pocitat jednicky 

	   if(StartCount==10)
        {
		  break;
		}
   
       tmout = EM_CHANGE_TIME;
       em_pdta = emPos;
     }

      tmout--;
     if(!tmout)
	  {
		tmout = EM_CHANGE_TIME;
		StartCount = 0;
	  }
 }


  if(StartCount < 10 ) 
    { 
	  EMMARIN_ESCAPE();
    }
	


// *************************************	
// detekovano 9x "1" - start
// *************************************
   tmout = EM_WAIT_NEXT;				// pockat na zacatek dalsiho bitu
   while(--tmout);

   tmout = EM_WAIT_NEXT/2;				// uprava kvuli RON cipum - pokud prijde prvnich 10 bitu jako '1'
   while(--tmout);						// je potreba zkorigovat casovani, a pockat jeste 1/2 bitu pred detekci pinu

   				  
	emPos = 0;
    eMask = 0x01;
    eprb = 0;                        	// uklada 5 bitu z karty 

    tmoutx = EM_TIMEOUT_EX;
    em_pdta = EMDATA;

      do
        {
          emDta = EMDATA;  

          if(emDta > em_pdta)                                                          // nabezna hrana = '0'
           {  
             eMask = eMask<<1;

             tmout = EM_BIT_TIME;
             while(--tmout);

             tmoutx = EM_TIMEOUT_EX;
             em_pdta = EMDATA;
          }

          if(emDta < em_pdta)                                                        // setupna hrana = '1'
           {  
             eprb |= eMask;
             eMask = eMask<<1;
             tmout = EM_BIT_TIME;
			 while(--tmout);

             tmoutx = EM_TIMEOUT_EX;
             em_pdta = EMDATA;
           }

          if(eMask==0x20)                   // nacteno 5 bit - ulozit
           {
		     c_buf[emPos] = eprb;
             emPos++;
		  
             if(emPos == 11)
		      break;                		// nacteno vse z karty
          
		  	 eprb = 0; 
          	 eMask = 0x01; 
           }
		   
		// overit pozadavekna ukonceni funkce, kvuli synchronizaci
		if (!(EDK.sys_flag & FLAG_READ_CARD))
		 {
			EMMARIN_ESCAPE();	
		 }
  
     } while(--tmoutx);


    EMCTRL_PIN = 1;							// vypne emmarin
    ALL_TimersInterruptEnable;	 
	  
  
    // kontrola parity
    eprb = 0;
    for( emPos=0; emPos<(CBUFF_SIZE-1); emPos++ )		// bez posledniho bajtu, je paritni
     {
        emDta = 0;
        eMask = 0x01; 

        while(eMask!=0x20)                  // radkova parita - suda
         {
           if(c_buf[emPos]&eMask) emDta ^= 0x01;
           eMask = (eMask<<1);        
         }

        if( emDta )                 		// chyba radkove parity
         { 
		   ALL_TimersInterruptEnable;	 
           return( EMMARIN_ERR_PARITY1 );
         }
    
         c_buf[emPos] = c_buf[emPos]&0x0f;   // orez paritniho bitu          
         eprb ^= c_buf[emPos];               // vypocet celkove parity
      }


 	  // jestli se nenacetly same nuly
	   for( emPos=0; emPos<(CBUFF_SIZE-1); emPos++ )                                
    	{
	     emDta |= c_buf[emPos];
		}
		 
	     if( !emDta )
	     {
  	    	ALL_TimersInterruptEnable;	 
	        return(EMMARIN_ERR_NULL);
	     }
	
       c_buf[emPos] = c_buf[emPos]&0x0f;
	   eprb ^= c_buf[emPos];

  	  
   if(!eprb )						// celkova parita OK
    {
      pdta[0] = 1;
       // convert it to output 
      for( emPos=0; emPos<4; emPos++ )
      {
         emDta = c_buf[(2*emPos+2)];
		 emDta = emDta<<4;
		 emDta |=  (c_buf[((2*emPos)+3)]);
         pdta[(1+emPos)] = emDta;
      }

      pdta[++emPos] = 0;   		// incrementation must be first 
      pdta[++emPos] = 0;
      pdta[++emPos] = 0;
      pdta[++emPos] = 0;
	  pdta[++emPos] = 0x08;		// nejaka stara zvyklost?

 	  ALL_TimersInterruptEnable;	 
	  return (READER_TAG_OK);
    }

   ALL_TimersInterruptEnable;	 
   return (EMMARIN_ERR_PARITY2);
}

