;***********************Leírás*************************************************
; 1 - MCLR		40 - 
; 2 - Gázkar	39 -
; 3 - Akkufesz	38 -
; 4 - 			37 - Féklámpa kapcsoló
; 5 -			36 -
; 6 - 			35 - 
; 7 - 			34 -
; 8 -			33 - Féklámpa
; 9 -			32 - Vdd
; 10 - 			31 - Vss
; 11 - Vdd		30 - 
; 12 - Vss		29 -
; 13 - 4 MHz	28 - LCD E
; 14 - 4 MHz	27 - LCD RS
; 15 -			26 - 
; 16 - 			25 -
; 17 - PWM		24 -
; 18 -			23 -
; 19 - LCD D4	22 - LCD D7
; 20 - LCD D5	21 - LCD D6

;***********************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
				SECOND			; Második 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
				NULLA			; 0 km/h kijelzése
				d0				; A bináris ASCII átalakítás segédregisztere
				d1				; A bináris ASCII átalakítás segédregisztere
				d2				; A bináris ASCII átalakítás segédregisztere
				
		endc
		
	LCD_PORT Equ PORTD
	LCD_RS   Equ 0x04           ; A Register Select (RS) vonal változója.
	LCD_E    Equ 0x05           ; Az Enable         (E)  vonal változója.

	ORG 0
	goto 	Start
;*********************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
 	
	bcf		STATUS,5			; Bank0 kiválasztása
	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:	
	bcf		PIR1,0				; A megszakítást jelző bit törlése
	incfsz	TIMERTCS			; A Timer1 túlcsordulását számláló változó növelése
	movlw	b'11111111'
	subwf	TIMERTCS,W			; Ha a TIMERTCS értéke eléri a 255 értéket
	btfsc	STATUS,Z			; a NULLA regiszter értékét növeli
	incf	NULLA				
	goto	VEGE
	
MEGSZ_CCP:	
	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"
 	movfw	CCPR2L				;W = CCPR2L
 	movwf	TEMP2L				;TEMP2L = CCPR2L ("második érték" alsó bájt elmentve)
 	movfw	CCPR2H				;W = CCPR2H
 	movwf	TEMP2H				;TEMP2H = CCPR2H ("második érték" felső bájt elmentve)
 	movfw	TIMERTCS
	movwf	TIMERTCS2
	bcf		PIR2,0  			;a CCPIF jelzőbit nullázása
 	bsf		SECOND,0			;a második kiolvasást jelzőbit beállítása
	bcf		FIRST,0
 	goto	VEGE		 		;ugrás a megszakításkezelő szubrutin végére
ELSO:	
	movfw	CCPR2L				;W = CCPR2L
 	movwf	TEMP1L				;TEMP2L = CCPR2L ("elso érték" alsó bájt elmentve)
 	movfw	CCPR2H				;W = CCPR2H
 	movwf	TEMP1H				;TEMP2H = CCPR2H ("elso érték" felső bájt elmentve)
 	movfw	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************************************************

Start
	 movlw	 b'0001111'
	 movwf	 count2
	 decf	 count2

Initialise                    ; Inicializálás (kezdeti értékek beállítása).
		clrf    count
		clrf    PORTD
		clrf    PORTC
        BANKSEL	TRISC
		CLRF	TRISC			; PortC kimenet
		BANKSEL	ADCON1
		MOVLW	b'01000100'
		MOVWF	ADCON1			; PortA O, 1, 3 bitje analóg bemenet, Vref+ = Vdd	Vref- = Vss
;		BANKSEL	ADCON0
;		MOVLW	b'10000001'		; Fosc/64, AN0 konverzió
;		MOVWF	ADCON0
		BANKSEL	TRISB
		MOVLW	b'00010000'
		MOVWF	TRISB			; PortB 4.-bitje bemenet

;**************************PWM beállítások***********************		
		
        ;PWM Frekvencia beállítása
        BSF 	STATUS, RP0 ;BANK 01
        MOVLW 	D'202' ;PR2 = D'202' PWM periódus = 2,03*10^-4 s => PWM frekvencia = 4,9 kHz
        MOVWF 	PR2
        BCF 	STATUS, RP0 ;BANK 00

        ;PWM kitöltés beállítása
        CLRF 	CCPR1L
        MOVLW 	B'00001100'
        MOVWF 	CCP1CON

        ;PWM kimenet beállítása
        BSF 	STATUS, RP0 ;BANK 01
        BCF 	TRISC, 2 ;PortC 2 bitje a PWM kimenet
        BCF 	STATUS, RP0  ;BANK 00

        ;TIMER 2 előosztás 1:1
        MOVLW 	B'00000100'
        MOVWF 	T2CON

        CLRF 	TMR2	;TIMER 2 törlése

        BSF 	T2CON, TMR2ON	;TIMER 2 indítása

;*************************LCD beállítások*************************		
		
SetPorts                      ; Portok beállítása.
     bsf     STATUS,RP0       ; Kiválasztjuk a Register Page 1-et.
     movlw   0x00             ; Összes kapu kimenet.
     movwf   TRISD
     bcf     STATUS,RP0       ; Vissza a Register Page 0-ra.
     call    Kesleltet100     ; Várakozás az LCD inicializálására.
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.
     clrf    count            ; Számláló regiszter törlése.

     movlw	 b'00000100'
	 call	 LCD_Line1W

Message                       ; Üzenetek kezelése.
     movf    	count,W          ; Számláló értéke a W regiszterbe.
     pagesel    Szoveg1
     call    	Szoveg1          ; Beolvas egy karaktert az 1. táblázatból.
     Pagesel    Message
     xorlw   	0x00             ; Zéró a státuszbit értéke?
     btfsc   	STATUS,Z
     goto    	NextMessage
     call    	LCD_Char
     incf    	count,f
     goto    	Message
