; ******************************************************************************
;                       Teplomer s DS18B20 a PIC 16F876A                       ;
;                                                                              ;
; Tento teplomer pouziva zapojeni az 4 cidel DS18B20 do procesoru PIC16F876A   ;
; pomoci 1-Wire sbernice, ve verzi parazitniho napajeni. Pro zobrazeni pouziva ;
; 6 sedmisegmentovych LED digitu se spolecnou anodou. Aktivace digitu i        ;
; segmentu se provadi logickou 0. Pro casovani byl zvolen krystal 4 000 000 Hz ;
; To je nutne dodrzet, pokud maji byt presne casovaci smycky pro komunikaci    ;
; s teplomerem funkcni.                                                        ;
;                                                                              ;
;                                                                              ;
;   LED zobrazovač - 7segmentové katody, jedna anoda:                          ;
;                                                                              ;
;      --a--       --a--       --a--       --a--       --a--       --a--       ;
;     |     |     |     |     |     |     |     |     |     |     |     |      ;
;     f     b     f     b     f     b     f     b     f     b     f     b      ;
;     |     |     |     |     |     |     |     |     |     |     |     |      ;
;      --g--       --g--       --g--       --g--       --g--       --g--       ;
;     |     |     |     |     |     |     |     |     |     |     |     |      ;
;     e     c     e     c     e     c     e     c     e     c     e     c      ;
;     |     |     |     |     |     |     |     |     |     |     |     |      ;
;      --d--  *o   --d--  *o   --d--  *o   --d--  *o   --d--  *o   --d--  *o   ;
;                                                                              ;
;     DIGITY ( 6 anod na PORTA )                                               ;
;     PA5:6.dgt    PA4:5.dgt   PA3:4.dgt   PA2:3.dgt   PA1:2.dgt  PA0:1.dgt    ;
;                                                                              ;
;     SEGMENTY - ( 7 katod na PORTB )                                          ;
;     PB7:'b', PB6:'f', PB5:'a', PB4:'g', PB3:'c', PB2:'o', PB1:'d', PB0:'e'   ;
;                                                                              ;
;                  PORTB bity:                   '76543210'                    ;
;                  Jmena segmentu v digitu:     b'bfagcode'                    ;
;                                                                              ;
;   Aktivace segmentu i digitu je poslanim log.0 na dany pin PORTA nebo PORTB  ;
;   Digit ma nadefinovane zobrazeni znaku "0-9", "A-Z", "-", "°" a "-"         ;
;   0-9 a A-Z se zobrazi podle jejich ASCII kodu, dalsi znaky jsou prekladany. ;
;                                                                              ;
;                                                                              ;
;   Pro spravnou funkci PIC 16F876A je treba:                                  ;
;		- mit externi oscilator                                                ;
;		- __CONFIG s definici tohoh oscilatoru ( _HS_OSC )                     ;
;		- propojeni Pinu 1 (MCLR/VPP) na VDD +5V ( proti samovolnemu resetu )  ;
;                                                                              ;
;                                                                              ;
;   Zapojeni externiho oscilatoru RC a teplomeru s parasite power              ;
;                                                                              ;
;                      +--------------------+                                  ;
;    +-----o---- Pin8  | Vss-GND    Vss-GND |  Pin19 -------------o---+        ;
;    |     |           |                    |                 Vdd |   | GND    ;
;    C 15p C 15p       |                    |                    DS18B20       ;
;    |     |           |                    |                       | DQ       ;
;    |     +---- Pin9  | OSC1/CLKI     RC0  |  Pin11 -----o---------+          ;
;    |     |           |                    |             |                    ;
;    |   Xtal 4 MHz    |                    |         R cca 4k7                ;
;    |     |           |                    |             |                    ;
;    +-----o---- Pin10 | OSC2/CLKO  Vdd+5V  |  Pin20 -----+                    ;
;                      +--------------------+                                  ;
;                             16F876A                                          ;
;                                                                              ;
;                                                                              ;
;                                                                              ;
; Licencni ujednani:                                                           ;
; Tento program a jeho casti muzete volne kopirovat, upravovat a pouzivat      ;
; pro komercni i nekomercni ucely ve smyslu licence CC-BY.                     ;
;                                                                 Trivius      ;
;                                                                              ;
; ******************************************************************************


;***** DEFINICE: DIREKTIV PROCESORU

	list      p=16f876a,R=DEC     ; list directiva prekladaci nadefinuje typ formatovani ( podle procesoru )
								  ; R=DEC zmeni ZADAVANI KONSTANT z defaultniho HEXA na DEKADICKE
	#include <p16f876a.inc>       ; vlozi soubor s definicemi specifickymi pro tento procesor
	errorlevel  -302              ; potlaci message 302


; '__CONFIG' directivy urcuji HW chovani procesoru. Nazvy pochazi z .inc souboru.
   __CONFIG   _CP_OFF & _CPD_OFF & _BODEN_OFF &              _WDT_OFF & _PWRTE_ON  & _WRT_OFF  & _HS_OSC & _LVP_OFF
;             ^ Code protection vypnuto                      ^ watchdog timer vypnout            ^ Volba ext. oscilatoru RC
;                        ^ Data protection vypnuto                     ^ PowerUp Delay Timer (udrzuje procik 72ms v resetu) zakazan 
;                                  ^ resetovat se pri zhoupnuti napajeni (brownout)                        ^ RB3 pin je std. IO ( Low voltage Programming vypnuto )

;***** DEFINICE: REGISTRY, MAKRA a KONSTANTY


; --------- KONSTANTY ---------

#define		NTE_PRERUSENI	1			; Pro SW delicku preruseni ( porovnavano s 'int_citac', preruseni projde jen kazde Nte )

; Konstanty pro HW nastaveni PINu PORTA - volba digitu ( 6..1 )
#define 	P_digit_0		PORTA,0		; 7segment digit 1
#define 	P_digit_1		PORTA,1		; 7segment digit 2
#define 	P_digit_2		PORTA,2		; 7segment digit 3
#define 	P_digit_3		PORTA,3		; 7segment digit 4
#define 	P_digit_4		PORTA,4		; 7segment digit 5
#define 	P_digit_5		PORTA,5		; 7segment digit 6

; Konstanty  pro HW nastaveni PINu PORTB - volba segmentu ( a..e )
#define 	P_segment_e		PORTB,0		; segment 0		1
#define 	P_segment_d		PORTB,1		; segment 1		2
#define 	P_segment_o		PORTB,2		; segment 2		4
#define 	P_segment_c		PORTB,3		; segment 3		8
#define 	P_segment_g		PORTB,4		; segment 4		16
#define 	P_segment_a		PORTB,5		; segment 5		32
#define 	P_segment_f		PORTB,6		; segment 5		64
#define 	P_segment_b		PORTB,7		; segment 5		128

; Konstanty  pro HW nastaveni PINu PORTC - teplomer
#define		P_18B20         PORTC,0		; Port teplomeru DS 18B20

