 TITLE  "wind.asm"         		; anemometer
 List P=PIC16F648A, R=DEC
 INCLUDE "p16f648a.inc"
 ERRORLEVEL -302         		; no bank warnings

 __CONFIG _CP_OFF & _DATA_CP_OFF & _LVP_OFF & _BOREN_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTOSC_OSC_NOCLKOUT
 
; data segment
 CBLOCK 0x20                   
 del, t1		  				; variables used for delay
 wind							; wind sensor counter	
 temp							; local variables
 w_save, stat_save				; locations to save W and STATUS in ISR
 tens, units					; storage for decimal digits
 ENDC

; code segment
  ORG 0                      	; start program at the beginning of mem
	goto 	main
 
  ORG 4							; Interrupt Service Routie
	movwf	w_save				; save W reg
	swapf	STATUS, w			; save stat reg without
	movwf	stat_save			; changing flags

	incf	t1, f				; count 8 TMR1 interrupts
	btfss	t1, 3				; corresponding to a 4 sec interval
	 goto	ISR_END
	clrf	t1

	movf	TMR0, w				; get pulse count				
	clrf	TMR0
	sublw	99					; if the number exceeds 100
	btfss	STATUS, C			; bound it with 99
	 clrw	
	sublw	99				

	btfss	PORTA, 1			; check the mode
	 goto	mode3				; given by the swicthes at
	btfsc  	PORTA, 0			; RA1 and RA0
	 goto	mode2

mode1							; convertion to km/h
	clrf	temp
	sublw	2					; set decimal point if the number of pulses
	btfsc	STATUS, C			; does not exceed 2
	 incf	temp, f
	sublw	2					; restore w
	call	convert1
	goto	process

mode2							; conversion to m/s
	clrf	temp
	sublw	45					; set decimal point if the number of pulses
	btfsc	STATUS, C			; does not exceed 45
	 incf	temp, f
	sublw	45					; restore w
	call	convert2			
	goto	process

mode3							; pulse count mode	
	call	bin2BCD				; convert pulse count into BCD
	goto	ISR_END

process
	clrf	PCLATH
	movwf	tens				; save table conversion results
	movwf	units

	swapf	tens, f				; extract tens
	movlw	0x0F
	andwf	tens, f
	andwf	units, f			; extract units	
	btfsc	temp, 0				; check for decimal point
	 bsf	tens, 4				; ebmed it into bit 4 of tens

ISR_END
	bcf		PIR1, TMR1IF		; clear interrupt flag
	swapf	stat_save, w		; get orig flags in STATUS
	movwf	STATUS
	swapf	w_save, f			; restore the original W
	swapf	w_save, w
	retfie

main							; main code
	bcf		STATUS, RP0			; activate BANK 0
	clrf	PORTA				; initialize PORT A
	clrf	PORTB				; initialize PORT B
	movlw	0x07
	movwf	CMCON				; comparators OFF

	bsf    	STATUS, RP0      	; change to BANK 1
	movlw	b'00111000'
	movwf	OPTION_REG ^ 0x80	; TMR0 setup
	movlw	b'00110011'			
	movwf	TRISA ^ 0x80		; enable output on PORTA<7:6, 3:2>
	clrf	TRISB ^ 0x80		; enable output on PORTB 0
	bsf		PIE1, TMR1IE		; enable TMR1 interrupts
	bcf    	STATUS, RP0        	; back to BANK 0

	bsf		INTCON, PEIE
	bcf		PIR1, TMR1IF		; clear TMR1 IF
	clrf	TMR1H
	clrf	TMR1L	
	clrf	TMR0
	movlw	b'00110001'			; TMR1 setup: 1:8 divider, FOSC/4
	movwf	T1CON
	clrf	t1
	bsf		INTCON, GIE			; enable interrupts globally

	clrf	wind				; clear the wind counter
	clrf	tens
	bsf		tens, 4
	clrf	units

loop							; main loop
	movf	tens, w
	call	encode7seg			; get 7-seg code in WREG
	btfsc	tens, 4				; check if dp must be on
	 addlw	2					; turn of dp
	bcf		PORTA, 7			; turn off units
	movwf	PORTB				; update display
	bsf		PORTA, 6			; turn on tens
	call	delay				; 7 msec delay	

	movf	units, w
	call	encode7seg			; get 7-seg code in WREG
	bcf		PORTA, 6			; turn off tens
	movwf	PORTB				; update display
	bsf		PORTA, 7			; turn on units
	call	delay				; 7 msec delay	

	goto 	loop

bin2BCD							; convert a 2-digit decimal value in BCD
	movwf	temp
	clrf	tens
	movlw	10
	subwf	temp, f				; subtract 10 from the counter
	incf	tens, f				; until we get a negative result
	btfsc	STATUS, C
	 goto	$-3
	decf	tens, f				; adjust the tens counter
	addwf	temp, w
	movwf	units				; obtain units
	return
	
delay							; a delay for del milliseconds
	movlw	7
	movwf	del
	movlw 	250
	
	addlw	-1					; this loop takes 4us*250 = 1ms
	btfss	STATUS, Z			; for PIC @ 4 Mhz
	 goto 	$-2

	decfsz	del, f
	 goto 	delay+2
	return

encode7seg	; abgfdepc	
	andlw	0x0F				
	addwf	PCL, f				; bit 1 is the decimal point
	retlw	b'11011101'			; code for 0
	retlw	b'01000001'			; code for 1
	retlw	b'11101100'			; code for 2
	retlw	b'11101001'			; code for 3
	retlw	b'01110001'			; code for 4
	retlw	b'10111001'			; code for 5
	retlw	b'10111101'			; code for 6
	retlw	b'11000001'			; code for 7
	retlw	b'11111101'			; code for 8
	retlw	b'11111001'			; code for 9
	retlw	b'00000000'			; blank
	retlw	b'00000000'			; blank
 	retlw	b'00000000'			; blank
	retlw	b'00000000'			; blank
	retlw	b'00000000'			; blank
	retlw	b'00000000'			; blank 

 ORG 0x100