NextMessage
     call    	LCD_Line2        ; A 2. sor 1. oszlopába állítja a kurzort.
     clrf    	count            ; Számláló regiszter törlése.
Message2
     movf    	count,W          ; Számláló értéke a W regiszterbe.
     Pagesel    Szoveg2
     call    	Szoveg2          ; Beolvas egy karaktert a 2. táblázatból.
     Pagesel    Message2
     xorlw   	0x00             ; Zéró a státuszbit értéke?
     btfsc   	STATUS,Z
     goto    	EndMessage
     call    	LCD_Char
     incf    	count,f
     goto    	Message2
    

EndMessage
     movlw	 b'00001001'	;Akku kijelzés helyére állítja a kurzort
	 call	 LCD_Line1W

;******************************CCP2 beállítások*****************************	 
	 
Init:
	bcf		STATUS,5			;Bank 0
	clrf	TULCSORDUL			;regiszter törlése
	clrf	CCP2CON				;a CCP modul kikapcsolása
 	clrf	T1CON				;Timer 1 kikapcsolva 
 	clrf	INTCON				;a megszakítások tiltása
 	clrf	PIR1
	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 Timer1 léptetésének indítása
	movlw	b'00000101'			;W = 0x05
 	movwf	CCP2CON				;a Capture üzemmód indítása, kiolvasás minden felfutó élre
	bsf		STATUS,5			;Bank 1
 	bsf		TRISC,1     		;a CCP2 kivezetés bemenetként való beállítása
 	bsf		PIE2,0				;megszakítás engedélyezés CCP2IE="1"
 	bsf		PIE1,0				;A Timer 1 megszakításának engedélyezése
 	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
	bcf		STATUS,5			;a 0. adatmemória lap kiválasztása

Kezd:	
;	btfsc	SECOND,0
;	goto	Kivon
;	goto	Kezd

;*************** A két CCP2 érték közötti különbség meghatározása ***
			;Az eredmény a TULCSORDUL, TIMEH, TIMEL regiszterekbe kerül

Kivon:
	movfw   TIMERTCS2    	
    subwf   TIMERTCS1,W    	
	movwf	TULCSORDUL
	movfw   TEMP2H     		
    subwf   TEMP1H,W
	movwf	TIMEH
	movfw   TEMP2L     	
    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
	  clrf		SECOND
      movfw		nratorL	
;***************** Konverzió (bináris/ASCII) ***
 	clrf	d2
	clrf 	d1
	clrf	d0 

; Test if W is more than 199 (200 to 255)
	addlw 	.256 - .200
	btfss 	STATUS,C
	goto  	digit100
	bsf   	d2,1
; Here we are in the 200 - 255 range, so it is possible to
; skip the .100 and .80 parts
	addlw 	.256 - .80
	goto  	digit40

; Now, we have a number from -200 to -1 (0..199),
; we add 100 to detect -100 to -1 (100..199).
digit100
	addlw 	.100
	btfss 	STATUS,C
	goto  	$+3
	bsf   	d2,0
	addlw 	.256 - .100

; Now, we have a number from -100 to -1 (0..99),
; we add 20 to detect -20 to -1 (80..99).
	addlw 	.20
	btfss 	STATUS,C
	goto  	digit40
	bsf   	d1,3
; We skip the 4 and 2, as the largest value is 8 + 1 = 9.
	addlw 	.256 - .20
	goto 	digit10

; Now, we have a number from -80 to -1 (0..79),
; we add 40 to detect -40 to -1 (40..79).
digit40
	addlw 	.40
	btfss 	STATUS,C
	goto  	$+3
	bsf   	d1,2
	addlw 	.256 - .40

; Now, we have a number from -40 to -1 (0..39),
; we add 20 to detect -20 to -1 (20..39).
	addlw 	.20
	btfss 	STATUS,C
	goto  	$+3
	bsf   	d1,1
	addlw 	.256 - .20

; Now, we have a number from -20 to -1 (0..19),
; we add 10 to detect -10 to -1 (10..19).
digit10
	addlw 	.10
	btfss 	STATUS,C
	goto  	$+3
	bsf   	d1,0
	addlw 	.256 - .10

; Now, we have a number from -10 to -1 (0..9),
; we add 58 to bring it from 48 to 57 (0..9).
	addlw 	.58
	movwf 	d0

	movlw 	0x30
	xorwf 	d1,f
	xorwf 	d2,f


;********************** Kijelzés vezérlése ************************************
	movlw	0x09
	call	LCD_Line2W		; A sebesség kijelzés helyére állítja a kurzort
;	movlw	0x01
;	subwf	NULLA,W			; 0-ból kivonjuk a NULLA regiszter értékét
;	btfsc	STATUS,C		; Ha a NULLA regiszter értéke több mint 0
;	goto	Nem_megy		; akkor nullákat írunk ki a sebességhez
	movfw	d2
	call	LCD_Char
	movfw	d1
	call	LCD_Char
	movfw	d0
	call	LCD_Char
	clrf	NULLA
	goto	Kezd
Nem_megy
;	movlw	0x00			; nullákat írunk ki a sebességhez
;	call	LCD_Char
;	call	LCD_Char
;	call	LCD_Char
	goto	Kezd
;***********************Szubrutinok és szövegtáblák****************************

	
; LCD rutinok

; Alaphelyzetbe állítja az LCD-t (inicializál)


     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.
;******************************************

	org 0x0800
    
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   ' '
     retlw   'k'
     retlw   'm'
     retlw   '/'
     retlw   'h'
     retlw   0x00


     end