
	list      p=16f870A             ; list directive to define processor
	#include <p16f870.inc>         ; processor specific variable definitions

        errorlevel -302           ; Register not in bank 0 warning

        radix dec

	__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON 
	  & _HS_OSC & _LVP_OFF & _DEBUG_OFF & _CPD_OFF

#define VERS	 	043 			;Version to display



; Data storange
	org	20h
wsave		equ	20H
ssave		equ	21H
bitcnt		equ	22H		; 
flag		equ	23H
count		equ	24H
scount		equ	25H
csave		equ	26H
ddata		equ	27H   ; was data
sdata		equ	28H
temp		equ	29H   
ontime		equ	2BH
oftime		equ	2CH
isrvec		equ	2DH
qtime		equ	2EH		;comm timer for serial
timer		equ	30H
freq		equ	33H		;
pwmp		equ	35H
mode		equ	36H
rate		equ	37H
baud		equ	38H
midic		equ	39H		;midi channel
pmode		equ	3AH
hi			equ	3BH
lo			equ	3CH   ; was low
rand		equ	3DH
acc			equ	40H		;32 bit register acc+0(40H)_MSB acc+3(43H)_LSB
xacc		equ	44H		;aux 32 bit value
digits		equ	48H		;segment data for LED
dignr		equ	4CH
dp			equ	4DH
ftimer		equ 4EH
segmask		equ	50H
dela		equ	51H
bcd			equ	54H		;10 digit packed bcd buffer (5 bytes)
;pto	equ	59H		; not used
;pti	equ	5AH		; not used
cnt			equ	59H			; 5BH
ii			equ	5AH
frame		equ	5BH
place       equ 5Ch
port_temp   equ 5Dh

 
; Program Start
	org	0
	goto	start    


;  Table for number to seven segment conversion 
digseg
	addwf	PCL,f
	retlw 3fh		;0
  retlw   6h		;1
  retlw   5bh		;2
  retlw   4fh		;3
  retlw   66h		;4
  retlw   6dh		;5
  retlw   7dh		;6
  retlw   7h		;7
  retlw   7fh		;8
  retlw   67h		;9

; Get anode value for PORT C output
getano	
	addwf	PCL,f
						
	retlw	1	
	retlw	2
	retlw	4
	retlw	8

getdp	
	addwf	PCL,f
	retlw	03h
	retlw	03h
	retlw	03h
	retlw	03h
	retlw	94h
	retlw	0A5h
	retlw	0C6h
	retlw	0D7h
	retlw	0E8h
	retlw	0F9h


start	
	bsf		STATUS,5
	movlw	b'00111111'
	movwf	TRISA
	movlw	0
	movwf	TRISB
	movlw	b'10110000'
	movwf	TRISC
	movlw	b'10001000'
	movwf	OPTION_REG
	bcf		STATUS,5	
	clrf	segmask
	bsf		segmask,0
	clrf	dignr	
	clrf    rate      ;added to decrease the scan rate for viewing	
	call	signon     
	goto    start


; show version No 
signon	                
	movlw	VERS
	call	wtod		;put version No  
	movlw	0				
	movwf	digits
	call	sign 	        
	return


; delay function

delay 
	movwf	dela+2
dld2
	movwf	dela+1
dld1
	movwf	dela
dld0
	decfsz	dela,f
	goto	dld0
	decfsz	dela+1,f
	goto	dld1
	decfsz	dela+2,f
	goto	dld2
	return
	
   
; show 8 bit value on display
wtod                
	movwf	acc
	clrf	acc+1
	clrf	acc+2
	clrf	acc+3
	call	b2bcd
	call	format
	return


sign	
	movlw	.30	 		
	movwf	temp
x1
	call	segout
	incf	rate,f
	movf    rate,w       ;decrease scan rate across display 
	call	delay     
	decfsz	count,f
	goto	x1
	decfsz  temp,f
	goto	x1
	return



; Convert 32-bit binary number at <acc> into a bcd number
; at <bcd>. Uses Mike Keitz's procedure for handling bcd
; adjust; Modified Microchip AN526 for 32-bits.
b2bcd
	movlw	32		; 32-bits
	movwf	ii		; make cycle counter
	clrf	bcd		; clear result area
	clrf	bcd+1
	clrf	bcd+2
	clrf	bcd+3
	clrf	bcd+4

b2bcd2
	movlw	bcd		; make pointer
	movwf	FSR
	movlw	5
	movwf	cnt

; Mike's routine_
b2bcd3
	movlw	33h
	addwf	0,f 		; add to both nybbles
	btfsc	0,3			; test if low result > 7
	andlw	0f0h		; low result >7 so take the 3 out
	btfsc	0,7			; test if high result > 7
	andlw	0fh			; high result > 7 so ok
	subwf	0,f 		; any results <= 7, subtract back
	incf	FSR,f 	; point to next
	decfsz	cnt,f
	goto	b2bcd3
	rlf		acc+0,f		; get another bit
	rlf		acc+1,f
	rlf		acc+2,f
	rlf		acc+3,f
	rlf		bcd+0,f		; put it into bcd
	rlf		bcd+1,f
	rlf		bcd+2,f
	rlf		bcd+3,f
	rlf		bcd+4,f
	decfsz	ii,f 		; all done?
	goto	b2bcd2		; no, loop
	return



; cycle thru individual segment drives on 4 digits
; (constant execution time_ 30 instructions)
; ************** Do Not Modify *******************

segout	

	movlw	0F0h
	andwf	PORTC,f		;clear low 4 bits
	movf	dignr,w		;get digit nr
	addlw	digits		;base of segment list
	movwf	FSR
	movf	0,w				;get the data
	andwf	segmask,w	;mask the bit
	xorlw	0ffh			;invert
	movwf	PORTB			;one possible segment line low
	movf	dignr,w
	call	getano	
	iorwf	PORTC,f   ; set one high.
	bcf		STATUS,C
	rlf		segmask,f
	btfsc	STATUS,C
	goto	nseg
	nop
	nop
	nop
	nop
	nop
	return

nseg
	bsf		segmask,0		;rotate
	incf	dignr,f
	btfsc	dignr,2		;overflow?
	clrf	dignr	
	return


; format first 4 signifcant digits on display
format
	call	first		;find 1st non-zero digit
ffx
	movf	count,w
	call	getdp		;get formating info
	movwf	dp
	andlw	0fh
	movwf	count
ff5
	call	ff9			;get segment pattern
	movwf	digits
	call	ff9
	movwf	digits+1
	call	ff9
	movwf	digits+2
	call	ff9
	movwf	digits+3
	return

ff9
	movf	count,w
	decf	count,f
	call	getbd		;get bcd value
	call	digseg
	return

; set count to 1st non zero digit
first
	movlw	9					;start w/last digit
	movwf	count
ff2
	movf	count,w		;get next digit
	call	getbd
	xorlw	0					;set z flag
	btfss	STATUS,Z
	return					;hit non zero
	decfsz	count,f
	goto	ff2
	return


; get bcd digit specified by 'w'
getbd
	movwf	temp		;save digit nr
	clrw
	btfsc	temp,7	;negative value?
	return				;zero if negative.
	bcf		STATUS,C
	rrf		temp,f		;find buffer offset
	movf	temp,w
	rlf		temp,f		;restore all bits
	addlw	bcd			;add start of bcd buff
	movwf	FSR			;set pointer
	movf	0,w			;get the byte
	movwf	ddata		;and store it.
	btfsc	temp,0	;low or hi nibble?
	swapf	ddata,f	;hi.
	movf	ddata,w
	andlw	0fh
	return


       
	end