; Konstanty pro HW nastaveni PINu PORTB ( 0 rozsveci aktivni segmenty )
;                   b'bfagcode'
#define		L0		b'00010100'
#define		L1		b'01110111'
#define		L2		b'01001100'
#define		L3		b'01000101'
#define		L4		b'00100111'
#define		L5		b'10000101'
#define		L6		b'10000100'
#define		L7		b'01010111'
#define		L8		b'00000100'
#define		L9		b'00000101'
#define		Ltecka	b'11111011'
#define		Ltma	b'11111111'
#define		Lstupen	b'00001111'
#define		Lminus	b'11101111'
#define		La		b'00000110'
#define		Lb		b'10100100'
#define		Lc		b'10011100'
#define		Ld		b'01100100'
#define		Le		b'10001100'
#define		Lf		b'10001110'
#define		Lg		b'10010100'
#define		Lh		b'00100110'
#define		Li		b'10111110'
#define		Lj		b'01110100'
#define		Lk		b'10000110'
#define		Ll		b'10111100'
#define		Lm		b'11010110'
#define		Ln		b'11100110'
#define		Lo		b'00010100'
#define		Lp		b'00001110'
#define		Lq		b'00000111'
#define		Lr		b'11101110'
#define		Ls		b'10000101'
#define		Lt		b'10011110'
#define		Lu		b'00110100'
#define		Lv		b'11110100'
#define		Lw		b'00111101'
#define		Lx		b'00100110'
#define		Ly		b'00100101'
#define		Lz		b'01001100'
;                   b'bfagcode'


; --------- REGISTRY ---------

; Pomocne registry
tmp_w			EQU		0x20		; zaloha W registru
tmp_status  	EQU		0x21		; zaloha STATUS registru
int_citac		EQU		0x22		; citaci registr sw delicky ( kazde N-te preruseni projde )
									; Preruseni je volano vzdy jednou za 256us ( 1us hodin, po 256 pretecen 8bit registr TMR0 )
									; Chceme-li volat napr. co 10ms namisto  co 256us, chceme jen kazde 39.preruseni.
									; ( 256us * 39 = 9984us = cca 10ms ). Proto potrebujeme SW delicku (konstantu a citaci registr).
w_temp			EQU		0x23		; Ulozeni WREGu pri preruseni
temp			EQU		0x24		; Pomocna viceucelova promenna

; Citace
COUNT			EQU		0x25		; Univerzalni citac cyklu
delay_citac1	EQU		0x26		; Pomocny citac ( pro smycky zpozdeni )
delay_citac2	EQU		0x27		; Pomocny citac ( pro smycky zpozdeni )
delay_citac3	EQU		0x28		; Pomocny citac ( pro smycky zpozdeni )

; teplomer
isMinus			EQU		0x29		; Priznak zaporne teploty
teplota1		EQU		0x2A		; Namerena teplota - dolni byte
teplota2		EQU		0x2B		; Namerena teplota - horni byte
bcd_100			EQU		0x2C		; hodnota teploty pro zobrazeni - Stovky
bcd_10			EQU		0x2D		; hodnota teploty pro zobrazeni - Desitky
bcd_1			EQU		0x2E		; hodnota teploty pro zobrazeni - Jednotky

; displej
dotmask			EQU		0x2F		; Maska pozadovaneho rozsviceni tecky
digit_citac		EQU		0x30		; Kruhovy citac aktualni pozice na digitu ( 6..1 pri kazdem preruseni )
digit1			EQU		0x31		; Obsag digitu - v behu se nastavi, v preruseni se zobrazi
digit2			EQU		0x32		; Obsag digitu - v behu se nastavi, v preruseni se zobrazi
digit3			EQU		0x33		; Obsag digitu - v behu se nastavi, v preruseni se zobrazi
digit4			EQU		0x34		; Obsag digitu - v behu se nastavi, v preruseni se zobrazi
digit5			EQU		0x35		; Obsag digitu - v behu se nastavi, v preruseni se zobrazi
digit6			EQU		0x36		; Obsag digitu - v behu se nastavi, v preruseni se zobrazi

tmp1			EQU		0x37		; Promenne pro pocitani CRC
tmp2			EQU		0x38		; Promenne pro pocitani CRC
crcitac			EQU		0x39		; Promenne pro pocitani CRC - citac CRC
crc				EQU		0x3A		; Promenne pro pocitani CRC - hodnota CRC

LastDiscrep		EQU		0x3B		; promenne pro ROM vycitani z 1-Wire sbernice
LastZero		EQU		0x3C		; promenne pro ROM vycitani z 1-Wire sbernice
BitMask			EQU		0x3D		; promenne pro ROM vycitani z 1-Wire sbernice
BitIndex		EQU		0x3E		; promenne pro ROM vycitani z 1-Wire sbernice
OwTemp			EQU		0x3F		; promenne pro ROM vycitani z 1-Wire sbernice

RomCOUNT		EQU		0x40		; Celkovy pocet vyctenych ROM z 1-Wire sbernice
RomCntDisp		EQU		0x41		; Aktualne zobrazeny teplomer

cblock 0x50							; Prostor pro 4 ROM IDs ( každé 8 byte )
 RomBuffer:8     				
 RomBuffer2:8     				
 RomBuffer3:8     				
 RomBuffer4:8     					; Končí posledním adresovatelným místem SFR registrů v Bank 1 ( 0x7F )
endc

; --------- MAKRA ---------

; ---- Vyber banky ----
Bank_0		MACRO
			bcf	STATUS,RP0
			bcf	STATUS,RP1
			ENDM
Bank_1		MACRO
			bsf	STATUS,RP0
			bcf	STATUS,RP1
			ENDM
Bank_2		MACRO
			bcf	STATUS,RP0
			bsf	STATUS,RP1
			ENDM
Bank_3		MACRO
			bsf	STATUS,RP0
			bsf	STATUS,RP1
			ENDM

; ---- Rezim portu ----
Tx_18B20	MACRO
			banksel	TRISC
			bcf		TRISC,0
			Bank_0
			ENDM

Rx_18B20	MACRO
			banksel	TRISC
			bsf	TRISC,0
			Bank_0
			ENDM

; ---- skoky podminene stavem registru W ----
jwz			MACRO	lbl6
			sublw	0				; 0 - 0(OK)
			btfsc	STATUS,C	   
			goto	lbl6
			ENDM
jwnz		MACRO	lbl6
			sublw	0				; 0 - 0(OK)
			btfss	STATUS,C	   
			goto	lbl6
			ENDM
; ---- skoky podminene stavem priznaku Z ----
jnz			MACRO	lbl1
			btfss	STATUS,Z           
			goto	lbl1
			ENDM
jz			MACRO	lbl2
			btfsc	STATUS,Z		; Pokud Z = 0 ( tj vysledek je nenulovy ), preskoc
			goto	lbl2			; Pokud Z=1 ( tj je vysledek nulovy ), jdi na navesti
			ENDM
; ---- skoky podminene stavem priznaku C ----
jnc			MACRO	lbl3
			btfss	STATUS,C	   
			goto	lbl3
			ENDM
jc			MACRO	lbl4
			btfsc	STATUS,C	   
			goto	lbl4
			ENDM

; ---- Prirazeni ( zdroj, cil ) ----
mov     	MACRO   SOURCE1, DEST1
			movwf	w_temp	   
			movf    SOURCE1,W
			movwf   DEST1
			movf	w_temp,w
			ENDM
mvi     	MACRO   CONST2, DEST2
			movwf	w_temp
			movlw   CONST2
			movwf   DEST2
			movf	w_temp,w
			ENDM

; ---- Rotace pres 2 registry ----
rr2f		MACRO	HReg, LReg
			bcf		STATUS, C
			btfsc	HReg,0
			bsf		STATUS, C
			rrf		LReg, F
			rrf		HReg, F
			ENDM


;***** Pocatek kodu **************************************************************

		ORG     0x000             ; Na tento vektor skoci procesor po resetu
		goto    main              ; Nutno presmerovat, protoze od 0x004 se zpracovava preruseni


