;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;   Schemat podłączeń programowanego układu
;
;                 +----v----+
;           MCLR [| 1     40|] 
;                [| 2     39|] 
;                [| 3     38|] 
;                [| 4     37|] 
;                [| 5     36|] 
;                [| 6     35|] 
;                [| 7     34|] 
;                [| 8     33|] RB0/INT <- S1
;                [| 9     32|] VDD
;                [|10     31|] VSS
;            VDD [|11     30|] 
;            VSS [|12     29|] 
;(20 MHz) / OSC1 [|13     28|]
;         \ OSC2 [|14     27|]
;                [|15     26|] 
;                [|16     25|] 
;                [|17     24|]
;                [|18     23|] 
;      D1 <- RD0 [|19     22|] 
;      D2 <- RD1 [|20     21|] 
;                 +---------+
;                 PIC16F877A
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#include	<p16f877A.inc>	

;ustawienia bitów konfiguracyjnych	
__CONFIG _CP_OFF&_WDT_OFF&_BODEN_OFF&_PWRTE_OFF&_HS_OSC&_WRT_OFF&_LVP_OFF&_CPD_OFF

;**********************************************************************
;zmienne dla podprogramu obsługi przerwań
w_temp		EQU	0x7D	
status_temp	EQU	0x7E	
pclath_temp	EQU	0x7F
;**********************************************************************
;zmienna programu
licznik		EQU 0x24
			
;**********************************************************************
;początek programu
	ORG     0x000
  	goto	main			;skok do etykiety programu głównego

;**********************************************************************
;podprogram obsługi przerwań
	ORG		0x004			;adres wektora przerwań
;zapamiętanie wartości rejestrów
	movwf	w_temp			;W -> w_temp
	movf	STATUS, w		;STATUS -> W
	movwf	status_temp		;W -> status_temp
	movf	PCLATH, w		;PCLATH -> W
	movwf	pclath_temp		;W -> pclath_temp
;kod obsługi przerwań
	btfss	INTCON, INTF	;przerwanie RB0/INT
	goto	koniec_isr		;jeśli bit INTF nie jest ustawiony, to wyjdź
		movlw	8			;W <- 8
		movwf	licznik		;W -> licznik
		bcf		INTCON, INTF;wyczyść flagę przerwania
koniec_isr:
;przywrócenie wartości rejestrów
	movf	pclath_temp, w	;pclath_temp -> W
	movwf	PCLATH			;W -> PCLATH
	movf    status_temp, w	;status_temp -> W
	movwf	STATUS			;W -> STATUS
	swapf	w_temp, f		;zamiast movf w_temp, w są 2 instrukcje swapf,
	swapf	w_temp, w		;by nie ustawiać rejestru STATUS (w_temp -> W)
	retfie					;powrót z przerwania

;**********************************************************************
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Biblioteka podprogramów opóźniających ;
;dla taktowania 20 MHz                 ;
;podprogram Czekaj_1us                 ;
;podprogram Czekaj_10us                ;
;parametry przekazywane w 4. rejestrach;
;R3:R2:R1:R0                           ;
#include "czas.inc"                    ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;**********************************************************************
;program główny
main:
	banksel (TRISD)			;ustaw bank dla TRISD (bank 1)
	bcf		TRISD, 0		;linia RD0 z diodą D1 wyjściowa
	bcf		TRISD, 1		;linia RD1 z diodą D2 wyjściowa
	banksel (PORTD)			;ustaw bank dla PORTD (bank 0)
	bcf		PORTD, 0		;dioda D1 nie świeci
	bcf 	PORTD, 1		;dioda D2 nie świeci

	;konfiguracja przerwania RB0/INT
	banksel (OPTION_REG)		;ustaw bank dla OPTION_REG
	bcf		OPTION_REG, INTEDG	;reakcja na zbocze opadające
	banksel (INTCON)			;ustaw bank dla INTCON
	bsf		INTCON, INTE		;włącz przerwanie RB0/INT
	bsf		INTCON, GIE			;globalne włączenie przerwań

	clrf	licznik				;licznik = 0
;nieskończona pętla
petla:
	;świecenie diody D2 jest uzależnione od stanu licznika
	movf	licznik, f		;czy licznik > 0 
	btfsc	STATUS, Z		;pomiń skok, jeśli Z=0 (licznik>0)
	goto	zeruj_RD1
		bsf		PORTD, 1	;RD1 = 1 (włącz diodę D2)
		decf	licznik, f	;licznik--
		goto	przelacz_RD0;pomiń zerowanie linii RD1
zeruj_RD1:
		bcf		PORTD, 1	;RD0 = 0 (wyłącz diodę D2)
przelacz_RD0:
	;przełącz stan linii RD0
	movlw	1				;W <- 1
	xorwf	PORTD, f		;PORTD ^= 1
	;zaczekaj 125 ms (12500 = 0x30D4)
	movlw   0			
	movwf   R3			
	movlw   0			
	movwf   R2			
	movlw   0x30		
	movwf   R1			
	movlw   0xD4		
	movwf   R0			
	call 	Czekaj_10us	
	;skok do pętli
	goto petla


	END
