 TITLE  "LM60 based thermometer"   	  
 List P=PIC16F819, R=DEC	
 INCLUDE "p16f819.inc"

 __CONFIG _CP_OFF & _CCP1_RB2 & _DEBUG_OFF & _WRT_ENABLE_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_IO

#define digit1	PORTA,4
#define	digit2	PORTA,7
#define digit3	PORTA,6
#define alarm 	PORTA,1			; alarm pin
#define thresh	0x25			; alarm threschold (in BCD)

 CBLOCK 0x20       				; data segment in BANK 0   
 hundreds, tens, units 			; working variables
 n:2, speed, del
 ENDC					

; code segment
 ORG 0     		               	; main code
	bcf		STATUS, RP0			; activate BANK 0
	clrf	PORTA				; initialize PORT A
	clrf	PORTB				; initialize PORT B
	
	bsf    	STATUS, RP0      	; switch to BANK 1	
	movlw	b'00101101'
	movwf	TRISA ^ 0x80		; enable input on some RA pins
	clrf	TRISB ^ 0x80		; enable output on PORTB
	movlw	b'01100000'
	movwf	OSCCON ^ 0x80
	movlw	b'10001111'			; configure ADC for rifgt-justified
	movwf	ADCON1 ^ 0x80		; AN0, Vref+, Vref-

	bcf		STATUS, RP0			; back to BANK 0
	movlw	b'01000001'			; FOSC/8, ON
	movwf	ADCON0				; (ADC configuration)

	clrf	hundreds
	clrf	tens
	clrf	units
	clrf	n

	movlw	10
	movwf	speed				; temp conversion speed
loop	
	bcf		digit3				; turn off digit3
	movf	hundreds, w
	call	encode7seg			; get next digit
	movwf	PORTB
	bsf		digit1				; turn on digit1
	call	delay

	bcf		digit1				; turn off digit1
	movf	tens, w
	call	encode7seg			; get next digit
	movwf	PORTB
	bsf		digit2				; turn on digit2
	call	delay

	bcf		digit2				; turn off digit2
	movf	units, w
	call	encode7seg			; get next digit
	movwf	PORTB
	bsf		digit3				; turn on digit3
	call	delay

	decf	speed, f			; check if it is time
	btfss	STATUS, Z			; for a new temp
	 goto	loop				; conversion

	call	getADC				; process a new measurement
	call	adc2BCD				; convert data to BCD	
	goto	loop-2


;//////////////// procedures
encode7seg	;	  ecdpgbaf
	andlw	0x0F
	addwf	PCL, f
	retlw	b'11100111'	; code for 0
	retlw	b'01000100'	; code for 1
	retlw	b'10101110'	; code for 2
	retlw	b'01101110'	; code for 3
	retlw	b'01001101'	; code for 4
	retlw	b'01101011'	; code for 5
	retlw	b'11101011'	; code for 6
	retlw	b'01000110'	; code for 7
	retlw	b'11101111'	; code for 8
	retlw	b'01101111'	; code for 9
	retlw	b'00001000'	; code for -
	retlw	b'10100011'	; code for C

getADC
	bsf		ADCON0, GO			; start ADC conversion
	btfsc	ADCON0, GO			; wait until it is over
	 goto	$-1			
	bsf		STATUS, RP0			; switch to BANK 1
	movf	ADRESL ^ 0x80, w
	bcf		STATUS, RP0			; back to BANK 0
	movwf	n					; save lower byte
	movf	ADRESH, w
	movwf	n+1					; save higher byte
	return

bin2BCD
	movlw	-1
	movwf	hundreds
	movwf	tens

	movlw	100					; subtract 100 (16-bit operation)	
	incf	hundreds, f
	subwf	n, f		
	clrw				
	btfss	STATUS, C
	 addlw	1					
	subwf	n+1, f
	btfsc	STATUS, C
	 goto	$-8
	movlw	100
	addwf	n, w

	addlw	-10					; subtract 10
	incf	tens, f
	btfsc	STATUS, C
	 goto	$-3
	addlw	10
	movwf	units
	return