;***** Sem vbehne preruseni pri preteceni TMR0 citace 
		; 4MHz krystal => 1MHz hodin => inkrementace TMR0 co 1us
		; TMR0 pretece po 256 cyklech => kazdych 256us
		; Pokud chceme mene casteji, priradime k preruseni preddelicku ( viz INTCON ) ..
		; .. a stanovime jeji pomer. Napr.pomer 4 => preruseni co 1 ms ( 4x256=1024us )
		; Pokud chceme jeste mene casteji, vytvorime SW delicku ..
		; .. a reagujeme jen na N-te preruseni

		; Provedeme zalohu registru W a STATUS
		ORG     0x004            	; Na tento vektor skoci procesor pri preruseni
		movwf   tmp_w            	; zaloha registru W
		movf	STATUS,W         	; STATUS -> W
		movwf	tmp_status       	; zaloha registru W

		; Pokud to je n-te preruseni (tj kazdych x ms), pokracuj. Jinak opust preruseni.
		incf	int_citac,F			; inkrementuj registr F (SW delicky preruseni); Vysledek uloz zpet do F
		movlw	NTE_PRERUSENI		; N-te -> W
		subwf	int_citac,W			; W = int_citac - NTE_PRERUSENI
		btfss	STATUS,C			; kdyz nepreteklo (C bit je 1. bit STATUS), preskoc nasledujici
		goto	ven					; Neni to Nte preruseni, vrat se
		clrf	int_citac			;   Je to Nte preruseni, vynuluj citac a pokracuj


		;Tady_zacina_obsluzny_kod_preruseni
		mvi		Ltma,PORTB			; Tma na vsech segmentech
		; digity - najde dalsi digit
		call	najdi_dalsi_digit	; posun se na nasledujici digit a aktivuj ho ( ost. zhasni )
		movwf	PORTA				; ( 6-5-4-3-2-1   6-5-... )
		; segmenty - nacte obsah digitu
		movf	digit_citac, W		; Podle aktivniho digitu ( mezi 1..6 )
		call	najdi_obsah_digitu	; zjisti jaky znak je pro nej pozadovan, a preved ho na 7segm -> W
		movwf	PORTB           	; Posle obsah na sbernici segmentu		
		; Tady_konci_obsluzny_kod_preruseni

ven
		; rusime priznak preruseni (zase se sam nahodi pri preteceni timeru 0)
		bcf		INTCON,T0IF		
  
		; Provedeme obnoveni registru W a STATUS
		movf    tmp_status,W     	; obnov puvodni STATUS registr
		movwf	STATUS            	; 
		swapf   tmp_w,F
		swapf   tmp_w,W          	; Obnov puvodni W registr

		; Vracime se z preruseni
		retfie                    	; return from interrupt



; ******************************
; Utility kt. pouzivaji "addwf PCL,F" nutno umistit co nejvys
; Abychom se vyhnuli strankovani PCL mezi bankami ( jinak je krome PCL jeste treba osetrovat PCLATH )

najdi_dalsi_digit
; Snizi cislo aktivniho digitu o 1 ( Pri 0 nastavi zase 6 )
		;	Vstup:  digit_citac
		;	Vystup: W = bitova maska aktivniho digitu ( pro PORTA )
		;         digit_citac = digit_citac - 1

		movlw	6				; nejvyssi mez = 6  ( bude nastavena, pokud se digit_citac snizi na 0 )
		decfsz	digit_citac,F	; digit_citac --
		movf	digit_citac,W	; W = digit_citac		( pri nule bude navrat k puvodni hodnote preskocen a W = 6 )
		movwf	digit_citac		; digit_citac = W  ( dekrementovany, nebo 6 )

		movlw	b'111'			; 
		andwf	digit_citac,w	; Do W uloz prvni 3 bity citace
		movwf	digit_citac
		addwf	PCL,F
		retlw	0			; nenastane
		retlw	b'00111110'	; digit 1
		retlw	b'00111101'	; digit 2
		retlw	b'00111011'	; digit 3
		retlw	b'00110111'	; digit 4
		retlw	b'00101111'	; digit 5
		retlw	b'00011111'	; digit 6
		retlw	255			; nenastane

		return

najdi_obsah_digitu
		; Podle cisla digitu najde obsah ( v glob. promennych digit1..digit6 )
		;	Vstup:  Cislo digitu ( 1..6 )
		;	Vystup: Bitova maska znaku ( pro 7segment. digit )
		addwf	PCL,F
		nop				; digit 0 neexistuje
		goto	dig1	; digit 1
		goto	dig2	; digit 2
		goto	dig3	; digit 3
		goto	dig4	; digit 4
		goto	dig5	; digit 5
		goto	dig6	; digit 6
dig1
		movf	digit1, W
		call	char_na_segmenty	
		btfsc	dotmask,0
		andlw	b'11111011'
		goto	ven_digit
dig2
		movf	digit2, W
		call	char_na_segmenty
		btfsc	dotmask,1
		andlw	b'11111011'
		goto	ven_digit
dig3
		movf	digit3, W
		call	char_na_segmenty
		btfsc	dotmask,2
		andlw	b'11111011'
		goto	ven_digit
dig4
		movf	digit4, W
		call	char_na_segmenty
		btfsc	dotmask,3
		andlw	b'11111011'
		goto	ven_digit
dig5
		movf	digit5, W
		call	char_na_segmenty
		btfsc	dotmask,4
		andlw	b'11111011'
		goto	ven_digit
dig6
		movf	digit6, W
		call	char_na_segmenty		
		btfsc	dotmask,5
		andlw	b'11111011'
		goto	ven_digit

ven_digit
		return


bit4_na_ascii
		; W < 10?
		movwf	temp
		sublw	9		; W = 9 - W  ( C=0 pri - .. pismena )
		jnc		pismena
		movf	temp, W
		addlw	48	; Mensi nez 10 - cisla
		return
pismena	movf	temp, W
		addlw	55	; Vetsi nez 10 - pismena
		return

char_na_segmenty
		; Prevede Kod znaku na segmenty
		;	Vstup:  ASCII kod znaku v W 
		;	Vystup: Bitova maska znaku pro 7segment. digit
		sublw	90
		addwf	PCL,F
		retlw	Lz	
		retlw	Ly
		retlw	Lx
		retlw	Lw
		retlw	Lv
		retlw	Lu
		retlw	Lt
		retlw	Ls
		retlw	Lr
		retlw	Lq
		retlw	Lp
		retlw	Lo
		retlw	Ln
		retlw	Lm
		retlw	Ll
		retlw	Lk
		retlw	Lj
		retlw	Li
		retlw	Lh
		retlw	Lg
		retlw	Lf
		retlw	Le
		retlw	Ld
		retlw	Lc
		retlw	Lb
		retlw	La
		retlw	Lstupen		; @				
		retlw	Ltma		; ?
		retlw	Ltma		; >				
		retlw	Lminus		; =				
		retlw	Ltma		; <				
		retlw	Ltma		; ;				
		retlw	Ltma		; :				
		retlw	L9
		retlw	L8
		retlw	L7
		retlw	L6
		retlw	L5
		retlw	L4
		retlw	L3
		retlw	L2
		retlw	L1
		retlw	L0
		return


desetiny
		addwf	PCL, F
		retlw	0	; 0
		retlw	1	; 1		0.0625	°C
		retlw	1	; 2		0.125	°C
		retlw	2	; 3		0.1875	°C
		retlw	3	; 4		0.25	°C
		retlw	3	; 5		0.3125	°C
		retlw	4	; 6		0.375	°C
		retlw	4	; 7		0.4375	°C
		retlw	5	; 8		0.5		°C
		retlw	6	; 9		0.5625	°C
		retlw	6	; A		0.625	°C
		retlw	7	; B		0.6875	°C
		retlw	8	; C		0.75	°C
		retlw	8	; D		0.8125	°C
		retlw	9	; E		0.875	°C
		retlw	9	; F		0.9375	°C
		return


;***** Hlavni smycka
main

