;================================================================================================
; Date			: 6 October 2007
; Project		: 7 Segment Thermometer
; Frequency		: 4 MHz
; Device used	: 16F877A
; Oscillator	: XT
; Watchdog		: OFF    
; Copyright		:  
; Designed by	: Mujahidin
; Comments		:
; Dowloaded from Downloads  www.iddhien.com
; The content information of this project is without waranty, you can free distribute any document
; in this project with still enclose the author name and the header title of this project.
;================================================================================================
		LIST p=16F877
;================================================================================================
		w			equ 0    ; working reg:
		f			equ 1    ; same reg: 
;================================================================================================
; STATUS FLAGS
;================================================================================================
		carry		equ 0
		zero		equ 2
		rp0     	equ 5  ; bank selection
		rp1     	equ 6
;================================================================================================
; SFR's - SPECIAL FUNCTIONS REGISTERS
;================================================================================================
		indf		equ 00
		tmr0		equ 01
		optionreg   equ 01 ;bank 1
		pcl			equ 02
		status		equ 03
		fsr			equ 04
		trisa       equ 05h ; bank1
		trisd       equ 08h ; bank1
		trisb       equ 06h ; bank1
		trise       equ 09  ; bank1
		trisc       equ 07h ; bank 1       
		porta		equ 05
		portb		equ 06
		portc		equ 07
		portd       equ 08
		porte       equ 09 
		pclath		equ 0Ah      
		intcon		equ 0Bh
		tmr1l		equ 0Eh
		tmr1h		equ 0Fh
		pir1		equ 0Ch
		pie1		equ 0Ch	; other bank
		t1con		equ 10h
		rcsta		equ 18h
		txsta		equ 18h	; other bank
		txreg		equ 19h
		spbrg		equ 19h	; other bank
		rcreg		equ 1Ah          
		adresl		equ 1Eh ; Bank 1
		adresh      equ 1Eh
		adcon0		equ 1Fh
		adcon1		equ 1Fh	; other bank
		_WDT_OFF    equ 3FFBh
		_XT_OSC     equ 3FFDh
;================================================================================================
; GPR - GENERAL PURPOSE REGISTERS area
;================================================================================================
		CBLOCK 20h
			simage
			wimage
			digit1
			digit2
			digit3
			ledindex
			delaysmall
			delaylarge
			delaytime
			resultlbyte
			resulthbyte
			tmrodelay
			count   
			temp    
			H_byte   
			L_byte   
			Treultlbyte
			Tresulthbyte
			TH_byte
			TL_byte
			R0                ; RAM Assignments
			R1       
			R2       
		ENDC

;================================================================================================
; Constants & Declarations
;================================================================================================
		gie			equ 7	; INTCON
		go          equ 2   ; a/d conversion start/stop 
		T0IF        equ 2   ; timer0 overfow check flag 
		ADON        equ 0   ; switch on a/d converter. 
;================================================================================================
; DEFINE
;================================================================================================
;configuration bits
       	__CONFIG        _XT_OSC & _WDT_OFF                      
;================================================================================================
; RESET VECTOR
;================================================================================================
		ORG 0
        goto   start
;================================================================================================
        org 04
isr		movwf   	wimage      ; saving critical registers
		swapf   	status,w
		movwf   	simage
		movf    	H_byte,w
        movwf   	TH_byte     ; these are also modified during isr,
        movf    	L_byte,w    ; so have to be saved till next cycle.
        movwf   	TL_byte 
;================================================================================================
;  IS routines goes here
;================================================================================================
 		decfsz     tmrodelay,f   ; wait for 16 interrupts to pass
        goto       isrexit
        nop
        call       atodcon       ; on 16th interrupt,conversion. 
        call       atodforbcd
        movlw      .16
        movwf      tmrodelay     ; reinitialise the variable