convert1						; conversion table for km/h
	clrf	PCLATH
	incf	PCLATH, f
	addwf	PCL, f

	retlw 	0x00
	retlw 	0x87
	retlw 	0x94
	retlw 	0x10
	retlw 	0x11
	retlw 	0x11
	retlw 	0x12
	retlw 	0x12
	retlw 	0x13
	retlw 	0x14
	retlw 	0x14
	retlw 	0x15
	retlw 	0x16
	retlw 	0x16
	retlw 	0x17
	retlw 	0x17
	retlw 	0x18
	retlw 	0x19
	retlw 	0x19
	retlw 	0x20
	retlw 	0x20
	retlw 	0x21
	retlw 	0x22
	retlw 	0x22
	retlw 	0x23
	retlw 	0x23
	retlw 	0x24
	retlw 	0x25
	retlw 	0x25
	retlw 	0x26
	retlw 	0x27
	retlw 	0x27
	retlw 	0x28
	retlw 	0x28
	retlw 	0x29
	retlw 	0x30
	retlw 	0x30
	retlw 	0x31
	retlw 	0x31
	retlw 	0x32
	retlw 	0x33
	retlw 	0x33
	retlw 	0x34
	retlw 	0x35
	retlw 	0x35
	retlw 	0x36
	retlw 	0x36
	retlw 	0x37
	retlw 	0x38
	retlw 	0x38
	retlw 	0x39
	retlw 	0x39
	retlw 	0x40
	retlw 	0x41
	retlw 	0x41
	retlw 	0x42
	retlw 	0x43
	retlw 	0x43
	retlw 	0x44
	retlw 	0x44
	retlw 	0x45
	retlw 	0x46
	retlw 	0x46
	retlw 	0x47
	retlw 	0x47
	retlw 	0x48
	retlw 	0x49
	retlw 	0x49
	retlw 	0x50
	retlw 	0x51
	retlw 	0x51
	retlw 	0x52
	retlw 	0x52
	retlw 	0x53
	retlw 	0x54
	retlw 	0x54
	retlw 	0x55
	retlw 	0x55
	retlw 	0x56
	retlw 	0x57
	retlw 	0x57
	retlw 	0x58
	retlw 	0x59
	retlw 	0x59
	retlw 	0x60
	retlw 	0x60
	retlw 	0x61
	retlw 	0x62
	retlw 	0x62
	retlw 	0x63
	retlw 	0x63
	retlw 	0x64
	retlw 	0x65
	retlw 	0x65
	retlw 	0x66
	retlw 	0x66
	retlw 	0x67
	retlw 	0x68
	retlw 	0x68
	retlw 	0x69

convert2							; conversion table for m/s
	clrf	PCLATH
	incf	PCLATH, f
	addwf	PCL, f

	retlw 	0x00
	retlw 	0x24
	retlw 	0x26
	retlw 	0x28
	retlw 	0x29
	retlw 	0x31
	retlw 	0x33
	retlw 	0x35
	retlw 	0x36	
	retlw 	0x38
	retlw 	0x40
	retlw 	0x41
	retlw 	0x43
	retlw 	0x45
	retlw 	0x46
	retlw 	0x48
	retlw 	0x50
	retlw 	0x52
	retlw 	0x53
	retlw 	0x55
	retlw 	0x57
	retlw 	0x58
	retlw 	0x60
	retlw 	0x62
	retlw 	0x64
	retlw 	0x65
	retlw 	0x67
	retlw 	0x69
	retlw 	0x70
	retlw 	0x72
	retlw 	0x74
	retlw 	0x75
	retlw 	0x77
	retlw 	0x79
	retlw 	0x81
	retlw 	0x82
	retlw 	0x84
	retlw 	0x86
	retlw 	0x87
	retlw 	0x89
	retlw 	0x91
	retlw 	0x93
	retlw 	0x94
	retlw 	0x96
	retlw 	0x98
	retlw 	0x99
	retlw 	0x10
	retlw 	0x10
	retlw 	0x10
	retlw 	0x11
	retlw 	0x11	
	retlw 	0x11
	retlw 	0x11
	retlw 	0x11
	retlw 	0x11
	retlw 	0x12
	retlw 	0x12
	retlw 	0x12
	retlw 	0x12
	retlw 	0x12
	retlw 	0x12
	retlw 	0x13
	retlw 	0x13
	retlw 	0x13
	retlw 	0x13
	retlw 	0x13
	retlw 	0x14	
	retlw 	0x14
	retlw 	0x14
	retlw 	0x14
	retlw 	0x14
	retlw 	0x14
	retlw 	0x15
	retlw 	0x15
	retlw 	0x15
	retlw 	0x15
	retlw 	0x15
	retlw 	0x15
	retlw 	0x16
	retlw 	0x16
	retlw 	0x16
	retlw 	0x16
	retlw 	0x16
	retlw 	0x16
	retlw 	0x17
	retlw 	0x17
	retlw 	0x17
	retlw 	0x17
	retlw 	0x17
	retlw 	0x17
	retlw 	0x18
	retlw 	0x18
	retlw 	0x18
	retlw 	0x18
	retlw 	0x18
	retlw 	0x18
	retlw 	0x19
	retlw 	0x19
	retlw 	0x19
	retlw 	0x19
 end