; nastaveni HW procesoru

		; GPIO piny - nulovani, nastaveni jako digitalni ( nikoliv jako komparator )
		Bank_0
		mvi	b'11111111',PORTA	; PORTA registr = 1 => Nastaveni vsech PORTA pinu
		mvi	b'11111111',PORTB	; PORTA registr = 1 => Nastaveni vsech PORTB pinu
		mvi	b'11111111',PORTC	; PORTA registr = 1 => Nastaveni vsech PORTC pinu

		; PORT A-C Piny - urceni ktere jsou vstupni/vystupni
		Bank_1
		mvi b'00000111',CMCON	; bity 2,1,0 : GP2,GP1,GP0 = 111 - nastavi PORTA jako digital IO, ( kdyby 000 - nastavi jako komparator )
		mvi	b'00000110',ADCON1	; Configure all pins as digital inputs
		mvi	b'00000000',CVRCON	; Configure all pins as digital inputs

		mvi	b'00000000',TRISA 	; Nastav Pa<5-0> jako vystupy. bity urcuji ktery Pa pin ( xx543210 )			- OUT - ktery displej
		mvi	b'00000000',TRISB 	; Nastav Pa<7-0> jako vystupy. bity urcuji ktery Pb pin ( 76543210 )			- OUT - ktery segment v displeji
		mvi b'11000000',TRISC 	; Nastav Pa<7-6> jako vstupy.  bity urcuji ktery Pb pin ( 76543210 ) 		- IN - tlacitko ( ext. pull-up nutny )

		Bank_0
		clrf 	TMR0 			; Clear TMR0 and prescaler

		;Hodiny timeru T0 = 1MHz; WDT s preddelickou 1:128 
		;  (WD typicky co 17ms(datasheet 9.6.1 - WDT period) x 128 ... co 2,2s)
		Bank_1
		mvi	b'10000010',OPTION_REG 	; bity 2,1,0 : PS2,PS1,PS0 = 011 - pomer Preddelicky 1:8
									; bit 3 : PSA = 0 (Prescaler Assignment bit) 
									;   	=> Preddelicka je prirazena k timeru ( ne k watchdogu ) 256us * 8 = 2ms
									; bit 4 : T0SE = 0 (TMR0 Source Edge Select bit) 
									;		=> Inkrementuj timer pri zmene hodin. signalu z log. 0 -> log. 1
									; bit 5 : T0CS = 0 (TMR0 Clock Source Select bit)
									;		=> Zdroj hodinoveho signalu je z vnitrnich hodin, ne z pinu
									; bit 6 : INTEDG = 0 (Interrupt Edge Select bit)
									;		=> Preruseni probehne na sestupnou hranu
									; bit 7 : !GPPU = 1 (GPIO Pull-up Enable bit)
									;		=> Uziti GPIO PullUp rezistoru je zakazano
		Bank_0


; Pocatecni podminky

		;Globalne povoli presruseni; povoli interni preruseni pri preteceni TMR0 registru (citace)
		mvi	b'10100000',INTCON		; bit 7 - GIE - Global Interrupt Enable bit
									;       - 1: povoluje vsechna preruseni
									; bit 6 - PEIE - Peripheral Interrupt Enable bit
									;       - 1: povoluje int z periferii (AD prevodnik, Komparator, T1G pin - viz PIE1 registr )
									; bit 5 - T0IE - TMR0 Overflow Interrupt Enable bit ( 1 povoluje preruseni, 0 zakazuje )
									;       - 1: povoluje interni preruseni, pokud pretece TMR0
									; bit 4 - INTE - GP2/INT External Interrupt bit
									;       - 1: povoluje externi preruseni z GP2/INT pinu (OPTION_REG INTEDG bit urci nabeznou hranu)
									; bit 3 - GPIE - Port Change Interrupt Enable bit
									;       - 1: povoluje preruseni, pokud doslo ke zmene na GPIO portech
									; bit 2 - T0IF - TMR0 Overflow Interrupt Flag bit
									;       - 1: TMR0 registr pretekl ( v obsluze preruseni musi byt znulovan )
									; bit 1 - INTF - GP2/INT External Interrupt Flag bit
									;		- 1: Vyskytlo se GP2/INT externi preruseni ( v obsluze preruseni musi byt znulovan )
									; bit 0 - GPIF - Port Change Interrupt Flag bit
									;		- 1: Alespon jeden GPIO port zmenil stav ( v obsluze preruseni musi byt znulovan )
									; GIE  povoleno (globalne povoleno), 
									; T0IE povoleno (preruseni navazano na preteceni timer registru TMR0)
									; T0IF flag znulovan
		mvi		7,digit_citac		; Kruhovy citac aktualniho digitu [6..1]. Pri prvnim pruchodu se snizi na 6 ( digit vlevo )
		mvi		0,dotmask			; Maska digitu ( pro rozsvicene desetinne tecky ). xx000000 ( bit0 = digit1, bit5=digit6 )





; Hlavni cyklus




; Smycka cekani na zarizeni, problikava "------"
nulujdisp
		mvi		0, dotmask			; Zhasni desetinne tecky
		mvi		'=',digit6			; Na 0.5s Zobraz pomlcky
		mvi		'=',digit5
		mvi		'=',digit4
		mvi		'=',digit3
		mvi		'=',digit2
		mvi		'=',digit1
		call	wait_500ms
		mvi		'?',digit6			; Na 0.5s zhasni digity
		mvi		'?',digit5
		mvi		'?',digit4
		mvi		'?',digit3
		mvi		'?',digit2
		mvi		'?',digit1
		call	wait_500ms			; cekej 0.5s
		call	reset_18B20			; ; test pritomnosti 1-Wire zarizeni
		jwnz	nulujdisp			; W=0: OK,   W=1: prazdne

; Vypis vsech nalezenych ROM IDs
ZacniVypis
		mvi		0,dotmask			; Zhasni desetinne tecky
		mvi		0,RomCOUNT			; Nuluj pocet 1-Wire zarizeni ( resp. jejich ROM IDs)

		; Zobraz Zpravu "ROM-0x"
UkazRomIDs
		mvi		'R',digit6			
		mvi		'O',digit5
		mvi		'M',digit4
		mvi		'=',digit3
		mvi		'0',digit2
		movf	RomCOUNT,W
		call	bit4_na_ascii
		movwf	digit1
		call	wait_1500ms			; cekej 1.5s

		; Nacti jedno ROM ID do FSR
		movf	RomCOUNT,F			; Pokud je RomCOUNT>0
		jnz		OwNext				; Zavolej OwSearchNext
		call	OwSearch			; Jinak zavolej OwSearch (jde o 1.pruchod)
		goto	UkazRomID			; a po nacteni RomID do FSR pokracuj v jeho zobrazeni
OwNext	call	OwSearchNext		; Na dalsi pruchody volej OwSearchNext

		; K nactenemu RomID zobraz vsech 8 bytu ( na 6digu vzdy po 3 bytech )
