/**************************************************************
   Schemat podłączeń programowanego układu

                      +----v----+
                MCLR [| 1     40|] RB7 -> LED Dp
                     [| 2     39|] RB6 -> LED G
                     [| 3     38|] RB5 -> LED F
                     [| 4     37|] RB4 -> LED E
                     [| 5     36|] RB3 -> LED D
                     [| 6     35|] RB2 -> LED C
                     [| 7     34|] RB1 -> LED B
                     [| 8     33|] RB0 -> LED A
                     [| 9     32|] VDD
                     [|10     31|] VSS
                 VDD [|11     30|] 
                 VSS [|12     29|] 
     (20 MHz) / OSC1 [|13     28|] RD5 -> W6
              \ OSC2 [|14     27|] RD4 -> W5
(32,768 kHz) / T1OSO [|15     26|] 
             \ T1OSI [|16     25|] 
                     [|17     24|]
           S1 -> RC3 [|18     23|] RC4 <- S2
           W1 <- RD0 [|19     22|] RD3 -> W4
           W2 <- RD1 [|20     21|] RD2 -> W3
                      +---------+
                      PIC16F877A
***************************************************************/
//definiujemy szybkość oscylatora dla funkcji __delay_
#define _XTAL_FREQ 20000000
#include <htc.h>

//oscylator 20 MHz (FOSC_HS)
//watchdog wyłączony (WDTE_OFF)
//wyłączone LVP (Low-Voltage ICSP Programming) (LVP_OFF)
__CONFIG(FOSC_HS & WDTE_OFF & LVP_OFF);

//zmienne globalne obsługi godziny
unsigned char godzina, godzina10, godzina1;
unsigned char minuta, minuta10, minuta1;
unsigned char sekunda, sekunda10, sekunda1;
//tablica cyfr dla wyświetlacza LED
unsigned char cyfra[10] = {0b11000000, 0b11111001, //0, 1
                           0b10100100, 0b10110000, //2, 3
                           0b10011001, 0b10010010, //4, 5
                           0b10000010, 0b11111000, //6, 7
                           0b10000000, 0b10010000};//8, 9
//zmienna pomocnicza dla utworzenia czasu stabilizacji impulsu przycisku
unsigned char czy_juz_czas;

