;***********************Beállítások********************************************

        PROCESSOR '16F877A'
        INCLUDE <P16F877A.INC>

        __CONFIG _XT_OSC & _WDT_OFF & _PWRTE_OFF & _CP_OFF & _LVP_OFF & _BODEN_OFF
		
	
;**********************Változók************************************************

		cblock  0x20
				TIMERTCS		; Timer1 túlcsordulások számlálója
				TIMERTCS1
				TIMERTCS2
				TULCSORDUL
				TEMP1L			; CCP első érték átmeneti tároló, alsó bit
				TEMP1H			; CCP első érték átmeneti tároló, felső bit
				TEMP2L			; CCP második érték átmeneti tároló, alsó bit
				TEMP2H			; CCP második érték átmeneti tároló, felső bit
				W_TEMP			; W átmeneti tárolója
				S_TEMP			; S átmeneti tárolója
				TIMEL			; Idő alsó bájt
				TIMEH			; Idő felső bájt
				FIRST			; Kiolvasás jelzőbit
				TIMER1L			; Időtartamszámítás, alsó bájt 
				TIMER1M			; Időtartamszámítás, középső bájt 
				TIMER1H			; Időtartamszámítás, felső bájt 
				count           ; Számláló a ciklus-rutinokhoz.
				count1          ; Számlálók a késleltető rutinhoz.
				counta
				countb
				count2
				tmp1            ; Átmeneti tárolás.
				tmp2
				templcd         ; Átmeneti tároló a 4 bites módhoz.
				templcd2
				SZORZO			; Szorzó
				r1				; Eredmény, alsó bájt
				r2				; Eredmény, középső bájt
				r3				; Eredmény, felső bájt
				bL				; Szorzandó, alsó bájt
				bH				; Szorzandó, felső bájt
				nratorH			; Számláló és eredmény felső bájt
				nratorM			; Számláló és eredmény középső bájt
				nratorL			; Számláló és eredmény alsó bájt
				denomH			; Nevező felső bájt
				denomM			; Nevező középső bájt
				denomL			; Nevező alsó bájt
				remainH			; Maradék felső bájt
				remainM			; Maradék középső bájt
				remainL			; Maradék alsó bájt
                BCount          ; Számláló az osztáshoz
                shiftH          ; Segédregiszter az osztáshoz
                shiftM          ; Segédregiszter az osztáshoz
                shiftL          ; Segédregiszter az osztáshoz
		endc
		
	LCD_PORT Equ PORTD
	LCD_TRIS Equ TRISD
	LCD_RS   Equ 0x04           ; A Register Select (RS) vonal változója.
	LCD_E    Equ 0x07           ; Az Enable         (E)  vonal változója.

ORG 0
goto Init
;*********************Megszakítás**********************************************

ORG 4

MEGSZ:
	movwf	W_TEMP				; a W értékének mentése
 	movfw	STATUS				; W = STATUS 
 	movwf	S_TEMP				; a STATUS regiszter elmentése
 	
	btfsc	PIR1,0				; Ha 1, akkor Timer1 okozta a megszakítást
	goto	MEGSZ_TIMER
	btfsc	PIR2,0				; Ha 1 akkor CCP okozta a megszakítást
	goto	MEGSZ_CCP
	goto	VEGE
	
MEGSZ_TIMER:	
	incf	TIMERTCS			; A Timer1 túlcsordulását számláló változó növelése
	bcf		PIR1,0				; A megszakítást jelző bit törlése
	goto	VEGE
	
MEGSZ_CCP:	
	bcf		STATUS,5			;a 0. adatmemória lap kiválasztása
 	bcf		PIR2,0				;A megszakítást jelző bit törlése
	btfss	FIRST,0				;az első eseményt jelző szoftveres jelzőbit vizsgálata
 	goto	ELSO				;ugrik, ha FIRST,0 = "0"
 	movf	CCPR2L				;W = CCPR2L
 	movwf	TEMP2L				;TEMP2L = CCPR2L ("második érték" alsó bájt elmentve)
 	movf	CCPR2H				;W = CCPR2H
 	movwf	TEMP2H				;TEMP2H = CCPR2H ("második érték" felső bájt elmentve)
 	movf	TIMERTCS
	movwf	TIMERTCS2
	bcf		PIR2,0  			;a CCPIF jelzőbit nullázása
 	bsf		STATUS,5			;az 1. adatmemória lap kiválasztása
 	clrf	PIE1				;a periféria megszakítások tiltása
 	bcf		STATUS,5			;a 0. adatmemória lap kiválasztása
 	clrf	CCP2CON				;a CCP modul kikapcsolása
 	goto	VEGE		 		;ugrás a megszakításkezelő szubrutin végére