;================================================================================================
isrexit         
;================================================================================================
		nop                       ; seems to be a timing violation
        nop                       ; so just a delay! 
        bcf     	intcon,T0IF
        bsf     	intcon,gie
        movf    	TH_byte,w
        movwf   	H_byte
        movf    	TL_byte,w         ;   replace the registers,
        movwf   	L_byte            ;   clear the tmr0 flag caused 
        bcf     	intcon,T0IF       ;   the interrupt. 
        swapf   	simage,w
 		movwf   	status
        swapf   	wimage,f
        swapf   	wimage,w  
	    retfie
;End of interrupt service routines
;================================================================================================
display_table 
	    addwf      	pcl,f      ; W + PCL -> PCL
		retlw      	b'00111111' ;  '0'
        retlw      	b'00000110' ;  '1'
        retlw      	b'01011011' ;  '2'
        retlw      	b'01001111' ;  '3'
        retlw      	b'01100110' ;  '4'   table for segment patterns
        retlw      	b'01101101' ;  '5'
        retlw      	b'01111101' ;  '6'
        retlw      	b'00000111' ;  '7'
        retlw      	b'01111111' ;  '8'
        retlw      	b'01100111' ;  '9'
        retlw      	b'10000000' ;  '.'
;================================================================================================
; SUBROIUTINES
;================================================================================================
display   
		movlw     	b'00000001'   ;  select the left most digit
        movwf     	ledindex      ;
	   	movwf     	porte         ;  digit selecting transistor on!
        movf      	digit1,w      ;  get the bcd value to display
        call      	digitout      ;  illuminate for a period
         
        rlf       	ledindex,f    ;  rotate to left to select next digit  
        movf      	ledindex,w    ;  enable next digit
        movwf     	porte         ;  digit selecting transistor on!
        movf      	digit2,w      ;  get the bcd value.
        call      	digitout      ;  illuminate for a period   
           
        rlf       	ledindex,f
        movf      	ledindex,w    ;  last digit selected.
        movwf     	porte 
        movf      	digit3,w      ;  get bcd value
        call      	digitout      ;  illuminate for a period
        return
;================================================================================================
digitdelay 
		movlw     	5h             ;  outer loop for delay
        movwf     	delaylarge
loopl   
	   	decf      	delaylarge,f 
        btfsc     	status,zero
        return
        movlw     	0FFh
        movwf     	delaysmall
loops   
	   	decfsz    	delaysmall,f   ;  inner loop for delay
        goto      	loops
        goto      	loopl             
;================================================================================================
digitout   
		nop
        call       	display_table ; illuminate digit and wait 
        movwf      	portd         ; for some time
        call       	digitdelay
        clrf       	portd         ; off the digit and return.
        clrf       	porte
        return 	 
;================================================================================================
iniports   
		bsf       	status,rp0
        movlw     	b'00000001'     ;  input for analogue  temp sensor
        movwf     	trisa           ;  RA0 as the input 
        clrw
        movwf     	trisd           ;  all portd output for segments.
        movwf     	trise           ;  porte for digit selection
        bcf       	status,rp0      ;  return to bank 0 and return  
        clrf      	porta
        clrf      	portd
        clrf      	porte
        return
;================================================================================================
iniatod    
		bsf      	status,rp0
        movlw    	b'10001110'      ;  result right justified ,ra0 as
        movwf    	adcon1           ;  analogue input with Vdd as Vref
        bcf      	status,rp0           
	   	movlw    	b'01000000'      ;  a/d clock Tosc*8 and Ra0 channel
        movwf    	adcon0           ;  selected. a/d module still off.
        return 
;================================================================================================
initimer  
		bsf       	status,rp0       ;  bank 1
        movlw     	b'10000111'      ;  timer0 on internal clock pulse
        movwf     	optionreg        ;  prescaler 1:256
        movlw    	b'10100000'      ;  gie and TMR0 interrupt enabled  
        movwf     	intcon           ;  all ready! 
	  	bcf       	status,rp0
        movlw     	.1
        movwf     	tmrodelay        ; initialise the delay variable to     
        return                     ; start conversion on 1st interrupt
;================================================================================================
atodcon    
		bsf       	adcon0,ADON ; swich on a/d converter.
        movlw     	0Ah
        movwf     	delaytime