UkazRomID
		bcf		STATUS,C			; Vynasob citac poctu RomIDs 8mi
		rlf		RomCOUNT			; ( hodi se dal, kdy muzeme pricist 8 bytu k FSR )
		rlf		RomCOUNT
		rlf		RomCOUNT

				; Zobraz 1. 3 byte a cekej 1.5s
		movlw	RomBuffer			; W = RomBuffer + COUNT
		addwf	RomCOUNT,W			; prvni trojici Byte z ROM ID ..
		call	ukaz_3Byte_FSR		; .. ukaz na displeji
		call	wait_1500ms			; cekej 1.5s

				; Zobraz 2. 3 byte a cekej 1.5s
		movlw	RomBuffer			; W = RomBuffer + COUNT
		addwf	RomCOUNT,W
		addlw	3					; druhou trojici Byte z ROM ID ..
		call	ukaz_3Byte_FSR		; .. ukaz na displeji
		call	wait_1500ms			; cekej 1.5s

				; Zobraz 3. 3 byte a cekej 1.5s
		movlw	RomBuffer			; W = RomBuffer + COUNT
		addwf	RomCOUNT,W				
		addlw	6					; treti trojici Byte z ROM ID ..
		call	ukaz_3Byte_FSR		; .. ukaz na displeji
		mvi		'?',digit2			; Namisto devateho byte ..
		mvi		'?',digit1			; .. zhasni oba posledni digity
		call	wait_1500ms			; cekej 1.5s

		bcf		STATUS, C			; Vrat zpatky nasobeni RomCOUNT
		rrf		RomCOUNT			; ( at dostaneme zpatky citac poctu RomIDs v jednotkach )
		rrf		RomCOUNT
		rrf		RomCOUNT

		movf	LastDiscrep,F		; Pokud je LastDiscrep=0, je tato adresa posledni.
		jz		smycka				; Tehdy opust nacitani a jdi dal k mereni

		incf	RomCOUNT,F			; Zvys RomCOUNT o 1
		btfss	RomCOUNT,2			; pokud jsme dosahli 4-teho 1-Wire zarizeni, opust nacitani a jdi dal na mereni
		goto	UkazRomIDs			; Nebyla to posledni ROM a neni to 4-te 1-Wire zarizeni, tak 




; -------- MERENI TEPLOTY NA DS18B20 --------------

smycka

	; test pritomnosti teplomeru
		call	reset_18B20		; W=0: OK,   W=1: ERR
		jwnz	nulujdisp		;  = 0 -> c=1(nula nebo kladne)

		mvi		0,RomCntDisp

; Zacni merit a ukazovat		
MerZas	call	MerNaCidle
		jwz		MerOK
		call	DispTemp_CRC
		goto	MerFin
MerOK	call	DispTemp_dec
MerFin	call	wait_500ms		; Ponech 0.5s udaje zobrazeny
		incf	RomCntDisp,F	; Zvys citac zobrazenych cidel
		movf	RomCntDisp,W	; Pokud je citac zobrazenych cidel..
		subwf	RomCOUNT,W		; .. vetsi nez citac existujicich cidel,
		jnc		smycka			; opust zobrazovani
		goto	MerZas			; jinak jdi na zmereni a yobrayeni dalsiho cidla




; ****************
; Utility displeje