void main()
{
	TRISD = 0;				//linie portu D wyjściowe
	TRISB = 0;				//port B wyjściowy
	TRISCbits.TRISC3 = 1;	//linia RC3 z przyciskiem S1 wejściowa
	TRISCbits.TRISC4 = 1;	//linia RC4 z przyciskiem S2 wejściowa

	//wyzerowanie zmiennych
	godzina = 0;
	godzina1 = 0;
	godzina10 = 0;
	minuta = 0;
	minuta1 = 0;
	minuta10 = 0;
	sekunda = 0;
	sekunda1 = 0;
	sekunda10 = 0;
	czy_juz_czas = 0;

	//konfiguracja przerwania modułu Timer1
	TMR1H = 0x80;			//TMR1 = 32768
	TMR1L = 0x00;			//(podłączony oscylator zegarkowy)
	//T1CONbits.T1CKPS1 = 0;//brak preskalera
	//T1CONbits.T1CKPS0 = 0;//brak preskalera
	PIE1bits.TMR1IE = 1;	//włącz przerwanie Timer1
	T1CONbits.T1OSCEN = 1;	//włącz oscylator dla Timer1
	T1CONbits.T1SYNC = 1;	//wyłącz synchronizację zewn. oscylatora
	T1CONbits.TMR1CS = 1;	//zewnętrzne źródło taktujące
	T1CONbits.TMR1ON = 1;	//włącz moduł Timer1

	INTCONbits.PEIE = 1;	//włączenie przerwań urządzeń peryferyjnych
	INTCONbits.GIE = 1;		//globalne włączenie przerwań

	for(;;)					//pętla nieskończona
	{
		//wyświetl godzinę///////////
		PORTD = 0b00111110;			//włącz W1 (RD0 w stan logicznego 0)
									//W2, W3, W4, W5, W6 wyłączone
		PORTB = cyfra[godzina10];	//wyświetl cyfrę 1
		__delay_ms(3);				//zaczekaj 5 ms

		PORTD = 0b00111101;			//włącz W2 (RD1 w stan logicznego 0)
									//W1, W3, W4, W5, W6 wyłączone
		PORTB = cyfra[godzina1];	//wyświetl cyfrę 2
		__delay_ms(3);				//zaczekaj 5 ms

		//wyświetl minutę////////////
		PORTD = 0b00111011;			//włącz W3 (RD2 w stan logicznego 0)
									//W1, W2, W4, W5, W6 wyłączone
		PORTB = cyfra[minuta10];	//wyświetl cyfrę 3
		__delay_ms(3);				//zaczekaj 5 ms

		PORTD = 0b00110111;			//włącz W4 (RD3 w stan logicznego 0)
									//W1, W2, W3, W5, W6 wyłączone
		PORTB = cyfra[minuta1];		//wyświetl cyfrę 4
		__delay_ms(3);				//zaczekaj 5 ms

		//wyświetl sekundę///////////
		PORTD = 0b00101111;			//włącz W5 (RD4 w stan logicznego 0)
									//W1, W2, W3, W4, W6 wyłączone
		PORTB = cyfra[sekunda10];	//wyświetl cyfrę 5
		__delay_ms(3);				//zaczekaj 5 ms

		PORTD = 0b00011111;			//włącz W6 (RD5 w stan logicznego 0)
									//W1, W2, W3, W4, W5 wyłączone
		PORTB = cyfra[sekunda1];	//wyświetl cyfrę 6
		__delay_ms(3);				//zaczekaj 5 ms
	
		if(czy_juz_czas > 0) czy_juz_czas--;
		//obsługa przycisków
		if(czy_juz_czas == 0)
		{
			//S1 - inkrementacja minuty
			if(PORTCbits.RC3 == 0)
			{
				minuta++;
				minuta1++;
				if(minuta1>9)
				{
					minuta1 = 0;
					minuta10++;
				}
				if(minuta > 59)
				{
					minuta = 0;
					minuta1 = 0;
					minuta10 = 0;
				}
				sekunda = 0;
				sekunda1 = 0;
				sekunda10 = 0;
			}
			//S2 - inkrementacja godziny
			if(PORTCbits.RC4 == 0)
			{
				godzina++;
				godzina1++;
				if(godzina1>9)
				{
					godzina1 = 0;
					godzina10++;
				}
				if(godzina > 23)
				{
					godzina = 0;
					godzina1 = 0;
					godzina10 = 0;
				}
			}
			czy_juz_czas = 20;
		}
	}
}

static void interrupt
knowania_przerwania(void)
{
	if(PIR1bits.TMR1IF == 1)	//przerwanie modułu Timer1 (wywoływane co 1 s)
	{
		TMR1H = 0x80;			//wartość początkowa do TMR1
		//TMR1L = 0x00;			//TMR1L = 0, więc nie trzeba go nastawiać
		//inkrementacja czasu
		sekunda++;
		//inkrementacja zmiennych wyświetlania sekundy
		sekunda1++;
		if(sekunda1>9)
		{
			sekunda1 = 0;
			sekunda10++;
		}
		if(sekunda > 59)
		{
			sekunda = 0;
			sekunda1 = 0;
			sekunda10 = 0;
			minuta++;
			//inkrementacja zmiennych wyświetlania minuty
			minuta1++;
			if(minuta1>9)
			{
				minuta1 = 0;
				minuta10++;
			}
			if(minuta > 59)
			{
				minuta = 0;
				minuta1 = 0;
				minuta10 = 0;
				godzina++;
				//inkrementacja zmiennych wyświetlania godziny
				godzina1++;
				if(godzina1>9)
				{
					godzina1 = 0;
					godzina10++;
				}
				if(godzina > 23) 
				{
					godzina = 0;
					godzina1 = 0;
					godzina10 = 0;
				}
			}
		}
		PIR1bits.TMR1IF = 0;	//wyczyść flagę przerwania
	}
}

