#include "i2c.h"
/////////////////////////////////////////////////////////////////
// DO TETO PROMENNE ULOZ CISLO PATRA PRO KTERE JE URCEN PROGRAM//
unsigned char KTERE_PATRO=3;////////////////////////////////////
////////////////////////////////////////////////////////////////

// *** Tlacitka v patre ***/
#define TL_NAH P2_4
#define TL_DOL P2_5

#define LED_NAH P2_6
#define LED_DOL P2_7

data unsigned char prichozi_patro;					 
data unsigned char prichozi_data;
data unsigned char key_reg;
//-----------------------------------------------------------------------------------------------------------------
void delaynop(unsigned char time) //cca 50us
{
    while (time>0)
    {    
        delay();
		delay();
		delay();
		time--;
    }
}
// ***MAX6953******************************************************************************************************
void Disp_Config(unsigned char on_off, unsigned char blink, unsigned char blnk_spd)
{
    unsigned char flag = 0x00;
    if (on_off)   flag |= NORMOP;		// Zapnut / Vypnut
    if (blnk_spd) flag |= FSTBLNK;		// Blink 2Hz (rychly)  / Blink 1Hz (pomaly)
    if (blink)    flag |= BLNKENBL;	    // Blink povolen     / Blink zakazan
    MAX_write( ADDR5300, CONFIG, flag);
}
void Disp_Tst(unsigned char on_off)		// 1-Test zapnut / 0-Test vypnut
{
    MAX_write( ADDR5300, DISP_TST, on_off); // Test displeje, rozsviti se cely display
}
void Disp_Intens(unsigned char intenzita) // 0x0 - nejnizssi, 0xF - nejvyssi
{
    unsigned char intenz = (intenzita << 4) + intenzita; 	//posouv se proto e bity 0-3 jsou pro jeden displej a 4-7 pro druh 
    MAX_write( ADDR5300, INTENS10, intenz); 				// displej 0 a 1
    MAX_write( ADDR5300, INTENS32, intenz);					// displej 2 a 3
}
// ***END**********************************************************************************************************

void Inicializuj(void)
{
    P0 = 0x00;		 //Nastaven nevyuvanho portu
    P1 = 0xFF;		 // Nastaven portu P1 na 00000000b (signly jsou negovan)
    SCL = 1;		 // I2C Clock pro display 
    SDA = 1;		 // I2C Data pro display 
    TL_NAH = 1;		 // Tlacitko vypnuto (signaly jsou negovan)
    TL_DOL = 1;		 // Tlacitko vypnuto (signaly jsou negovan)
    LED_NAH = 0;	 // LED zhasnuta
    LED_DOL = 0; 	 // LED zhasnuta

    IT0 = 1;   		 // Nastaven preruen 0 (pro sestupnou hranu je-li IT0 = 1) /INT0 (P3.2)
    EX0 = 1;    	 // Povolen preruen 0
    EA = 1;	  		 // Povoleni vech preruen preruseni
    
    
	//Displej
    Disp_Config(1,1,1);		// Nastaven displeje
    Disp_Tst(0);		    // Displej test vypnut
    Disp_Intens(0x7); 		// Nastaveni stredni intenzity svitivosti displeje
    MAX_write( ADDR5300, D0P0, CH_NIC);MAX_write( ADDR5300, D0P1, CH_NIC);	 //	Smazan veho z displeje 0
    MAX_write( ADDR5300, D1P0, CH_NIC);MAX_write( ADDR5300, D1P1, CH_NIC);	 //	Smazan veho z displeje 1
    MAX_write( ADDR5300, D2P0, CH_NIC);MAX_write( ADDR5300, D2P1, CH_NIC);	 //	Smazan veho z displeje 2
    
//  porucha = 0;		 		// Porucha nen
    key_reg = 0;				// Nen stisknut dn tlacitko

}

////////////////////////////////////////////////////////////////////////////////

unsigned char Parita(unsigned char d_patro,unsigned char d_zbytek)	// Licha parita je dobra pokud bity O = log0 a V=log1
																	// Program v plc pocita sudou + 1 (bit V=log1) ->Proto m bt prichoz parita lich
{
	unsigned char soucet=0;		//Uchovava pocet jednicek
	unsigned char pom;			//Pomocna
	unsigned char i;			//Pomocna do for cyklu

	for(i=0;i<5;i++)			//Cyklus FOR pro spocitani jednicek v Bytu patro
	{
		pom=d_patro;
		pom=pom>>i;
		pom=pom & 0x01;
		if (pom==1) soucet++;
	}

	for(i=0;i<7;i++)			//Cyklus FOR pro spocitani jednicek v Bytu zbytek
	{
		pom=d_zbytek;
		pom=pom>>i;
		pom=pom & 0x01;
		if (pom==1) soucet++;
	}	
	if (soucet & 0x01)	return 1; //Lich parita na vstupu 1
	else				return 0; //Sud parita na vstupu 0
}