DispTemp_dec
; Zobrazeni teploty v dec
; Nastavi digit6..digit1 pode teploty v teplota1,teplota2
		; Vstup: teplota1 - teplota ( mantisa )
		; Vstup: teplota2 - teplota ( bit7..bit4: desetinny rozvoj, bit3..bit0: znamenko )
		; Vystup: digit6..digit1  ( x - # #.# ° ) - dekadicky
		;         obsazeni digitu ( 6 5 4 3 2 1 )

		mvi	b'00000100',dotmask		; Na digitu3 rozsvecej desetinnou tecku 

		; Digit 6 - Poradi teplomeru
		movf	RomCntDisp,W
		call	bit4_na_ascii	
		movwf	digit6				; Priprav k zobrazeni digit6 - ID mereneho teplomeru


		movf	teplota1, W			; Preved cislo v teplota1 na 3 cislice
		call	Hex_BCD				; ( napln bcd_100, bcd_10, bcd_1 )

		; Digit 5 - stovky
		movf	bcd_100,W				; Priprav k zobrazeni digit6 ( stovky )
		jz		skryj3				;   bcd_100=0 ? : nerozsvecej
		call	bit4_na_ascii		;   bcd_100=[0..9] ? : preved na ascii kod
		goto	di_dal3				;   a pozaduj jeho zobrazeni
skryj3	movlw	'?'
di_dal3	movwf	digit5				;   Nastav pozadovanou cislici

		; Digit 4 - desitky
		movf	bcd_10,W				; Priprav k zobrazeni digit5 ( desitky )
		jz		skryj2				;   bcd_10=0 ? : nerozsvecej
		call	bit4_na_ascii		;   bcd_10=[0..9] ? : preved na ascii kod
		goto	di_dal2				;   a pozaduj jeho zobrazeni
skryj2	movlw	'?'					;
di_dal2	movwf	digit4				;   Nastav pozadovanou cislici

		; Digit 3 - jednotky
		movf	bcd_1,W				; Priprav k zobrazeni digit4 ( jednotky )
		call	bit4_na_ascii		;   preved na ascii kod
		movwf	digit3				;   Nastav pozadovanou cislici

		; Digit 2 - desetiny 		( Vyssi nibble z teplota2 )
		mov		teplota2, temp		; Priprav k zobrazeni digit3 ( desetiny )
		rrf		temp				;   Je treba vzit z teplota2 horni 4 bity
		rrf		temp				;
		rrf		temp				;
		rrf		temp				;
		movlw	0x0f				;	a odstranit pripadne bity znaminka
		andwf	temp, W				;
		call	desetiny			;   [ 0..F ] je treba prevest na [ 0..9 ]
		call	bit4_na_ascii		;   preved na ascii kod
		movwf	digit2				;   Nastav pozadovanou cislici

		; Digit 1 - stupne
		mvi		'@',digit1			; Priprav k zobrazeni digit3 ( napevno znak ° ) 
		
		; Znamenko
		btfss	isMinus, 0			; Pokud neni pozadovano znaminko, opust
		return		
		movf	bcd_10,F			; Pokud na desitkach neni nula,
		jnz		Setbcd_100			; jdi na psani znaminka do stovek
Setbcd_10	
		mvi		'=',digit4			; jinak pis znaminko - do desitek ( jednotky neres, maji v digitu cislo vzdy )
		return
Setbcd_100
		mvi		'=',digit5			;  Nastav znamenko - do stovek
		return


DispTemp_CRC
; Zobrazeni chyby CRC
		mvi		0, dotmask			; Zhasni desetinne tecky
		movf	RomCntDisp,W
		call	bit4_na_ascii		
		movwf	digit6
		mvi		'?',digit5			; Zobraz chybu
		mvi		'?',digit4
		mvi		'C',digit3
		mvi		'R',digit2
		mvi		'C',digit1
		return


; ********************
; Matematicke Utility 

Hex_BCD
; Prevede cislo ve W na cislice
		; vstup: W [ 00..FF ]
		; vystup: bcd_100 [0..9], bcd_10 [0..9], bcd_1 [0..9]

		movwf	bcd_1				; Vstup do bcd_1
		mvi		0xff, bcd_10		; Init citacu desitek
		mvi		0xff, bcd_100		; Init citacu stovek
		movlw	10					; Init delitele
	desitky
		incf	bcd_10				; zvedni desitky ( prvne na 0 )
		subwf	bcd_1,F				; bcd_1 = bcd_1 - 10; pri zapornem vysledku c=0, pri kladnem c=1
		btfsc	STATUS, C			; Preskoc, je-li zaporne
		goto	desitky				; Jinak opakuj odecet
		addwf	bcd_1,F				; Odecet co vedl do minusu vrat
	stovky
		incf	bcd_100				; zvedni desitky ( prvne na 0 )
		subwf	bcd_10,F			; bcd_10 = bcd_10 - 10; pri zapornem vysledku c=0, pri kladnem c=1
		btfsc	STATUS, C			; Preskoc, je-li zaporne
		goto	stovky				; Jinak opakuj odecet
		addwf	bcd_10,F			; Odecet co vedl do minusu vrat
		return

rotuj_o_4		
; Kruhova 16bitová rotace o 4 bity vpravo		
		; vstup: teplota1,2			; Puvodne [ ---- -TTT ] [ TTTT tttt ]		t = bit desetiny, T = bit mantisy
		; vystup: teplota1,2		; Finalne [ tttt ---- ] [ -TTT TTTT ]		- = Znaminkove bity pro doplnek
		rr2f	teplota2, teplota1	; Rotuj 16bit cislo v teplota2;teplota1 doprava o jednu
		rr2f	teplota2, teplota1	; Rotuj 16bit cislo v teplota2;teplota1 doprava o jednu
		rr2f	teplota2, teplota1	; Rotuj 16bit cislo v teplota2;teplota1 doprava o jednu
		rr2f	teplota2, teplota1	; Rotuj 16bit cislo v teplota2;teplota1 doprava o jednu
		return
		
ZaporneNaKladne
; Aby bylo mozno zobrazit na displeji jako kladne, prevadi zaporna cisla z Dvojkového doplňkového kódu na Přímý kód
 		;            teplota2         teplota1
		;		 	[ tttt ---- ] [ -TTT TTTT ]
 		; Vstup:    [ 1111 1111 ] [ 1111 1111 ] -0.0625 °C v dvojkovém doplňkovém kódu, isminus = 0
		; Vystup: 	[ 0001 0000 ] [ 0000 0000 ] -0.0625 °C v přímém kódu, isminus = 1

		; Je cislo kladne?
		mvi		0,isMinus			; Cislo je kladne, pokud test nevyvrati
		btfss	teplota1,7			; Test - je cislo zaporne?
		return						; Ne, ponech priznak isMinus=0 a vrat se
		mvi		1,isMinus			; Ano, cislo je zaporne, nastav priznak isMinus=1

		; Ma zaporne cislo desetiny?
		movlw	0xF0				; odstranim ostatni bity v teplota2
		andwf	teplota2,F				
		jz		DesetinyNejsou		; Zbylo v desetinach nejake cislo?

DesetinyJsou						; Ano, je treba zpracovat jak desetiny, tak mantisu
		swapf	teplota2,F				; Prohodim nibbles v teplota2
		decf	teplota2,F				; Snizim a zneguji teplota2
		movlw	b'00001111'
		xorwf	teplota2,F
		swapf	teplota2,F				; Prohodim nibbles v teplota2 na puvodni poradi
		movlw	b'11111111'
		xorwf	teplota1,F				; Zneguji teplota1
		return
DesetinyNejsou						; Ne, v desetinach nic neni, je treba zpracovat jen mantisu
		decf	teplota1,F
		movlw	0xFF
		xorwf	teplota1,F
		return



; ******************************
; Utility Teplomeru


	; Iniciuj mereni
MerNaCidle
		; Match ROM
		movlw   0x55			; cmd "Match ROM"
		call	pis_18B20
		movf	RomCntDisp,W	; Vezmi jen aktualni ROM, ostatni at mlci az do resetu 
		call	pis_18B20_ROM


		; zmerit teplotu a zapsat do sratchpadu
		movlw	0x44			; cmd Convert T ( prikaz pro nacteni teploty do 2-byte registru; DS18S20 odesle )
		call	pis_18B20		; temperature convert  command  		
	    						
		; Cekat na nabiti pri Parasite temp
		call	wait_1500ms		; Aby se nabil parazitni kondik, cekej cca 1 s
		
	; Vycti data

		; 18B20 Init - uvolni 
		call	reset_18B20		; W=0: OK,   W=1: ERR

		movlw   0x55			; cmd "Match ROM"
		call	pis_18B20
		movf	RomCntDisp,W	; Vezmi jen aktualni ROM, ostatni at mlci az do resetu 
		call	pis_18B20_ROM
		

		; 18B20 WR cmd: Cti ze sratchpadu
		movlw	0xBE			; cmd "READ SCRATCHPAD"
    	call	pis_18B20		;READ temperature command

		clrf    crc

		; 18B20 RD
    	call	cti_18B20		;Cti scratchpad B1 - TEMPERATURE LSB
		call	DejCRC
    	mov		temp, teplota1

    	call	cti_18B20		;Cti scratchpad B2 - TEMPERATURE MSB
		call	DejCRC
    	mov		temp, teplota2

    	call	cti_18B20		; Cti scratchpad 			B3 - TH/USER BYTE 1
		call	DejCRC			; jen z nej pocitame CRC
    	call	cti_18B20		; Cti scratchpad 			B4 - TL/USER BYTE 2
		call	DejCRC			; jen z nej pocitame CRC
    	call	cti_18B20		; Cti scratchpad 			B5 - CONFIG ( bit5,6 - presnost )
		call	DejCRC			; jen z nej pocitame CRC
    	call	cti_18B20		; Cti scratchpad 			B6 - reserved
		call	DejCRC			; jen z nej pocitame CRC
    	call	cti_18B20		; Cti scratchpad 			B7 - reserved
		call	DejCRC			; jen z nej pocitame CRC
    	call	cti_18B20		; Cti scratchpad 			B8 - reserved
		call	DejCRC

    	call	cti_18B20		; Cti scratchpad B9 - CRC
		call	DejCRC
		xorwf	crc,W    	; CRC Kontrola
		jz		TempOK			; Pokud OK, pokracuj

		call	reset_18B20		; Uvolni Match ROM hluchotu ostatnich zarizeni			
		call	wait_500ms
		retlw	1

TempOK
		call	reset_18B20		; Uvolni Match ROM hluchotu ostatnich zarizeni
		;clrf 	TMR0
		;bcf	INTCON,5
		call	rotuj_o_4		; [ ---- -TTT ] [ TTTT tttt ]  =>  [ tttt ---- ] [ -TTT TTTT ]
								; teplota2 ma desetiny, teplota1 ma mantisu

		call	ZaporneNaKladne	; Prevede z dvojkového doplňkového kódu na Přímý kód, a naplni spravne isMinus registr.
		retlw	0






; ----- Reset ------

reset_18B20
		;clrf 	TMR0
		bcf		INTCON,5
		Tx_18B20				; TRISC,0 = 0 : Rezim vysilani 
		bcf		P_18B20			; PORTC,0 - Stahni k 0
		call	wait_480		;  480us
		Rx_18B20				; TRISC,0 = 1 : Rezim prijmu
		call	wait_70			;
		btfsc	P_18B20			; Pokud zarizeni existuje ( PORTC.0 stazen k 0 ), preskoc
		goto	neex
		call	wait_410
		bsf		INTCON,5
		retlw	0				; ERR ( zarizeni nenalezeno)
neex	call	wait_410
		bsf		INTCON,5
		retlw	1				; OK ( zarizeni existuje)
		return

; ----- Psani ------

pis_18B20_ROM
		movwf	temp			; kolikate 1-Wire zarizeni< ( 0..3 )
		bcf		STATUS, C		; Preved na 8
		rlf		temp
		rlf		temp
		rlf		temp
		movf	temp,W
		addlw	RomBuffer		; Pricti k pozici dane v RomBuffer
		; byte 0
		movwf	FSR				; Podle W nastav ukazatel FSR
	 	movf	INDF,W			; nacti INDF registr pod FSR ukazatelem do W
		call	pis_18B20
		; byte 1
		incf	FSR
	 	movf	INDF,W			; nacti INDF registr pod FSR ukazatelem do W
		call	pis_18B20
		; byte 2
		incf	FSR
	 	movf	INDF,W			; nacti INDF registr pod FSR ukazatelem do W
		call	pis_18B20
		; byte 3
		incf	FSR
	 	movf	INDF,W			; nacti INDF registr pod FSR ukazatelem do W
		call	pis_18B20
		; byte 4
		incf	FSR
	 	movf	INDF,W			; nacti INDF registr pod FSR ukazatelem do W
		call	pis_18B20
		; byte 5
		incf	FSR
	 	movf	INDF,W			; nacti INDF registr pod FSR ukazatelem do W
		call	pis_18B20
		; byte 6
		incf	FSR
	 	movf	INDF,W			; nacti INDF registr pod FSR ukazatelem do W
		call	pis_18B20
		; byte 7
		incf	FSR
	 	movf	INDF,W			; nacti INDF registr pod FSR ukazatelem do W
		call	pis_18B20
		return

pis_18B20
		;clrf	TMR0			; Inicializace ( oddaleni preruseni, psany byte, citac bitu )
		bcf		INTCON,5
	    movwf	temp			; w ( byte k zapisu ) -> temp ( bude rotovat )
		mvi		0x08,COUNT		; budu prochazet vsech 8 bitu       	
	    bcf		STATUS,C		; Nuluj Carry bit	

  WRST  rrf		temp,1			; Rotace temp, nejpravejsi bit do C
		jnc		WR_0			; Testuj C, jestli ma data 0 nebo 1
	    call	bit_pis1_18B20	; PIS 1
	    goto	WREND
  WR_0	call	bit_pis0_18B20	; PIS 0	

  WREND decfsz	COUNT,f			; Sniz COUNT a pokud je 0, vrat se
	    goto	WRST
		bsf		INTCON,5
	    return

bit_pis1_18B20
		;clrf	TMR0
		bcf		INTCON,5
		Tx_18B20				; PORTC,0 - Rezim vysilani 
		bcf		P_18B20			; PORTC,0 - Stahni k 0
		call	wait_6			; 6us
		Rx_18B20				; PORTC,0 - Rezim prijmu, pull-up rezistor vytahne k 1
		call	wait_64			; 64us
		bsf		INTCON,5
		return

bit_pis0_18B20
		;clrf	TMR0
		bcf		INTCON,5
		Tx_18B20				; PORTC,0 - Rezim vysilani 
		bcf		P_18B20			; PORTC,0 - Stahni k 0
		call	wait_60			; 60us
		Rx_18B20				; PORTC,0 - Rezim prijmu, pull-up rezistor vytahne k 1
		call	wait_10			; 10us
		bsf		INTCON,5
		return

; ----- Cteni ------

cti_18B20
		;clrf	TMR0			; Inicializace ( oddaleni preruseni, citac bitu )
		bcf		INTCON,5
		mvi		0x08,COUNT		; budu prochazet vsech 8 bitu       	

  RD_ST	Tx_18B20				; nuluj TRISC.0 ( PORTC.0 je OUT )
	    bcf		P_18B20			; PORTC.0 = 0 ( first pull low data line )
		call	wait_6			; 6us

		Rx_18B20				; nastav TRISC.0 ( PORTC.0 je IN )
		call	wait_9			; 9us

	    bsf		STATUS,C		; C = 1
	    btfss	P_18B20			; Nacti do C stav data pinu teplomeru
	    bcf		STATUS,C		; - pokud byl 0, pak C=0
		call	wait_55			; 55us

	    rrf		temp,F			; Posun C do temp
	    decfsz	COUNT,F			; Sniz COUNT a pokud je 0, vrat se ( nacteno vsech 8 bitu )
	    goto	RD_ST
		movf	temp,W			; Pro potrebu CRC dej temp i do W
		bsf		INTCON,5
	    return

bit_cti_18B20
		;clrf	TMR0
		bcf		INTCON,5

		Tx_18B20				; PORTC,0 - Rezim vysilani 
		bcf		P_18B20			; PORTC,0 - Stahni k 0
		call	wait_6			; 6us

		Rx_18B20				; PORTC,0 - Rezim prijmu
		call	wait_9			; 9us
		btfsc	P_18B20			; Zjisti nacteny bit
		goto is1				; Byla nactena 1
		goto is0				; Byla nactena 0

is1		call	wait_55			; 55us
		bsf		STATUS, C
		bsf		INTCON,5
		retlw	1				; vrat nacteny bit v C a ve W

is0		call	wait_55			; 55us
		bcf		STATUS, C
		bsf		INTCON,5
		retlw	0				; vrat nacteny bit v C a ve W

		return


; ----- Presna cekani x us ------
; (Xtal 4MHz = 1us na instr.cyklus ) 

wait_480
		call	wait_70
		call	wait_70
		call	wait_70
		call	wait_70
		call	wait_70
		call	wait_70
		call	wait_56
		return

wait_70
        movlw 	16
        movwf 	delay_citac1
ddd		;clrf	TMR0
		nop
        decfsz 	delay_citac1,F
        goto 	ddd
		nop
		return

wait_410
		call	wait_70
		call	wait_70
		call	wait_70
		call	wait_70
		call	wait_70
		call	wait_56
		return

wait_64
        movlw 	14
        movwf 	delay_citac1
fff		;clrf	TMR0
		nop
        decfsz 	delay_citac1,F
        goto 	fff
		nop
		nop
		nop
		return

wait_6	;clrf	TMR0
		nop
		nop
		return

wait_9	;clrf	TMR0
		nop
		nop
		nop
		nop
		nop
		return

wait_10	call	wait_6
		return
		
wait_60
		call	wait_56
		return

wait_55
        movlw 	12
        movwf 	delay_citac1
ggg		;clrf	TMR0
		nop
        decfsz 	delay_citac1,F
        goto 	ggg
		nop
		nop
		return

wait_56
        movlw 	12
        movwf 	delay_citac1
eee		;clrf	TMR0
		nop
        decfsz 	delay_citac1,F
        goto 	eee
		nop
		nop
		nop
		return

wait_500ms
        movlw 	0x03
        movwf 	delay_citac3
        movlw 	0x8a
        movwf 	delay_citac2
        movlw 	0x56
        movwf 	delay_citac1
        decfsz 	delay_citac1,F
        goto 	$-1
        decfsz 	delay_citac2,F
        goto	$-3
        decfsz	delay_citac3,F
        goto	$-5
		return

wait_1000ms
		call	wait_500ms
		call	wait_500ms
		return

wait_1500ms
		call	wait_500ms
		call	wait_500ms
		call	wait_500ms
		return

; ----- CRC ------
; VSTUP:	W, crc
; VYSTUP:	crc ( nove spoctene podle W )
DejCRC	movwf	tmp2
		movlw	8
		movwf	crcitac
		movf	tmp2,W
loop	xorwf	crc,W
		movwf	tmp1
		rrf		tmp1,W
		movf	crc,W
		btfsc	STATUS,0
		xorlw	b'00011000'
		movwf	tmp1
		rrf		tmp1,W
		movwf	crc
		bcf		STATUS,0
		rrf		tmp2,F
		movf	tmp2,W
		clrwdt
		decfsz	crcitac,F
		goto	loop
		return


; ------ Search ROM ------
; Nacte do neprimeho registru RomBuffer hodnotu ROM ID
; VYSTUP:	RomBuffer s obsahem ROM ID
 OwSearch  						; Inspirovano podle https://www.microchip.com/forums/m622854-print.aspx, autorem prispevku K8LH. Diky.
		clrf	TMR0
		clrf	LastDiscrep     ; inicializuj LastDiscrepency ( Vysledek posledni namerene nejednoznacnosti )
		movlw	RomBuffer       ; nastav FSR ukazatel na INDF registr ..
		movwf	FSR             ; .. na pocatek prostoru, rezervovaneho pro ROM IDs
 OwSearchNext
		clrf	BitIndex        ; BitIndex = 0
		clrf	LastZero        ; LastZero = 0
		movlw	b'00000001'     ;
		movwf	BitMask         ; nastav bitovou masku aktualni polohy v RomArray
		call	reset_18B20	  	; posli reset pro vsechna 1-Wire zarizeni
		movlw	0xF0			; posli prikaz "Search ROM"
		call	pis_18B20
 GetBits
		clrf	TMR0
		call	bit_cti_18B20   ; nacti bit A do Carry
		rlf		OwTemp,F        ; F = -------A
		call	bit_cti_18B20   ; nacti bit B do Carry
		rlf		OwTemp,W        ; W = ------AB
		rrf		OwTemp,F        ; Vrat bit A do Carry
		andlw	0x03            ; AB = 00, cili nejednoznacnot?
		bnz		SendRomBit      ; pokud ne, pouzij bit A, jinak ..
 Discrepency					; .. res nejednoznacnost takto:
		movf	BitIndex,W      ; 0..63
		subwf	LastDiscrep,W   ; 0..63
		bnc		IndexGTLD       ; index > LastDiscrepency, pouzij 0
		bz		SendRomBit      ; index = LastDiscrepency, pouzij 1
 IndexLTLD                      ; index < LastDiscrepency, pouzij ROM
		movf	BitMask,W       ; nacti ROM bit do W
		andwf	INDF,W          ; je  to 0?
		bnz		SendRomBit      ; ne, nastav C = 1, jinak ..
		clrc                    ; .. nastav C = 0 a
 IndexGTLD
		movf	BitIndex,W      ; aktualizuj LastZero
		movwf	LastZero        ;
 SendRomBit
		movf	BitMask,W       ; nastav ROM bit na hodnotu v Carry
		iorwf	INDF,F          ; nastav ROM bit (bezpodminecne)
		skpc                    ; pokud je bit=1, preskoc, jinak
		xorwf	INDF,F          ; nuluj ROM bit
		call	pis_carry_18B20	; posli direction/qualifier bit
		rlf		BitMask,W       ;
		rlf		BitMask,F       ; posun se na dalsi bit v BitMask
		skpnc                   ; prosli jsme vsech 8 bitu? pokud ne preskoc, jinak
		incf	FSR,F           ; se s ukazatelem FSR presun na nasledujici adresu INDF registru
		incf	BitIndex,F      ; zdvihni citac bitu ROM ID o 1 ( RomID ma 8 byte, cili pocitame bity 0..63 )
		btfss	BitIndex,6      ; BitIndex = 64?  pokud ano, preskoc, jinak ..
		goto	GetBits         ; .. se vrat a projdi dalsi bit
		movf	LastZero,W      ; Jsme na konci, aktualizuj hodnotu update LastDiscrepency
		movwf	LastDiscrep     ;  ( LastDiscrepency=0 znamena, ze jsme zmerili ROM ID posledniho zarizeni)
		return                  ;

pis_carry_18B20
; Vstup:	STATUS,C
; Vystup:	bit zapsany do teplomeru
		jc		pis1
pis0	call	bit_pis0_18B20		
		return
pis1	call	bit_pis1_18B20
		return


ukaz_3Byte_FSR
; Ukaze na displeji W-te 3 byte (v hex) z FSR
; Vstup:	W jako poradi
		movwf	FSR					; Podle W nastav ukazatel odpovidajici RomBuffer

	 	mov		INDF,temp			; nacti INDF registr pod FSR ukazatelem
		rrf		temp				; Ziskej horni nibble
		rrf		temp
		rrf		temp
		rrf		temp
		movlw	0x0f				; odstran sum
		andwf	temp, W				;
		call	bit4_na_ascii		; preved na ascii kod
		movwf	digit6

	 	mov		INDF,temp			; read INDF register
		movlw	0x0f				; a odstranit pripadne bity znaminka
		andwf	temp, W				;
		call	bit4_na_ascii		; preved na ascii kod
		movwf	digit5


		incf 	FSR,F 				; FSR++

	 	mov		INDF,temp			; nacti INDF registr pod FSR ukazatelem
		rrf		temp				; Ziskej horni nibble
		rrf		temp
		rrf		temp
		rrf		temp
		movlw	0x0f				; odstran sum
		andwf	temp, W				;
		call	bit4_na_ascii		; preved na ascii kod
		movwf	digit4

	 	mov		INDF,temp			; nacti INDF registr pod FSR ukazatelem
		movlw	0x0f				; odstran sum
		andwf	temp, W				;
		call	bit4_na_ascii		; preved na ascii kod
		movwf	digit3


		incf 	FSR,F 				; FSR++

	 	mov		INDF,temp			; nacti INDF registr pod FSR ukazatelem
		rrf		temp				; Ziskej horni nibble
		rrf		temp
		rrf		temp
		rrf		temp
		movlw	0x0f				; a odstranit pripadne bity znaminka
		andwf	temp, W				;
		call	bit4_na_ascii		; preved na ascii kod
		movwf	digit2

	 	mov		INDF,temp			; nacti INDF registr pod FSR ukazatelem
		movlw	0x0f				; odstran sum
		andwf	temp, W				;
		call	bit4_na_ascii		; preved na ascii kod
		movwf	digit1		

		return
				

		END                       ; Konec programu



; ***********************
; Pro pripadne debugovani


;DispTemp_hex_debug
;; Zobrazeni teploty v hex
;; Nastavi digit6..digit1 pode teploty v teplota1,teplota2
;		; Vstup: teplota1 - teplota ( mantisa )
;		; Vstup: teplota2 - teplota ( bit7..bit4: desetinny rozvoj, bit3..bit0: znamenko )
;		; Vystup: digit6..digit1  ( # # # # ° C ) - hexa
;		;         obsazeni digitu ( 6 5 4 3 2 1 )  ( digit65-Temp2, Digit43-Temp1 )
;
;
;		; Digit 6 - Vyssi nibble z teplota2
;		mov		teplota2, temp
;		rrf		temp				;   Je treba vzit z teplota2 horni 4 bity
;		rrf		temp
;		rrf		temp
;		rrf		temp
;		movlw	0x0F				;	a odstranit pripadne bity znaminka
;		andwf	temp,W
;		call	bit4_na_ascii		;   preved cislo na ascii kod
;		movwf	digit6				;   Nastav pozadovanou cislici 
;
;		; Digit 5 - Nizsi nibble z teplota2
;		movlw	0x0F				;   Je treba vzit z teplota2 dolni 4 bity
;		andwf	teplota2,W
;		call	bit4_na_ascii		;   preved cislo na ascii kod
;		movwf	digit5				;   Nastav pozadovanou cislici 
;
;		; Digit 4 - Vyssi nibble z teplota1
;		mov		teplota1, temp
;		rrf		temp				;   Je treba vzit z teplota1 horni 4 bity
;		rrf		temp
;		rrf		temp
;		rrf		temp
;		movlw	0x0F				;	a odstranit ostatni bity
;		andwf	temp,W
;		call	bit4_na_ascii		;   preved cislo na ascii kod
;		movwf	digit4				;   Nastav pozadovanou cislici 
;
;		; Digit 3 - Nizsi nibble z teplota1
;		movlw	0x0F				;   Je treba vzit z teplota1 horni 4 bity
;		andwf	teplota1,W
;		call	bit4_na_ascii		;   preved cislo na ascii kod
;		movwf	digit3				;   Nastav pozadovanou cislici
;
;		; Digit 2 - stupne
;		movlw	'@'					; Priprav k zobrazeni digit3 ( napevno znak ° )
;		movwf	digit2				;   Nastav pozadovanou cislici 
;
;		; Digit 1 - Celsia
;		movlw	'C'					; Priprav k zobrazeni digit3 ( napevno znak C )
;		movwf	digit1				;   Nastav pozadovanou cislici 
;
;	return