ELSO:	
	movf	CCPR2L				;W = CCPR2L
 	movwf	TEMP1L				;TEMP2L = CCPR2L ("elso érték" alsó bájt elmentve)
 	movf	CCPR2H				;W = CCPR1H
 	movwf	TEMP1H				;TEMP2H = CCPR2H ("elso érték" felső bájt elmentve)
 	movf	TIMERTCS
	movwf	TIMERTCS1
	bsf		FIRST,0				;az első érték elmentésének jelzése a szoftvernek
 	bcf		PIR2,0				;a CCPIF jelzőbit nullázása
VEGE:	
	movfw	S_TEMP				;W = STATUS regiszter elmentett értéke
 	movwf	STATUS				;a STATUS regiszter értékének visszaállítása
 	movfw	W_TEMP				;a W_TEMP értékének bitcseréje
 	
 	retfie	 			;visszatérés a megszakításból
;*********************Főprogram************************************************



Init:
	call	LCD_Init			;LCD alaphelyzetbe állítása	
	clrf	CCP2CON				;a CCP modul kikapcsolása
 	clrf	T1CON				;Timer 1 kikapcsolva (előosztás 1:1, belső léptetés, szinkronizáció)
 	clrf	INTCON				;a megszakítások tiltása
 	bsf		STATUS,5			;az 1. adatmemória lap kiválasztása
 	bsf		TRISC,2     		;a CCP2 kivezetés bemenetként való beállítása
 	clrf	PIE2				;a periféria megszakítások tiltása
 	bcf		STATUS,5			;a 0. adatmemória lap kiválasztása
 	clrf	PIR2				;a periféria megszakításkérő jelzőbitek nullázása
 	clrf	FIRST				;a szoftveres jelzőbit regiszterének nullázása
 	bsf		T1CON,0				;a Timer 1 léptetésének indítása
 	movlw	0x05				;W = 0x05
 	movwf	CCP2CON				;a Capture üzemmód indítása, kiolvasás minden felfutó élre
 	bsf		STATUS,5			;az 1. adatmemória lap kiválasztása
 	bsf		PIE2,0				;megszakítás engedélyezés CCP2IE="1"
 	bcf		STATUS,5			;a 0. adatmemória lap kiválasztása
 	bsf		INTCON,6			;PEIE="1"; periféria megszakítások engedélyezése
 	bsf		INTCON,7			;GIE="1"; globális megszakítás engedélyezés

;*************** A két érték közötti különbség meghatározása ***
			;Az eredmény a TULCSORDUL, TIMEH, TIMEL regiszterekbe kerül

Kivon:			
 	movf    TIMERTCS2,W    	
    subwf   TIMERTCS1,W    	
	movwf	TULCSORDUL
	movf    TEMP2H,w     		
    subwf   TEMP1H,W
	movwf	TIMEH
	movf    TEMP2L,w     	
    subwf   TEMP1L,W
	movwf	TIMEL
		 
;*************** Időtartamszámítás ********************************************
;			Kerék kerület 1,2 m. Mivel a m/s és km/h között 3,6 a váltószám a s és a us között 1 000 000,
; úgy kell számolni, hogy 1,2x3 600 000/idő (tehát 4 320 000/idő) . Ez km/h-át ad egész értékben.
; számláló: nratorH  nratorM  nratorL
; nevező: denomH   denomM   denomL
; Az eredmény a nratorH  nratorM  nratorL regiszterekbe kerül
Oszt:
	  movlw		b'01000001'		; A számláló 24 bites regiszterébe 4 320 000-et töltünk
	  movwf		nratorH
	  movlw		b'11101011'
	  movwf		nratorM
	  movlw		b'00000000'
	  movwf		nratorL
	  
	  movfw		TULCSORDUL
	  movwf		denomH
	  movfw		TIMEH
	  movwf		denomM
	  movfw		TIMEL
	  movwf		denomL	

Divide_24x24:
      movlw    .24		; set decimal 24 loop count
      movwf    BCount
      movf     nratorH,w ; copy Numerator into Shift Holding ram registers
      movwf    shiftH
      movf     nratorM,w
      movwf    shiftM
      movf     nratorL,w
      movwf    shiftL
      clrf     nratorH	;  clear final Answer Numerator Ram locations
      clrf     nratorM
      clrf     nratorL
      ;
      clrf     remainH  ;  clear final Answer Remainder Ram locations
      clrf     remainM
      clrf     remainL