//////////////////////////////////////////////////////////////////////////

void Zobraz2(unsigned char rpatro, unsigned char rdata)
{
	bit porucha;
	bit jede;
	bit up;
	bit down;
	
	if ((rdata&0x01)>0) porucha=1;	   //D2-porucha
	else porucha=0;
	if ((rdata&0x02)>0) jede=1;		   //D3-jede
	else jede=0;
	if ((rdata&0x04)>0) down=1;		   //D4-dolu
	else down=0;
	if ((rdata&0x08)>0) up=1;		   //D5-nahoru
	else up=0;

	//MAX_write( ADDR5300, D0P0, CH_NIC);MAX_write( ADDR5300, D0P1, CH_NIC);	 //	Smazan veho z displeje 0
    //MAX_write( ADDR5300, D1P0, CH_NIC);MAX_write( ADDR5300, D1P1, CH_NIC);	 //	Smazan veho z displeje 1
    //MAX_write( ADDR5300, D2P0, CH_NIC);MAX_write( ADDR5300, D2P1, CH_NIC);	 //	Smazan veho z displeje 2

	if (porucha==0)
	{
		 if((jede==0)&& (rpatro!=KTERE_PATRO)&& (down==0)&& (up==0))
			 {
			 	MAX_write( ADDR5300, D0P0, CH_POML);
				MAX_write( ADDR5300, D0P1, CH_POML);
			 }
		 if((jede==0)&& (rpatro==KTERE_PATRO)&& (down==0)&& (up==0)) //pro patro ve kterem jsem a mm stt
			 {
			 	MAX_write( ADDR5300, D0P0, CH_POML);
				MAX_write( ADDR5300, D0P1, CH_POML);
				LED_NAH=0;
				LED_DOL=0;
				key_reg=0;
			 }
		
		 if((jede==1)&& (up==1)) 		//Jedem nahoru
			 {
			 	MAX_write( ADDR5300, D0P0, CH_NAH);	MAX_write( ADDR5300, D0P1, CH_NAH);
			 }
		 if((jede==1)&& (down==1)) 		//Jedem dolu
			 {
			 	MAX_write( ADDR5300, D0P0, CH_DOL); MAX_write( ADDR5300, D0P1, CH_DOL);
			 }
		 if((jede==0)&& (up==1)) 		//Pojedem nahoru, nemusi se vyuzit, ale je lepsi at tu tam moznost bude
			 {
				MAX_write( ADDR5300, D0P0, CH_NAH);
				MAX_write( ADDR5300, D0P1, CH_NIC);
			 }
		 if((jede==0)&& (down==1)) 		//Pojedem dolu, nemusi se vyuzit, ale je lepsi at tu tam moznost bude
			 {
				MAX_write( ADDR5300, D0P0, CH_DOL);
				MAX_write( ADDR5300, D0P1, CH_NIC);
			 }
		 if(((jede==1)&& ((down==0)&&(up==0)))||((down==1)&&(up==1))||(rpatro==0))
			{
			
			 if((jede==1)&& ((down==0)&&(up==0)))		//Kdyz dostavam signal ze jede ale nedostavam smer tak se zobrazi chyba -2-
				 {
				 	  MAX_write( ADDR5300, D0P0, CH_POML);MAX_write( ADDR5300, D0P1, CH_POML);
					  MAX_write( ADDR5300, D1P0, CH_2);MAX_write( ADDR5300, D1P1, CH_2);
					  MAX_write( ADDR5300, D2P0, CH_POML);MAX_write( ADDR5300, D2P1, CH_POML);
				 }
			 if  ((down==1)&&(up==1))					//Kdyz dostavam signal ze jede nebo pojede zaroven nahoru i dolu chyba -3-
				 {
					  MAX_write( ADDR5300, D0P0, CH_POML);MAX_write( ADDR5300, D0P1, CH_POML);
					  MAX_write( ADDR5300, D1P0, CH_3);MAX_write( ADDR5300, D1P1, CH_3);
					  MAX_write( ADDR5300, D2P0, CH_POML);MAX_write( ADDR5300, D2P1, CH_POML);
				 }
			 if (rpatro==0)
				 {
				 	//Nech na obrazovce to co bylo jendna se jen o pretizeni pro kabinu
				 }
				
			
			}
			
		 else 	//Klidne vypis patro
		 	{										
				 
					 if ((rpatro>0)&&(rpatro<10)) 	//Pokud je paro v intervalu <20,24>  tak na prostrednim displeji zobrazi "0"
						 {
							 MAX_write(ADDR5300,D1P0,CH_0);MAX_write(ADDR5300,D1P1,CH_0);
						 }
					 if ((rpatro>9)&&(rpatro<20)) 	//Pokud je paro v intervalu <10,19>  tak na prostrednim displeji zobrazi "1"
						 {
							 MAX_write(ADDR5300,D1P0,CH_1);MAX_write(ADDR5300,D1P1,CH_1); 
						 }
					 if ((rpatro>19)&&(rpatro<25)) 	//Pokud je paro v intervalu <20,24>  tak na prostrednim displeji zobrazi "2"
						 {
							 MAX_write(ADDR5300,D1P0,CH_2);MAX_write(ADDR5300,D1P1,CH_2);
						 }
					 	 //
					 if (rpatro<25)
				 		{	
						 	switch (rpatro % 10)
						            {   case 0 : MAX_write(ADDR5300,D2P0,CH_0);MAX_write(ADDR5300,D2P1,CH_0);break;
						                case 1 : MAX_write(ADDR5300,D2P0,CH_1);MAX_write(ADDR5300,D2P1,CH_1);break;
						                case 2 : MAX_write(ADDR5300,D2P0,CH_2);MAX_write(ADDR5300,D2P1,CH_2);break;
						                case 3 : MAX_write(ADDR5300,D2P0,CH_3);MAX_write(ADDR5300,D2P1,CH_3);break;
						                case 4 : MAX_write(ADDR5300,D2P0,CH_4);MAX_write(ADDR5300,D2P1,CH_4);break;
						                case 5 : MAX_write(ADDR5300,D2P0,CH_5);MAX_write(ADDR5300,D2P1,CH_5);break;
						                case 6 : MAX_write(ADDR5300,D2P0,CH_6);MAX_write(ADDR5300,D2P1,CH_6);break;
						                case 7 : MAX_write(ADDR5300,D2P0,CH_7);MAX_write(ADDR5300,D2P1,CH_7);break;
						                case 8 : MAX_write(ADDR5300,D2P0,CH_8);MAX_write(ADDR5300,D2P1,CH_8);break;
						                case 9 : MAX_write(ADDR5300,D2P0,CH_9);MAX_write(ADDR5300,D2P1,CH_9);break;
						            }
						}

					 else
						{		   //Pokud je cislo patra vetsi nez 24 da na displej chybu -1-
							MAX_write( ADDR5300, D0P0, CH_POML);MAX_write( ADDR5300, D0P1, CH_POML);
							MAX_write( ADDR5300, D1P0, CH_1);MAX_write( ADDR5300, D1P1, CH_1);
							MAX_write( ADDR5300, D2P0, CH_POML);MAX_write( ADDR5300, D2P1, CH_POML);
						}
		  	}
		
	}
	else						   //Kdyz nastala porucha	
	{
		MAX_write( ADDR5300, D0P0, CH_e);MAX_write( ADDR5300, D0P1, CH_e);
        MAX_write( ADDR5300, D1P0, CH_r);MAX_write( ADDR5300, D1P1, CH_r);	
        MAX_write( ADDR5300, D2P0, CH_r);MAX_write( ADDR5300, D2P1, CH_r);
		LED_NAH=0;
		LED_DOL=0;
		key_reg=0;
   
	
	}
}