aquiloop   
		decfsz    	delaytime,f ; wait for aqusition time. 
		goto      	aquiloop
		bsf       	adcon0,go   ; conversion starts now!
converloop 
		btfsc     	adcon0,go   ; loop until conversion complete.
		goto      	converloop
        bsf       	status,rp0  ;  bank for adresl 
        movf      	adresl,w    ;  low byte of result.
        bcf       	status,rp0
        movwf     	resultlbyte ;  a/d low byte saved
        movf      	adresh,w    ;  high byte of result
        movwf     	resulthbyte ;  a/d high byte saved    
        return
;================================================================================================
B2_BCD  
		bcf     	status,0                ; clear the carry bit
		movlw   	.16
		movwf   	count
		clrf    	R0
		clrf    	R1
		clrf    	R2
loop16  
		rlf     	L_byte, f
		rlf     	H_byte, f
		rlf     	R2, f
		rlf     	R1, f
		rlf     	R0, f
;
		decfsz  	count, f                ; routine for bcd conversion
		goto    	adjDEC
		retlw  		0
;
adjDEC  
		movlw   	R2
		movwf   	fsr
		call    	adjBCD                    ; no bank switching, always 
;                                         ; indirect access for RAM
		movlw   	R1
		movwf   	fsr
		call    	adjBCD
;
		movlw   	R0
		movwf   	fsr
		call    	adjBCD
;
		goto    	loop16
;
adjBCD  
		movlw   	3
		addwf   	0,W
		movwf   	temp
		btfsc   	temp,3          ; test if result > 7
		movwf   	indf
		movlw   	30
		addwf   	0,W
		movwf   	temp
		btfsc   	temp,7          ; test if result > 7
		movwf   	indf               ; save as MSD
		retlw   	0
;================================================================================================
;   Arrange the  result as digits 1,2,3.
bcdsplit   
		movf     	R1,w     ;   bring first nibble  
		andlw    	0Fh      ;   mask the upper nibble
        movwf    	digit1   ;   send to display routine variable.

        movf     	R2,w     ;   bring the second digit!
        andlw    	0F0h     ;   mask the lower nibble.
        movwf    	digit2   ;   send to display routine variable.
        swapf    	digit2,f ;   after swaping!
 
        movf     	R2,w     ;   Again bring the lowbyte
        andlw    	0Fh      ;   mask the upper nibble
        movwf    	digit3   ;   send it to display routine variable     
        return
;================================================================================================
atodforbcd  
		rrf      	resultlbyte,f  ; routine for dividing the value 
		bcf      	status,carry
		rrf     	resulthbyte,f            
        btfsc    	status,carry
        bsf      	resultlbyte,7  ;
xxx     
		movf     	resultlbyte,w  ; 
        movwf    	L_byte         ; bcd conversion subroutine.   
        movf     	resulthbyte,w  ;
        movwf    	H_byte         ; 
        return
;================================================================================================
; Main program starts
;================================================================================================
start	 
		clrf   		simage
        clrf   		wimage
        clrf   		digit1
        clrf   		digit2
        clrf   		digit3
        clrf   		ledindex
        clrf   		delaysmall
        clrf   		delaylarge 
        clrf   		porta
        clrf   		portd
        clrf   		porte
        bsf    		status,rp0
        clrf   		trisd
        clrf   		trisb
        clrf   		trisc
	   	clrf   		trise
        clrf   		trisa
        bcf    		status,rp0
        bcf    		status,rp1
        call   		iniports    ;  initialise all relevent ports.
        call   		iniatod     ;  initialise a/d converter module.       
        call   		initimer    ;  initialise timer0 so to derive a time base.
          
;================================================================================================
main       
		;call     	atodcon         ;   conversion and result saved.
        ;call     	atodforbcd      ;   result moved for bcd conversion
        call     	xxx
        call     	B2_BCD         ;   bcd conversion
        call     	bcdsplit       ;   seperate nibbles for digits
        call     	display        ;   display the digits.  
	
        goto 		main
;================================================================================================
		END