dloop:
      bcf		STATUS, C  ; bit clear Carry Flag in STATUS register
      rlf		shiftL, f  ; Shift numerator(dividend) Left to move
      rlf		shiftM, f  ; next bit to remainder
      rlf		shiftH, f  ; and shift in next bit of result

      rlf		remainL, f ; shift carry (next Dividend bit) into remainder
      rlf		remainM, f
      rlf		remainH, f
      movf     denomH,w
      subwf    remainH,w  ; subtract divsor(denomH) from(newly shifted left) Remainder HIGH byte.
      btfss    STATUS, Z
      goto     nochk		  ; skip if result was ZERO from good subtraction result
      ;
      movf     denomM,w
      subwf    remainM,w  ; subtract divsor(denomM) from(newly shifted left) Remainder MIDDLE byte.
      btfss    STATUS, Z
      goto     nochk		  ; skip if result was ZERO from good subtraction result
      ;
      movf     denomL,w
      subwf    remainL,w  ; subtract divsor(denomL) from(newly shifted left) Remainder LOW byte.
nochk:
      btfss    STATUS, C   ;  Carry SET? then denom is larger than reemainder
      goto     nogo
      ;
      movf     denomL,w			 
      subwf    remainL, f   	 ; Subtract denominator from remainder value in Low Byte
      btfsc    STATUS, C       ; Carry Set? Then execute fixup code for when a borrow is generated
      goto 		nodec_remainM   ; when no borrow bit is needed from the higher byte positions.
      decf     remainM, f      ; Decrement to Borrow from Middle Byte, because carry was SET.
      movf     remainM,w
      xorlw    0xff				 ; Check if rollover from Borrow occurred. remainM value went from 0 to 0xFF 
      btfsc    STATUS, Z
      decf     remainH, f		 ; ZERO bit set, yes rollover, so Decrement to Borrow from High Byte, too!
nodec_remainM:
      movf     denomM,w
      subwf    remainM, f		 ; Subtract denominator from remainder value in Middle Byte
      btfss    STATUS, C
      decf     remainH ,f      ; Decrement High Byte, to borrow 1 bit
      movf     denomH,w   		 
      subwf    remainH, f      ; Subtract denominator from remainder value in High Byte
      bsf		STATUS, C       ; set CARRY bit to rotate in Numerator Result next.
nogo:
      rlf		nratorL, f  ; rotate Numerator result left 1 bit
      rlf		nratorM, f
      rlf		nratorH, f
      decfsz   BCount, f   ; decrement the Loop Bit Counter
      goto     dloop
      goto      Kivon
	
 	 	 	;*** Konverzió (például bináris/BCD és BCD/7-szegmens) ***
 	 	 
 	 	 	;*** Kijelzés vezérlése ***
;***********************Szubrutinok és szövegtáblák****************************

	
; LCD rutinok

; Alaphelyzetbe állítja az LCD-t (inicializál)
LCD_Init
     movlw   0x20             ; A 4 bites mód beállítása.
     call    LCD_Cmd

     movlw   0x28             ; Shift (betűemelés) beállítása.
     call    LCD_Cmd

     movlw   0x06             ; Karakter mód beállítása.
     call    LCD_Cmd

     movlw   0x0c             ; Kijelző ki/be és kurzor parancs.
     call    LCD_Cmd

     call    LCD_Clr          ; Kijelző törlése.

     retlw    0x00

; Parancs-üzemmód beállítása.
LCD_Cmd
     movwf   templcd
     swapf   templcd,W        ; Elküldi a felső nibble-t.
     andlw   0x0f             ; Törli a felső 4 bitet a W regiszterből.
     movwf   LCD_PORT
     bcf     LCD_PORT,LCD_RS  ; RS vonalat nullára állítja.
     call    Pulse_e          ; Magas impulzust küld az Enable lábra.

     movf    templcd,W        ; Elküldi a alsó nibble-t.
     andlw   0x0f             ; Törli a felső 4 bitet a W regiszterből.
     movwf   LCD_PORT
     bcf     LCD_PORT,LCD_RS  ; RS vonalat nullára állítja.
     call    Pulse_e          ; Magas impulzust küld az Enable lábra.
     call    Kesleltet5
     retlw   0x00

; Karakter-üzemmód beállítása.
LCD_CharD
     addlw   0x30