//////////////////////////////////////////////////////////////////////////
		

void main(void)
{
    Inicializuj();
    while (1)
    {   // Cyklus 111
        
        P1 = 0x8F;							// 1000 1111 ve skutecnosti 0111 0000 poadavek o prvn cast dat
        while ((~P1 & 0x08) == 0x00); 		// Cek a K (xxxxKxxx) zmen na 0

        delaynop(30);						// Zpodovac smycka o 1,5ms
        prichozi_patro = (~P1 & 0x07);			// Znegovn informace a aplikace masky na |0|0|0|0|0|D10|D9|D8|
        prichozi_patro = prichozi_patro << 3;		// Bitovy posun informace na 			 |0|0|D10|D9|D8|0|0|0|
        
        // Cyklus 010
        
        P1 = 0xDF;					    	// 1101 1111 ve skutecnosti 0010 0000 poadavek o druhou cast dat
        while ((~P1 & 0x08) == 0x08); 		// Cek a K (xxxxKxxx) zmen 1

        delaynop(30);						// Zpodovac smyka o 1,5ms
		prichozi_patro = prichozi_patro|(~P1 & 0x07);// V patru mame |0|0|D10|D9|D8|0|0|0| a k tomu bitove pricteme negovan upraven data z P1
											// Nakonec v patru mame |0|0|D10|D9|D8|D7|D6|D5|	POZOR- Cislo patra je jen v bitech D10-D6!!!
		prichozi_data = prichozi_patro & 0x01;		// Protoze D5 patri do prichozi_data patro upravm tak aby tam zbylo jen D5 a ulozime do prichozi_data
		prichozi_patro >>= 1;					// Patro dostaneme do ciloveho tvaru |0||0|0|D10|D9|D8|D7|D6|
		prichozi_data <<= 3;					// D5 v prichozi_data posuneme o 3 bity na |0|0|0|0|D5|0|0|0|

        // Cyklus 001

        P1 = 0xEF;							// 1110 1111 ve skutecnosti 0001 0000 poadavek o treti cast dat
        while ((~P1 & 0x08) == 0x00); 		// Cek a K (xxxxKxxx) zmen na 0

        delaynop(30);						// Zpodovac smyka o 1,5ms
        prichozi_data =prichozi_data|(~P1 & 0x07);	// Pridam dalsi 3 bity do prichozi_data na  |0|0|0|0|D5|D4|D3|D2|
        prichozi_data <<= 3;				  	// Bitovy posun na  |0|D5|D4|D3|D2|0|0|0|

        // Cyklus 000

        P1 = 0xFF;							// 1111 1111 ve skutecnosti 0000 0000 poadavek o ctvrtou cast dat
        while ((~P1 & 0x08) == 0x08); 		// Cek a K (xxxxKxxx) zmen na 1

        delaynop(30);						// Zpodovac smyka o 1,5ms
        prichozi_data =prichozi_data|(~P1 & 0x07);	// Pridam dalsi 3 bity do prichozi_data na  |0|D5|D4|D3|D2|D1|O|V|
    
		if (Parita(prichozi_patro,prichozi_data)) 	// Parita bere ohled i na bity O a V
		{
			prichozi_data=prichozi_data>>3;		   	//Zahazuju paritni bit a O a V, do zobraz vstupuje:
	
			Zobraz2(prichozi_patro,prichozi_data);	// prichozi_patro |0||0|0|D10|D9|D8|D7|D6| a prichozi_data |0|0|0|0|D5|D4|D3|D2|
			
		}

		// Pokud bylo zmcknuto tlacitko pridava se 5. cyklus
		if (key_reg > 0) 
        {   if (key_reg == 1)	 // Pokud je zmacknute DOLNI tlacitko
            {   LED_DOL = 1;		// Rosvt se DOLNI LED
                P1 = 0xBF;			// Vyle se poadavek 10111111 co je 0100000 (100) , master neodpovida
            }
            if (key_reg == 2) 	// Pokud je zmacknute HORNI tlacitko
            {   LED_NAH = 1;		// Rosvt se HORNI LED
                P1 = 0xAF;			// Vyle se poadavek 10101111 co je 0101000 (101)	, master neodpovida
            }
            if (key_reg == 3)	// Oba tlacitka sepnuta
            {   LED_NAH = 1;		// Rosvt se HORNI LED
                LED_DOL = 1;		// Rosvt se DOLNI LED
                P1 = 0xCF;			// Vyle se poadavek 11001111 co je 0011000 (011) , master neodpovida
            }
            delaynop(400);			// Zpodovac smyka o 20ms
        }
    }
}
void keyboard_interrupt(void) interrupt 0	 // Pri stisku tlacitka se vyvola preruseni a zmeni hodnoty key_reg
{
	if (TL_NAH == 0) key_reg |= 2;		 	// Pri zmacknuti tlacitka zmeni key_reg na 0000 0010 
	if (TL_DOL == 0) key_reg |= 1;	 		// Pri zmacknuti tlacitka zmeni key_reg na 0000 0001
											// Pri zmacknuti obou 					   0000 0011
}