adc2BCD
	movlw	LOW 352				; display "---" for negative
	subwf	n, f				; temperatures
	movlw	HIGH 352				
	btfss	STATUS, C
	 addlw	1					
	subwf	n+1, f
	btfsc	STATUS, C
	 goto   $+5
	movlw	10					; temp > 0 : proceed
	movwf	hundreds
	movwf	tens
	return

	movf	n, w
	bsf		STATUS,	RP1			; switch to BANK 2
	movwf	EEADR ^ 0x100		; set address (in Wreg) to read
	bsf		STATUS, RP0			; switch to BANK 3
	bcf		EECON1 ^ 0x180, EEPGD
	bsf		EECON1 ^ 0x180, RD	; load byte from EEPROM
	bcf		STATUS, RP0			; back to BANK 2
	movf	EEDATA ^ 0x100, w	; move it to Wreg
	bcf		STATUS, RP1			; back to BANK 0

	movwf	hundreds
	movwf	tens
	movwf	n
	swapf	hundreds, f
	movlw	0x0F
	andwf	hundreds, f
	andwf	tens, f
	movlw	11					; code for C
	movwf	units

	movlw	thresh				; check if temp > thresh
	subwf	n, w
	btfsc	STATUS, C
	 bsf	alarm				; turn alarm on/off
	btfss	STATUS, C
	 bcf	alarm
	return

delay
	movlw	6
	movwf	del
	movlw	250					; this loop takes 1us*4*250 = 1ms
	addlw	-1					; for PIC @ 4 MHz
	btfss	STATUS, Z
	 goto 	$-2
	decfsz	del, f
	 goto	$-5
	return

 ORG 0x2100						; ASCII conversion table
	dt 0xF0, 0xF0, 0xF0, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1
	dt 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF3, 0xF3, 0xF3
	dt 0xF3, 0xF3, 0xF4, 0xF4, 0xF4, 0xF4, 0xF4, 0xF5
	dt 0xF5, 0xF5, 0xF5, 0xF5, 0xF5, 0xF6, 0xF6, 0xF6
	dt 0xF6, 0xF6, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF8
	dt 0xF8, 0xF8, 0xF8, 0xF8, 0xF9, 0xF9, 0xF9, 0xF9
	dt 0xF9, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11
	dt 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12
	dt 0x12, 0x13, 0x13, 0x13, 0x13, 0x13, 0x14, 0x14
	dt 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x15
	dt 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17
	dt 0x17, 0x17, 0x17, 0x18, 0x18, 0x18, 0x18, 0x18
	dt 0x19, 0x19, 0x19, 0x19, 0x19, 0x20, 0x20, 0x20
	dt 0x20, 0x20, 0x21, 0x21, 0x21, 0x21, 0x21, 0x22
	dt 0x22, 0x22, 0x22, 0x22, 0x22, 0x23, 0x23, 0x23
	dt 0x23, 0x23, 0x24, 0x24, 0x24, 0x24, 0x24, 0x25
	dt 0x25, 0x25, 0x25, 0x25, 0x26, 0x26, 0x26, 0x26
	dt 0x26, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x28
	dt 0x28, 0x28, 0x28, 0x28, 0x29, 0x29, 0x29, 0x29
	dt 0x29, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x31
	dt 0x31, 0x31, 0x31, 0x32, 0x32, 0x32, 0x32, 0x32
	dt 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x34, 0x34
	dt 0x34, 0x34, 0x34, 0x35, 0x35, 0x35, 0x35, 0x35
	dt 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x37, 0x37
	dt 0x37, 0x37, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38
	dt 0x39, 0x39, 0x39, 0x39, 0x39, 0x40, 0x40, 0x40
	dt 0x40, 0x40, 0x41, 0x41, 0x41, 0x41, 0x41, 0x42
	dt 0x42, 0x42, 0x42, 0x42, 0x43, 0x43, 0x43, 0x43
	dt 0x43, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45
	dt 0x45, 0x45, 0x45, 0x45, 0x46, 0x46, 0x46, 0x46
	dt 0x46, 0x47, 0x47, 0x47, 0x47, 0x47, 0x48, 0x48
	dt 0x48, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49

 END