LCD_Char
     movwf   templcd
     swapf   templcd,W        ; Elküldi a felső nibble-t.
     andlw   0x0f             ; Törli a felső 4 bitet a W regiszterből.
     movwf   LCD_PORT
     bsf     LCD_PORT,LCD_RS  ; RS vonalat egyre állítja.
     call    Pulse_e          ; Magas impulzust küld az Enable lábra.

     movf    templcd,W        ; Elküldi a alsó nibble-t.
     andlw   0x0f             ; Törli a felső 4 bitet a W regiszterből.
     movwf   LCD_PORT
     bsf     LCD_PORT,LCD_RS  ; RS vonalat egyre állítja.
     call    Pulse_e          ; Magas impulzust küld az Enable lábra.
     call    Kesleltet5
     retlw   0x00

; Kurzor pozicionálása.
LCD_Line1
     movlw   0x80             ; Az 1. sor 1. oszlopába helyezi a kurzort.
     call    LCD_Cmd
     retlw   0x00

LCD_Line2
     movlw   0xc0             ; A 2. sor 1. oszlopába helyezi a kurzort.
     call    LCD_Cmd
     retlw   0x00

LCD_Line1W
     addlw   0x80             ; Az 1. sor W oszlopába helyezi a kurzort
     call    LCD_Cmd
     retlw   0x00

LCD_Line2W
     addlw   0xc0             ; A 2. sor W oszlopába helyezi a kurzort.
     call    LCD_Cmd
     retlw   0x00

LCD_CurOn
     movlw   0x0d             ; Kijelző ki/be és kurzor parancs.
     call    LCD_Cmd
     retlw   0x00

LCD_CurOff
     movlw   0x0c             ; Kijelző ki/be és kurzor parancs.
     call    LCD_Cmd
     retlw   0x00

LCD_Clr
     movlw   0x01             ; Törli a kijelzőt.
     call    LCD_Cmd
     retlw   0x00

LCD_HEX
     movwf   tmp1
     swapf   tmp1,w
     andlw   0x0f
     call    HEX_Table
     call    LCD_Char
     movf    tmp1,W
     andlw   0x0f
     call    HEX_Table
     call    LCD_Char
     retlw   0x00

Kesleltet255
     movlw   0xff             ; A késleltetés 255ms.
     goto    K0
Kesleltet100
     movlw   d'100'           ; A késleltetés 100ms.
     goto    K0
Kesleltet50
     movlw   d'50'            ; A késleltetés 50ms.
     goto    K0
Kesleltet20
     movlw   d'20'            ; A késleltetés 20ms.
     goto    K0
Kesleltet5
     movlw   0x05             ; A késleltetés 5.000 ms (4 MHz órajel).
K0
     movwf   count1
K1
     movlw   0xC7             ; A késleltetés 1ms.
     movwf   counta
     movlw   0x01
     movwf   countb
Kesleltet_0
     decfsz  counta,f
     goto    $+2
     decfsz  countb,f
     goto    Kesleltet_0

     decfsz  count1,f
     goto    K1
     retlw   0x00

Pulse_e
     bsf     LCD_PORT,LCD_E   ; Magasra állítja az LCD Enable bemenetét.
     nop                      ; Egy óraciklus idejére magasan tartja.
     bcf     LCD_PORT,LCD_E   ; Törli az E bemenetet (alacsony szint).
     retlw   0x00

; LCD rutinok vége.
;******************************************
    
HEX_Table
     addwf   PCL,f
     retlw   0x30
     retlw   0x31
     retlw   0x32
     retlw   0x33
     retlw   0x34
     retlw   0x35
     retlw   0x36
     retlw   0x37
     retlw   0x38
     retlw   0x39
     retlw   0x41
     retlw   0x42
     retlw   0x43
     retlw   0x44
     retlw   0x45
     retlw   0x46

Szoveg1
     addwf   PCL,f
     retlw   'A'
     retlw   'k'
     retlw   'k'
     retlw   'u'
     retlw   ':'
	 retlw   ' '
	 retlw   ' '
	 retlw   ' '
	 retlw   '%'
     retlw   0x00

Szoveg2
     addwf   PCL,f
     retlw   'S'
     retlw   'e'
     retlw   'b'
     retlw   'e'
     retlw   's'
     retlw   's'
     retlw   'e'
     retlw   'g'
     retlw   ':'
     retlw   ' '
     retlw   ' '
     retlw   'k'
     retlw   'm'
     retlw   '/'
     retlw   'h'
     retlw   0x00


     end