;************************************************************
; Author: Dave Smith
; Company: Analog Devices Inc.
; Revision: 1.1
; Date: 4-9-2001
;************************************************************
; This program controls and reads data from The Analog Devices ADE7756
; Single Phase Bi-Directional Power/Energy IC to measure Active Energy, Voltage RMS and Current RMS.
; This program should be used in conjunction with the AN-578 Application note
; The Energy Dump routine describes in the AN-564 and AN-578 
; is not implemented in this version of the program
; This code is for the PIC16F873 but can easily been changed to work with PIC16C63
 

	list      p=16f873           ; list directive to define processor
	#include <p16f873.inc>        ; processor specific variable definitions
	
	__CONFIG _CP_OFF & _WDT_OFF & _BODEN_ON & _PWRTE_ON & _HS_OSC & _WRT_ENABLE_ON & _LVP_OFF & _CPD_OFF

; Declare variables 		; valid addresses are Bank 0 20 to 7F Hex and bank1 A0 to FF Hex



spi   		equ  	H'20'		; spi reg data =0c hex 

swap_w		equ	H'21'		; used in interrupt routine 
swap_status		equ	H'22'		; used in interrupt routine
swap_wordlen	equ	H'23'		; used in interrupt routine

outd1		equ	H'24'		; out to 7756 1st byte (msb 1st) of word
outd2		equ	H'25'		; out to 7756 2st byte (msb 1st) of word	

mem		equ	H'26'		; used to check eeprom mem
carry		equ	H'27'		; used in carrychk routine
wordlen	equ	H'28'		; word length for rotate 
	
sar1		equ	H'29'		; approximation register 1
sar2		equ	H'2A'		; approximation register 2
sar3		equ	H'2B'		; approximation register 3

wait		equ	H'2C'		; wait loop data 
wait2		equ	H'2D'		; wait2 loop data 

bcd0		equ	H'2E'		; lsb of bcd word
bcd1		equ	H'2F'		; 	 bcd word
bcd2		equ	H'30'		;  	 bcd word
bcd3		equ	H'31'		;   	 bcd word
bcd4		equ	H'32'		; msb of bcd word

bin0		equ	H'33'		; lsb of bin word
bin1		equ	H'34'		;        bin word
bin2		equ	H'35'		;        bin word
bin3		equ	H'36'		;        bin word
bin4		equ	H'37'		; msb of bin word

addend1		equ	H'38'	; result of addition 
addend2		equ	H'39'	; result of addition 
addend3		equ	H'3A'	; result of addition  
addend4 		equ	H'3B'	; result of addition 
addend5		equ	H'3C'	; result of addition 
addend6		equ	H'3D'	; result of addition 

y1		equ	H'3E'	; binary acumulated power   
y2		equ	H'3F'	; binary acumulated power 
y3		equ	H'40'	; binary acumulated power 
y4		equ	H'41'	; binary acumulated power 
y5		equ	H'42'	; binary acumulated power 
y6		equ	H'43'	; period to freq

mode0		equ	H'44'	; lsb mode register data
mode1		equ	H'45'	; msb mode register data

sample_low		equ	H'46'	; lsb cf divide data
sample_middle	equ	H'47'	; msb cf divide data
sample_high		equ	H'48'	; period to freq

contint		equ	H'49'	; loop for energy dump	

dave1		equ	H'4A'	; 
dave2		equ	H'4B' 	; 

x1		equ	H'4C'	; output of iir filter 
x2		equ	H'4D'	; output of iir filter 
x3		equ	H'4E'	; output of iir filter 
x4		equ	H'4F'	; output of iir filter 
x5		equ	H'50'	; output of iir filter 
x6		equ	H'51'	; output of iir filter 

eep1		equ	H'52'	; 
eep2		equ	H'53'	; 

timerh	equ	H'54'	; timer working reg
timerl	equ	H'55'	; timer working reg 

sinwait	equ 	H'56'	; serial in wait between bit check
bcdtemp	equ	H'57'	; energy conversion constant .xxxxxxxx
lcdout	equ	H'58'	; lcd output data
lcdup		equ	H'59'	; lcd acsii data upper 4 bits  
lcdlow 	equ	H'5A'	; lcd ascii data lower 4 bits  
wait3		equ	H'5B'	; wait for lcd

insd1		equ	H'5C'	; in from 7756 1st byte (msb 1st) of word
insd2		equ	H'5D'	; in from 7756 2st byte (msb 1st) of word
insd3		equ	H'5E'	; in from 7756 3st byte (msb 1st) of word
insd4		equ	H'5F'	; in from 7756 4st byte (msb 1st) of word
insd5		equ	H'60'	; in from 7756 5st byte (msb 1st) of word
insd6		equ	H'61'	; sign extension    
insd7		equ	H'62'	; sign extension
insd8		equ	H'63'	; sign extension
insd9		equ	H'64'	; sign extension
insd10	equ 	H'65'	; sign extension 
insd11	equ 	H'66'	; sign extension 

econstant0	equ	H'67'
econstant1	equ	H'68'
econstant2	equ	H'69'

tempof	equ	H'6A'
econstant	equ	H'6B'
mem2		equ	H'6C'
msdbcd	equ	H'6D'	; used in bcd conversion 	
lsdbcd	equ	H'6E'	; used in bcd conversion 
point		equ	H'6F'	; decimal point flag
 
mem3 		equ	H'70'	; energy conversion constant .xxxxxxxx

sampcnt	equ	H'71'	; loop for energy dump	

square1	equ 	H'72'	; used in rms routine lsb
square2	equ 	H'73'	; used in rms routine 
square3	equ 	H'74'	; used in rms routine 
square4	equ 	H'75'	; used in rms routine 
square5	equ 	H'76'	; used in rms routine  
square6	equ	H'77'	; used in rms routine msb

add1		equ 	H'78'	; results of square and sum lsb
add2		equ 	H'79'	; results of square and sum 
add3		equ 	H'7A'	; results of square and sum 
add4		equ 	H'7B'	; results of square and sum 
add5		equ 	H'7C'	; results of square and sum 
add6	 	equ 	H'7D'	; results of square and sum  

div		equ 	H'7E'	; results of square and sum msb
 		
wavsamp	equ	H'7F'	; number of wav samples

; A0 to FF 	page1 address**************************************************

icof1		equ	H'A0'	; lsw current coef
icof2		equ	H'A1'	; msw current coef

vcof1		equ	H'A2'	; lsw volts coef
vcof2		equ	H'A3'	; msw volts coef

coffdiv	equ	H'A4'	; coeff divisor 

rmsch		equ	H'A5'	; channel memory 

ioffset1	equ	H'A6'	; current channel offset correction 
ioffset2	equ	H'A7'	; current channel offset correction 

voffset1	equ	H'A8'	; voltage channel offset correction 
voffset2	equ	H'A9'	; voltage channel offset correction 

aenergy0	equ	H'AA'	; binary acumulated power 
aenergy1	equ	H'AB'	; binary acumulated power 
aenergy2 	equ	H'AC'	; binary acumulated power 
aenergy3 	equ	H'AD'	; binary acumulated power 
aenergy4	equ	H'AE'	; binary acumulated power 
aenergy5 	equ	H'AF'	; binary acumulated power after conversion to kwh
aenergy6 	equ	H'B0'	; binary acumulated power   
aenergy7	equ	H'B1'	; binary acumulated power 
aenergy8	equ	H'B2'	; binary acumulated power 
aenergy9	equ	H'B3'	; binary acumulated power 
aenergy10	equ	H'B4'	; binary acumulated power 

e0		equ	H'B5'	; temp storage for energy before display
e1		equ	H'B6'	; temp storage for energy before display
e2		equ	H'B7'	; temp storage for energy before display
e3		equ	H'B8'	; temp storage for energy before display
e4		equ	H'B9'	; temp storage for energy before display
e5		equ	H'BA'	; temp storage for energy before display




;setup ports 
	

	org	0 	; start at address 0
	clrf    PCLATH            ; ensure page bits are cleared
	GOTO	INITIALIZE
	org	0x0004	; interrupt vector 
	LGOTO	INTERRUPT

;---------LCD control setup I/O--------------------------
  	
#DEFINE lcd7 PORTA,5  	
#DEFINE lcd4 PORTC,0 
#DEFINE lcd5 PORTC,1
#DEFINE lcd6 PORTC,2
#DEFINE lcde PORTA,3
#DEFINE lcdrs PORTC,6
#DEFINE lcdrw PORTC,7

;--------rs232 port setup I/O----------------------------

#DEFINE rsout  PORTA,0
#DEFINE rsin  PORTA,4

;--------7756 control setup I/O--------------------------

#DEFINE irqb  PORTB,0
#DEFINE rstb  PORTB,3
#DEFINE csb   PORTB,4
#DEFINE sagb  PORTB,6

#DEFINE rms  PORTB,1
;end port setup	


;----------------freq setup--------------------

#DEFINE timer  PORTA,1	; timer,0 stop timer,1 start 

#DEFINE mcsb  PORTB,5	; cs for spi rom 



INITIALIZE:

	

TRISTATE:

;=====================check for cal cable set all pins to input============================
; if cable present display cal mode on display and tristate all spi buss pins to allow pc to take over


	bcf	STATUS,6 
	bsf 	STATUS,5	; set to bank 1 
	movlw	H'06'		; set port a to digital same as 16C62B
	movwf	ADCON1
	clrf	PIE1		; clr register in bank 1  
	clrf	PIE2		; clr register in bank 1 
	bcf 	STATUS,5	; set to bank 0
	
	movlw	B'11010111'	; w := 11111010 binary
	tris	PORTA		; port A ctrl register := w
	movlw	B'11111111'	; w := 11111010 binary
	tris	PORTB		; port B ctrl register := w
	movlw	B'00111000'	; w := 11111010 binary			outputs are on for lcd only!!!
	tris	PORTC		; port c ctrl register := w

	nop
	nop

	btfss	PORTB,7		; test for cable if there loop 
	GOTO 	CABLE 
	GOTO 	NORMAL		; normal operation 
CABLE:
	CALL 	INITLCD		; initialize lcd for 4 bit mode


	movlw	A' '		; ascii	" "
	CALL	LCDCHAR
	movlw	A' '		; ascii	" "
	CALL	LCDCHAR
	movlw	A' '		; ascii	" "
	CALL	LCDCHAR
	movlw	A' '		; ascii	" "
	CALL	LCDCHAR
	movlw	A'C'		; ascii	"C"
	CALL	LCDCHAR
	movlw	A'A'		; ascii	"A"
	CALL	LCDCHAR
	movlw	A'L'		; ascii 	"L"
	CALL	LCDCHAR
 	movlw	A' '		; ascii 	" "
  	CALL	LCDCHAR
    	movlw	A'M'		; ascii 	"M"
  	CALL	LCDCHAR
   	movlw	A'O'		; ascii 	"O"
 	CALL	LCDCHAR
 	movlw	A'D'		; ascii 	"D"
	CALL	LCDCHAR
  	movlw	A'E'		; ascii 	"E"
	CALL	LCDCHAR
	
CABLE3:	GOTO	CABLE3


;=====================if no cable normal operation then norma operation========================
	
NORMAL:

; port A is for rs232 serial comunications bit 5 is for LCD data4
; port B is for 7756 comunication and control 
; port C is for LCD data, LCD control and serial epprom 

	bcf	STATUS,6 
	bsf 	STATUS,5	; set to bank 1 
	movlw	H'06'		; set port a to digital same as 16C62B
	movwf	ADCON1
	clrf	PIE1		; clr register in bank 1  
	clrf	PIE2		; clr register in bank 1 
	bcf 	STATUS,5	; set to bank 0
	
	movlw	B'11010110'	; w := 11111010 binary
	tris	PORTA		; port A ctrl register := w
				; port A is 4 bits wide 
				;  
				; ra0 and ra1 will be used for serial com

				; ra0 as xmit rs232
				; ra1 as rcv  rs232
				; ra2 will be used for lcd enable
				; ra3 lcd enable 
				; ra4 will serve as interrupt in 
				; ra5 LCD databit 4

				; setting a bit to '1' = an input
	movlw	B'010000111'	; w := 11000011 binary
	tris	PORTB		; port B ctrl register := w
				; sets rb0 and rb1 as in
				; set rb1,2,3,4,5,6 as out for com with 7756
				; rb0 in from /IRQ on 7756		input 
				; rb1 input from rms select 		input  
				; rb2 not used 			  	output 
				; rb3 out to /reset in on 7756		output 
				; rb4 out to /chip select on 7756 	output
			 	; rb5 out to serial clock on 7756 	output 
				; 

	movlw	B'00010000'
	tris	PORTC		; port C ctrl register := w
 

	movlw	B'10111100'	; w := 00111100 binary
	movwf	PORTB		; port B itself := w sets all output of PORTB high
	 	
	bsf	PORTA,0		; set PORTA bit 0 to "1" rs232 inactive state
	bcf	PORTB,7		; set clk to low
	bcf	PORTB,3		; set /reset to 7756 low
	bsf	PORTB,3		; set /reset to 7756 high 
	bsf	PORTB,4		; set /cs to 7756 high
  
;--------------- this will set timer 0 to ff and no prescale increment on falling 
;		edge. This will generate and interrupt and service serial in routine
;
;				; 1 enable 0 disable 

	clrf	INTCON		; set intcon to 00000000		
	bcf	INTCON,7	; disable all interrupts		CLR DISABLE                   
	bcf	INTCON,6	; enable disable peripheral int bits	CLR DISABLE 
	bcf	INTCON,5 	; enable tmr0 overflow interrupt 	CLR DISABLE 
	bsf	INTCON,4 	; enable rb0/int  			CLR DISABLE 
	bcf	INTCON,3 	; PORT B INTERRUPT ON CHANGE     	CLR DISABLE 
	bcf	INTCON,2	; clear tmr0 overflow interrupt bit 
	bcf	INTCON,1	;  
	bcf	INTCON,0	;  

	bcf	INTCON,7	; disable all interrupts
	bsf	STATUS,5	; set to bank 1 
	bcf	OPTION_REG,7	; enable pullups on port b
	bcf	OPTION_REG,6	; int in falling edg of rb0/int 

;	bsf	OPTION_REG,5	; select ra4/tocki as source input to tmr0
;	bsf	OPTION_REG,4	; inc tmr0 on (set for rising clr for falling) edge
;	bsf	OPTION_REG,3	; set prescale to wdt 
;	bcf	OPTION_REG,2	; set prescale to 0
;	bcf	OPTION_REG,1	; set prescale to 0
;	bcf	OPTION_REG,0	; set prescale to 0

	bcf	PIE1,7		; always clear
	bcf	PIE1,6		; A/D converter interrupt enable 
	bcf	PIE1,5		; always clear
	bcf	PIE1,4		; always clear
	bcf	PIE1,3		; ssp port interrupt enable 
	bcf	PIE1,2		; ccp1 int enable 
	bcf	PIE1,1		; tmr2 int enable 
	bcf	PIE1,0		; tmr1 int enable for energy measure

	clrf	TMR1L		; clear timer 1 low byte
	clrf	TMR1H		; clear timer 1 high byte

	bcf	STATUS,5	; set to bank 0

;	movlw	H'FF'
	movwf	TMR0		; set timer 0 to FF prep for overflow



;------------------------------ setup timer 1 for energy dump--------------------------------

	movlw	B'00110000'
	movwf	T1CON		; sets up timer 1 prescale/8 increment on internal xtal/4 
				; start and stop is bit 0 




	
;------------------------------ setup spi port for 7756 communication SCLK = 20Mhz/16--------
;
;	movlw	B'00110000'
;	movwf	T1CON		; sets up timer 1 prescale/8 increment on internal xtal/4 
;				; start and stop is bit 0 
;



;------------------------------setup spi port for 7756 communication------------------------------------------------------
;	movlw	B'00000010'	;set up spi as master fos/64 idle state high 
	movlw	B'00000001'	;set up spi as master fos/16 idle state high 
;	movlw	B'00000000'	;set up spi as master fos/4 idle state high 
	movwf	SSPCON		; mov w to spi control register 
	movlw	B'00000000'
	bsf     STATUS,5        ; set to bank 1
	movwf	SSPSTAT		; set up clk edges 
	bcf     STATUS,5        ; set to bank 0
;	movlw	B'00100000'		; set up spi as master fos/4 idle state high 
;	movlw	B'00100001'		; set up spi as master fos/16 idle state high 
;	movwf	SSPCON		; mov w to spi control register 

	bsf	SSPCON,5

;------------------------------end port setup------------------------------------------------------	

;------------------------------clear all registers-------------------------------------------------
	clrf  spi 
	 
	clrf  outd1	 
	clrf  outd2		 	
	clrf  mem	 
	clrf	carry	 
	clrf	wordlen		 	

	clrf	wait	 
	clrf	wait2	 
	clrf	bcd0	 
	clrf	bcd1	 
	clrf	bcd2	 
	clrf	bcd3	 
	clrf	bcd4	 
	clrf	bin0	 
	clrf	bin1	 
	clrf	bin2	 
	clrf	bin3	 
	clrf	bin4	 
	clrf	mode0		 
	clrf	mode1	 
 		 
	clrf	swap_w		 
	clrf	swap_status 

	clrf	sinwait		 
	clrf	bcdtemp	 
	clrf	lcdout		 
	clrf	lcdup	 
	clrf	lcdlow 	 
	clrf	wait3	 
	clrf	insd1	 
	clrf	insd2	 
	clrf	insd3		 
	clrf	insd4		 
	clrf	insd5		 
	clrf	insd6	 
	clrf	insd7	 
	clrf	insd8		 
	clrf	insd9		 
	clrf	insd10		 
	clrf	insd11

	clrf	sample_high
	clrf	sample_middle
	clrf	sample_low

	bsf   STATUS,5     ; set to bank 1	 
	clrf	icof1  
	clrf	icof2
	clrf	vcof1  
	clrf	vcof2
	clrf	coffdiv
	clrf	rmsch
	bcf   STATUS,5    ; set to bank 0 

	CALL 	INITLCD	; initialize lcd for 4 bit mode
	
	CALL	ENERGYSET	; recall saved energy from eeprom 
	
	CALL 	KWH		; recall calibration values from eeprom and write to ADE7756 registers


;****--------------Start of read power routine normal operation ------------------------

	clrf 	dave1		; zero sample counter
	clrf 	dave2		
	clrf 	contint	; clear int count for next interrupt 
	bsf	INTCON,7	; enable all unmasked interrupts
	bsf	point,6	

	GOTO START1

ENGREAD1:
	movlw	B'00000011'	; mov 03 into w register
	movwf	spi		; output to spi read active energy and reset 
	movlw	b'00010000'	; number of bytes to download B'000(5)(4)(3)(2)(1)' 
	movwf	wordlen	; wordlen is 40 bits. reg is actually 40 bits
	CALL	SPIRX		; CALL SPI read 40 bit word data will be in 
 				; insd1,2,3,4,5.  5 being msb 1 being lsb
 
;---------------test polarity before add and sign extend if necessary----------------------------------------------- 
 
	movlw	B'00000000'	; this sign extends the 40 bit energy register positive 
	movwf	insd6		; to be added to the 80 bit accum. energy register 
	movwf	insd7	
	movwf	insd8
	movwf	insd9
	movwf	insd10		 
	movwf	insd11
	btfss	insd5,7
	GOTO 	POSITIVEE

	movlw	B'11111111'	; this sign extends the 40 bit energy register negative 
	movwf	insd6		; to be added to the 80 bit accum. energy register 
	movwf	insd7	
	movwf	insd8
	movwf	insd9
	movwf	insd10		 
	movwf	insd11

POSITIVEE:

	btfss insd5,7	; test polarity of acc energy
	GOTO 	POSPOL

	movlw	B'00001000'	; upper 4 bits of next command
	CALL 	LCD		; output command to lcd 
	movlw	B'00001111'	; lower 4 bits of last command  display shift to location 40
	CALL 	LCD		; output command to lcd 

	movlw	A'*'		; ascii "*"	= Negative Energy accumulated display updated each energy rear
	CALL	LCDCHAR	; output character to LCD 
	GOTO	POLDONE

POSPOL:
	movlw	B'00001000'	; upper 4 bits of next command
	CALL 	LCD		; output command to lcd 

	movlw	B'00001111'	; lower 4 bits of last command  display shift to location 40
	CALL 	LCD		; output command to lcd 

	movlw	A' '		; ascii " "	= Positive Energy accumulated
	CALL	LCDCHAR	; output character to LCD	

POLDONE: 

	CALL 	MULTBYCOEF	; multiply by energy coeff then add to 88 bit energy accumulator 
	CALL	PLUSORMINUS	; divide energy accu by 2^40 and make positive 
	CALL	DISPLAYKWH	; mov energy to bin0-4 then output kwh( )or(-)
	CALL  BIN2BCD	; convert bin0-4 to bcd
	CALL	LCDUPDATE	; convert bcd to ascII and output to lcd add decimal and remove if indicated 
				; unwanted resolution
	RETURN 


;---------------Multiply the 40-bit read by the econstant register to convert register in WattHour--------------- 		
MULTBYCOEF:
 

	movf 	econstant0,w	; mov econstant0 to mem
	movwf	mem			; mem will be cleared during multiply 
	CALL	MULT10
	movf 	econstant1,w	; mov econstant1 to mem
	movwf	mem			; mem will be cleared during multiply 
	CALL	MULT10
	movf 	econstant2,w	; mov econstant2 to mem
	movwf	mem			; mem will be cleared during multiply 
	CALL	MULT10

	RETURN
	
 
MULT10:
	movlw	D'8'		; number of bits to multiply
	movwf	wordlen	; mov 40 into wordlen
MULTLOOP0:			;					 
				;  
	btfsc	mem,0		; if bit is 1 add insd1-9 to aenergy0-10 		
	CALL	ADDEGY	; add insd1-11 to energy accu. 
	bcf	STATUS,0	;  
	rrf	mem,1		; rotate constant for next bit to multiply 
	bcf	STATUS,0
	rlf 	insd1,1		; rotate for next add 
	rlf 	insd2,1		; rotate for next add 
	rlf 	insd3,1		; rotate for next add 
	rlf 	insd4,1		; rotate for next add 
	rlf 	insd5,1		; rotate for next add 
	rlf 	insd6,1		; rotate for next add 
	rlf 	insd7,1		; rotate for next add 	
	rlf 	insd8,1		; rotate for next add 
	rlf 	insd9,1		; rotate for next add 
	rlf 	insd10,1	; rotate for next add 
	rlf 	insd11,1	; rotate for next add Register is long enought by mult 32 bits
	bcf	STATUS,0
	decfsz wordlen,1	  
	GOTO	MULTLOOP0	; repeat 
 
	RETURN 

ADDEGY:
;-----------------------40 bit add routine results in 88 bit aenergy0-10 10msb
 
 	movf	insd1,w
	bsf	STATUS,5	; page 1
	addwf	aenergy0,1
	bcf	STATUS,5	; page 0	 
 	CALL	CARRYCHK
 	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy1,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy2,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy3,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy4,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy5,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy6,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy7,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK	
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy8,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy9,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy10,1
	bcf	STATUS,5	; page 1
	 

	movf	insd2,w
	bsf	STATUS,5	; page 1
	addwf	aenergy1,1
	bcf	STATUS,5	; page 1	 
 	CALL	CARRYCHK
 	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy2,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy3,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy4,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy5,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy6,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy7,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK	
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy8,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy9,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy10,1
	bcf	STATUS,5	; page 0
  	
	
	movf	insd3,w
	bsf	STATUS,5	; page 1
	addwf	aenergy2,1
	bcf	STATUS,5	; page 0	 
 	CALL	CARRYCHK
 	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy3,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy4,1 
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy5,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy6,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy7,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK	
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy8,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy9,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy10,1
	bcf	STATUS,5	; page 0
	 
	 
	movf	insd4,w
	bsf	STATUS,5	; page 1
	addwf	aenergy3,1
	bcf	STATUS,5	; page 0	 
 	CALL	CARRYCHK
 	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy4,1
	bcf	STATUS,5	; page 0
	CALL	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy5,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy6,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy7,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK	
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy8,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy9,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK 
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy10,1
	bcf	STATUS,5	; page 0
	 
	movf	insd5,w
	bsf	STATUS,5	; page 1
	addwf	aenergy4,1
	bcf	STATUS,5	; page 0	 
 	CALL	CARRYCHK	
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy5,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy6,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy7,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK	
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy8,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy9,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK 
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy10,1
	bcf	STATUS,5	; page 0
	 
	movf	insd6,w
	bsf	STATUS,5	; page 1
	addwf	aenergy5,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy6,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy7,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK	
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy8,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy9,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy10,1
	bcf	STATUS,5	; page 0
	 	

	movf	insd7,w
	bsf	STATUS,5	; page 1
	addwf	aenergy6,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy7,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK	
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy8,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy9,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy10,1
	bcf	STATUS,5	; page 0
	 
	
	movf	insd8,w
	bsf	STATUS,5	; page 1
	addwf	aenergy7,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK	
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy8,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy9,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy10,1
	bcf	STATUS,5	; page 0
 
 	
	movf	insd9,w
	bsf	STATUS,5	; page 1
	addwf	aenergy8,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy9,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy10,1
	bcf	STATUS,5	; page 0
	 
	movf	insd10,w
	bsf	STATUS,5	; page 1
	addwf	aenergy9,1
	bcf	STATUS,5	; page 0
	CALL 	CARRYCHK
	movf	carry,w
	bsf	STATUS,5	; page 1
	addwf	aenergy10,1
	bcf	STATUS,5	; page 0
 	
	movf	insd11,w
	bsf	STATUS,5	; page 1
	addwf	aenergy10,1
	bcf	STATUS,5	; page 0
	
	RETURN
 

CARRYCHK:
	clrf	carry		; clear carry register 
	btfsc	STATUS,0	; test status reg carry bit. skip if clr
	incf	carry,1	; increment carry 
	RETURN

;-----------------------------end 40 bit add routine------------------------

PLUSORMINUS:
;-------------divide by 2^40 the result of Aenergyxeconstant
; mov aenergy5-10 to e0-e5 for temporary manipulation before conversion to ascII

	bsf 	STATUS,5	; page 1
	movf	aenergy5,w
	movwf	e0
	movf	aenergy6,w
	movwf	e1
	movf	aenergy7,w
	movwf	e2
	movf	aenergy8,w
	movwf	e3
	movf	aenergy9,w
	movwf	e4
	movf	aenergy10,w
	movwf	e5
 
	btfss	aenergy10,7	;test for sign extension
	GOTO	PLORMIEND

	comf	e0,1		; complement and add 1
	comf	e1,1
	comf	e2,1
	comf	e3,1
	comf	e4,1
	comf	e5,1	
 
	bcf	STATUS,0	; clear carry
	movlw	B'00000001'
	addwf	e0,1		; add 1 and ripple if carry jump when no carry to PLORMIEND
	btfss	STATUS,0
	GOTO	PLORMIEND
	bcf	STATUS,0	; clear carry
	movlw	B'00000001'
	addwf	e1,1
	btfss	STATUS,0
	GOTO	PLORMIEND
	bcf	STATUS,0	; clear carry
	movlw	B'00000001'	 
	addwf	e2,1
	btfss	STATUS,0
	GOTO	PLORMIEND
	bcf	STATUS,0	; clear carry
	movlw	B'00000001' 
	addwf	e3,1
	btfss	STATUS,0
	GOTO	PLORMIEND
	bcf	STATUS,0	; clear carry
	movlw	B'00000001' 
	addwf	e4,1
	bcf	STATUS,0	; clear carry
	GOTO	PLORMIEND
	bcf	STATUS,0	; clear carry
	movlw	B'00000001' 
	addwf	e5,1
	bcf	STATUS,0	; clear carry
	

PLORMIEND:
	bcf	STATUS,5	; page 0
	RETURN


;----------------Display the result kWhour on the LCD---------------------------
; moves the selected range of the energy accumulator (aenergy0:10) for bin2bcd conversion
DISPLAYKWH:
	bsf	STATUS,5	; page 1
	movf 	e0,w
	bcf	STATUS,5	; page 0
	movwf	bin0		; mov energy5-9 to bin 0-4 for bcd conversion 
	bsf	STATUS,5	; page 1
	movf 	e1,w
	bcf	STATUS,5	; page 0
	movwf	bin1
	bsf	STATUS,5	; page 1
	movf 	e2,w
	bcf	STATUS,5	; page 0
	movwf	bin2
	bsf	STATUS,5	; page 1
	movf 	e3,w
	bcf	STATUS,5	; page 0
	movwf	bin3
	bsf	STATUS,5	; page 1
	movf	e4,w
	bcf	STATUS,5	; page 0
	movwf	bin4


	movlw	B'00001000'	; upper 4 bits of next command
	CALL 	LCD		; output command to lcd 
	movlw	B'00000000'	; lower 4 bits of last command  display shift to location 40
	CALL 	LCD		; output command to lcd 


	CALL	DELCD		; wait for last LCD command to complete 
	CALL 	DELCD
 	CALL 	DELCD
	CALL 	DELCD

			
	 
	movlw	A'K'		; ascii "K"
	CALL	LCDCHAR	; output char to lcd 

	movlw	A'w'		; ascii "w"
	CALL	LCDCHAR	; output char to lcd 

	movlw	A'h'		; ascii "h"
	CALL	LCDCHAR	; output char to lcd 
	bsf	STATUS,5	; page1
	btfss	aenergy10,7	; test for sign extension
	GOTO	PSIGN0	; displays "-" sign if neg energy
	bcf	STATUS,5	; page 0
	movlw	A'-'		; ascii "-"
	CALL	LCDCHAR	; output char to lcd 		
 	GOTO 	PSIGN1
PSIGN0:	
	bcf	STATUS,5	; page 0
	movlw	A' '		; ascii " " if positive
	CALL	LCDCHAR

PSIGN1:

	RETURN
;----------------------------------------------------------------------------------------

				; CALL EEPWAIT
EEPWAIT:			; wait for spi buffer to empty 
	bsf   STATUS,5    ; set to bank 1
MXLOOP1:
	btfss	SSPSTAT,0	; wait for completion
	GOTO	MXLOOP1
	bcf 	STATUS,5

	RETURN

ENERGYSET:

;-----------------------------Save the Active Energy in the EEPROM------------------------
; first two writes set up start address for block read. each word is shifted out after 8 clock pulses.
; keep clocking and each  work is sent out in order until eeprom cs is set high. will roll over to the 
; address after 16 words. 

	CALL 	SPIEEPROM	; call routine to setup spi port for eeprom rising edge transfer
 
	bcf	mcsb		; clear chip select for eeprom 	

	bsf   STATUS,5  ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5  ; set to bank 0
	movlw	B'00000011'	; write instruction 
	bcf	mcsb		; clear chip select for eeprom 
	movwf	SSPBUF	; output 8 bit word msb first (mode and A8 bit) 	
	CALL EEPWAIT

	bsf     STATUS,5  ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf     STATUS,5  ; set to bank 0
	movlw	B'00000000'	; start at address 00  
	bcf	mcsb		; clear chip select for eeprom 
	movwf	SSPBUF	; output 8 bit word msb first 	
	CALL EEPWAIT


	
	CALL	MEMDATAIN	; read 8 bit of data from eeprom starting at 00 inc address each memdatain until
				; mcsb goes hi
	bsf	STATUS,5	; page1
	movwf	aenergy0
	bcf	STATUS,5	; page0

	CALL	MEMDATAIN
	bsf	STATUS,5	; page1
	movwf	aenergy1
	bcf	STATUS,5	; page0

	CALL	MEMDATAIN
	bsf	STATUS,5	; page1
	movwf	aenergy2
	bcf	STATUS,5	; page0


	CALL	MEMDATAIN
	bsf	STATUS,5	; page1
	movwf	aenergy3
	bcf	STATUS,5	; page0

	
	CALL	MEMDATAIN
	bsf	STATUS,5	; page1
	movwf	aenergy4
	bcf	STATUS,5	; page0

	
	CALL	MEMDATAIN
	bsf	STATUS,5	; page1
	movwf	aenergy5
	bcf	STATUS,5	; page0


	CALL	MEMDATAIN
	bsf	STATUS,5	; page1
	movwf	aenergy6
	bcf	STATUS,5	; page0


	CALL	MEMDATAIN
	bsf	STATUS,5	; page1
	movwf	aenergy7
	bcf	STATUS,5	; page0


	CALL	MEMDATAIN
	bsf	STATUS,5	; page1
	movwf	aenergy8
	bcf	STATUS,5	; page0


	CALL	MEMDATAIN
	bsf	STATUS,5	; page1
	movwf	aenergy9
	bcf	STATUS,5	; page0


	CALL	MEMDATAIN
	bsf	STATUS,5	; page1
	movwf	aenergy10
	bcf	STATUS,5	; page0

	bsf	mcsb		; write enable eeprom 

	CALL 	SPI7756	; sets spi port to talk to 7756 data latch on the falling edge.

	RETURN

ENERGYDUMP:
; 		dump energy to eeprom starting at address 00 when called by interrupt routine 
:           after sag is detected

	CALL 	SPIEEPROM	; call routine to setup spi port for eeprom rising edge transfer

;====================================================================================
	
	bsf	csb		; set 7756 csb to high if not already  		
	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5    ; set to bank 0
	movlw	B'00000110'	; WREN instruction 
	bcf	mcsb		; clear chip select for eeprom 
	movwf	SSPBUF	; output 8 bit word msb first (mode and A8 bit) 	
	CALL EEPWAIT	; wait for spi buff to be empty
	bsf	mcsb		; write enable eeprom  

;=====================================================================================

 		
bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5    ; set to bank 0
	movlw	B'00000010'	; write instruction 
	bcf	mcsb		; clear chip select for eeprom 
	movwf	SSPBUF	; output 8 bit word msb first (mode and A8 bit) 	
	CALL EEPWAIT

	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5    ; set to bank 0
	movlw	B'00000000'	; start at address 00  
	movwf	SSPBUF	; output 8 bit word msb first 	
	CALL EEPWAIT
	
	bsf	STATUS,5	; page 1
	movf	aenergy0,w	
	bcf	STATUS,5	; page 0	
	CALL	MEMDATAOUT	; start at address 00 and increment for each memdataout

	bsf	STATUS,5	; page 1
	movf	aenergy1,w
	bcf	STATUS,5	; page 0	
	CALL	MEMDATAOUT

	bsf	STATUS,5	; page 1
	movf	aenergy2,w
	bcf	STATUS,5	; page 0	
	CALL	MEMDATAOUT

	bsf	STATUS,5	; page 1
	movf	aenergy3,w 
	bcf	STATUS,5	; page 0	
	CALL	MEMDATAOUT

	bsf	STATUS,5	; page 1
	movf	aenergy4,w
	bcf	STATUS,5	; page 0	
	CALL	MEMDATAOUT

	bsf	STATUS,5	; page 1
	movf	aenergy5,w
	bcf	STATUS,5	; page 0	
	CALL	MEMDATAOUT

	bsf	STATUS,5	; page 1
	movf	aenergy6,w 
	bcf	STATUS,5	; page 0	
	CALL	MEMDATAOUT

	bsf	STATUS,5	; page 1
	movf	aenergy7,w 
	bcf	STATUS,5	; page 0	
	CALL	MEMDATAOUT

	bsf	STATUS,5	; page 1
	movf	aenergy8,w 
	bcf	STATUS,5	; page 0	
	CALL	MEMDATAOUT

	bsf	STATUS,5	; page 1
	movf	aenergy9,w 
	bcf	STATUS,5	; page 0	
	CALL	MEMDATAOUT

	bsf	STATUS,5	; page 1
	movf	aenergy10,w
	bcf	STATUS,5	; page 0	
	CALL	MEMDATAOUT

	bsf	mcsb		; setting memory /cs starts block write in eeprom 
	
	CALL	CHECKWRITE	; is write complete???

	CALL 	SPI7756	; sets spi port to talk to 7756 data latch on the falling edge.
	RETURN

MEMDATAOUT:
  
	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5    ; set to bank 0
	movwf	SSPBUF	; output 8 bit word msb first 	
	CALL  EEPWAIT

	RETURN

CHECKWRITE:
			
	bsf   STATUS,5  	; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5   	; set to bank 0
	movlw	B'00000101'	;read status register 
	bcf	mcsb		; clear chip select for eeprom 
	movwf	SSPBUF	; output 8 bit word msb first (mode and A8 bit) 	
	CALL  EEPWAIT

	CALL	MEMDATAIN
	bsf	mcsb		; set chip select for eeprom
	btfsc	SSPBUF,0	; check to see if wpi bit is set if so repeat until clear	
	GOTO 	CHECKWRITE	
	
	RETURN

SPIEEPROM:
				; CALL	SPIEEPROM
	;------------------------------setup spi port------------------------------------------------------

	bsf	csb		; clear enable for csb 7756
	bcf	SSPCON,5	; disable port for reconfiguring 
	movlw	B'01000000'
	bsf   STATUS,5 	; set to bank 1
	movwf	SSPSTAT	; set up clk edges 
	bcf   STATUS,5    ; set to bank 0
	bsf	SSPCON,5	; enable spi port after changes
	RETURN

MEMDATAIN:

	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag
	bcf   STATUS,5    ; set to bank 0
	movf	H'0',w	; lower eight bits
	movwf	SSPBUF	; output starts after mov command 
	bsf   STATUS,5    ; set to bank 1
	CALL  EEPWAIT
	movf	SSPBUF,w
	RETURN


SPI7756:
			
;------------------------------ setup spi port	 CALL SPI7756 ------------------------------------------------------
				

	bcf	SSPCON,5	; disable port for reconfiguring 
	movlw	B'00000000'
	bsf   STATUS,5    ; set to bank 1
	movwf	SSPSTAT	; set up clk edges 
	bcf   STATUS,5    ; set to bank 0
	bsf	SSPCON,5	; enable spi port after changes
	RETURN

;---------------------------------------------------------
;
;start read of spi port of X bit reg defined by spicnt 
;
;----------------------------------------------------------


SPIRX: 
	
	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5  	; set to bank 0
	movf	spi,w		; spi control word (first 8 bits)
	bcf 	csb		; set  to 0 /cs pin
	movwf	SSPBUF	; output 8 bit word msb first 

	bsf   STATUS,5    ; set to bank 1
LOOPSPI:
	btfss	SSPSTAT,0	; wait for completion
	GOTO	LOOPSPI	; wait for output buffer empty 
	bcf   STATUS,5    ; set to bank 0

	clrf	insd1		; clear input data registers 
	clrf	insd2
	clrf	insd3
	clrf	insd4
	clrf	insd5
	
	btfsc	wordlen,4	; input 40 bits if set 5 bytes
	GOTO	bit40
	btfsc	wordlen,3	; input 32 bits if set 4 bytes
	GOTO	bit32
	btfsc	wordlen,2	; input 24 bits if set 3 bytes
	GOTO	bit24
	btfsc	wordlen,1	; input 16 bits if set 2 bytes
	GOTO	bit16
	btfsc	wordlen,0	; input 8 bits if set 1 bytes
	GOTO	bit8


bit40:
	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag
	bcf   STATUS,5    ; set to bank 0
	movf	H'0',w	; lower eight bits
	movwf	SSPBUF	
	bsf   STATUS,5    ; set to bank 1
LOOP40:
	btfss	SSPSTAT	; wait for completion
	GOTO	LOOP40
	bcf   STATUS,5    ; set to bank 0
	movf	SSPBUF,w
	movwf	insd5


bit32:
	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag
	bcf   STATUS,5    ; set to bank 0
	movf	H'0',w	; lower eight bits
	movwf	SSPBUF	
	bsf   STATUS,5    ; set to bank 1
LOOP32:
	btfss	SSPSTAT,0	; wait for completion
	GOTO	LOOP32
	bcf   STATUS,5    ; set to bank 0
	movf	SSPBUF,w
	movwf	insd4
	 

bit24:
	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag
	bcf   STATUS,5    ; set to bank 0
	movf	H'0',w	; lower eight bits
	movwf	SSPBUF	
	bsf   STATUS,5    ; set to bank 1
LOOP24:
	btfss	SSPSTAT,0	; wait for completion
	GOTO	LOOP24
	bcf   STATUS,5    ; set to bank 0
	movf	SSPBUF,w
	movwf	insd3
	

bit16:
	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag
	bcf   STATUS,5    ; set to bank 0
	movf	H'0',w	; lower eight bits
	movwf	SSPBUF	
	bsf   STATUS,5    ; set to bank 1
LOOP16:	
	btfss	SSPSTAT,0	; wait for completion
	GOTO	LOOP16
	bcf   STATUS,5    ; set to bank 0	
	movf	SSPBUF,w
	movwf	insd2

 
bit8:
	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag
	bcf   STATUS,5    ; set to bank 0
	movf	H'0',w	; lower eight bits
	movwf	SSPBUF	
	bsf   STATUS,5    ; set to bank 1
LOOP8:
	btfss	SSPSTAT,0	; wait for completion
	GOTO	LOOP8
	bcf   STATUS,5    ; set to bank 0 
	movf	SSPBUF,w
	movwf	insd1

	bsf	csb		; set /cs to 1
	RETURN


;------------------------end spi control write---------------------- 

;-----------------------------------------------------------
;
;	This routine writes to the 7756 spi control 
;	control data (first 8 bits before data read or write)
; 
;	OUTPUT 8 BIT SPI CONTROL AND 8 OR 16 BIT DATA 
;	34us FOR 8+16 BIT AND 26us FOR 8+8 BIT 
;-------------------------------------------------------------------


SPIDX:

	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5    ; set to bank 0
	movf	spi,w
	bcf 	csb		; set  to 0 /cs pin
	movwf	SSPBUF	; output 8 bit word msb first
 	
	bsf   STATUS,5    ; set to bank 1
TXLOOP1:
	btfss	SSPSTAT,0	; wait for completion
	GOTO	TXLOOP1
;------------------------end spi control write---------------------- 
 
;------------------------start of data------------------------------
	bsf     STATUS,5  ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag
	bcf     STATUS,5  ; set to bank 0
	btfsc	wordlen,3	; test for 8 or 16 bits 
	GOTO	eight	  
	movf	outd2,w	; upper eight bits 
	movwf	SSPBUF	; move word to buffer 

	bsf     STATUS,5  ; set to bank 1
TXLOOP2:
	btfss	SSPSTAT,0	; wait for completion
	GOTO	TXLOOP2

eight:	 
	bsf     STATUS,5  ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag
	bcf     STATUS,5  ; set to bank 01
	movf	outd1,w	; lower eight bits
	movwf	SSPBUF	

	bsf     STATUS,5  ; set to bank 1
TXLOOP3:
	btfss	SSPSTAT,0	; wait for completion
	GOTO	TXLOOP3
	bcf 	STATUS,5


	bsf	csb		; set /cs to 1

	RETURN


;-----------------end spi control and data (x) out--------------------

;----------------------------ASCII 8 bit to 2 4bit words for lcd------


LCDCHAR:
	movwf	lcdup      	;
	movwf	lcdlow     	;       
	movlw	B'11110000'	; for masking lower bits
	andwf   lcdup,1	; lcdupper= xxxx0000
	swapf	lcdup,1	; lcdupper= 0000xxxx	
	movlw	B'00010000'	; add data command to lcd output
	addwf	lcdup,0	; "          "                "
	CALL	LCD		; output upper 4 bits to lcd	
	movlw	B'00001111'	; for masking upper bits
	andwf   lcdlow,1	; lcdlower= 0000xxxx	
 	movlw	B'00010000'	; add data command to lcd output
	addwf	lcdlow,0	; "          "                "
	CALL	LCD		; output lower 4 bits
	
	RETURN

;------------------end ascii convert for lcd--------------------------


KWH:


;-----------------------------------------------------------------------------------------------------------

;-----------------This initializes the part as a power meter------------------------------------------------	
; 156us for 8bit control and 16 bit data, 112us for 8bit control and 8 bit out   	 


; RECALL 7756 SETTINGS FROM EEPROM 


; first two writes set up start address for block read. each word is shifted out after 8 clock pulses.
; keep clocking and each  work is sent out in order until eeprom cs is set high. will roll over to the 
; address after 16 words. 


;------------------------------cf read----------------------------------------------------------------------

CALL 	SPIEEPROM	; call routine to setup spi port for eeprom rising edge transfer
 
	bcf	mcsb		; clear chip select for eeprom 	

	bsf   STATUS,5  	; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5  	; set to bank 0
	movlw	B'00000011'	; read instruction 
	movwf	SSPBUF	; output 8 bit word msb first (mode and A8 bit) 	
	CALL 	EEPWAIT

	bsf  	STATUS,5   	; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5   	; set to bank 0
	movlw	D'16'		; start at address 16 PAGE 2  
	movwf	SSPBUF	; output 8 bit word msb first 	
	CALL EEPWAIT
	
	CALL	MEMDATAIN	; get address 16
	movwf outd1
	CALL	MEMDATAIN	; get address 17
	movwf outd2

	movlw	B'10000111'	; command to write to cfdiv register 
	movwf spi		; call spi control write to cfdiv reg
	movlw	D'16'		; number of bits
	movwf	wordlen
	bsf	mcsb		; chip select high 
	CALL 	SPI7756	; sets spi port to talk to 7756 data latch on the falling edge.
	CALL	SPIDX		; output outd1 and outd2 to 7756
;-------------------------------------------------------------------------------------------------------------
	

;------------------------------apgain read--------------------------------------------------------------------

	CALL 	SPIEEPROM	; call routine to setup spi port for eeprom rising edge transfer
 
	bcf	mcsb		; clear chip select for eeprom 	

	bsf  	STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5    ; set to bank 0
	movlw	B'00000011'	; read instruction 
	movwf	SSPBUF	; output 8 bit word msb first (mode and A8 bit) 	
	CALL EEPWAIT

	bsf  	STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5    ; set to bank 0
	movlw	D'18'		; start at address 18 PAGE 2  
	movwf	SSPBUF	; output 8 bit word msb first 	
	CALL EEPWAIT
	
	CALL	MEMDATAIN	; get address 18
	movwf outd1
	CALL	MEMDATAIN	; get address 19
	movwf outd2
	
	movlw	B'10001011'	; command to write to apgain register 
	movwf spi		; call spi control write to apgain reg
	movlw	D'16'		; number of bits
	movwf	wordlen
	bsf	mcsb		; chip select high 
	CALL 	SPI7756	; sets spi port to talk to 7756 data latch on the falling edge.
	CALL	SPIDX		; output outd1 and outd2 to 7756
;-------------------------------------------------------------------------------------------------------------
	
;------------------------------apos read----------------------------------------------------------------------

	CALL 	SPIEEPROM	; call routine to setup spi port for eeprom rising edge transfer
 
	bcf	mcsb		; clear chip select for eeprom 	

	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5    ; set to bank 0
	movlw	B'00000011'	; read instruction 
	movwf	SSPBUF		; output 8 bit word msb first (mode and A8 bit) 	
	CALL EEPWAIT

	bsf   STATUS,5   	; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5   	; set to bank 0
	movlw	D'37'		; start at address 37 PAGE 3 
	movwf	SSPBUF	; output 8 bit word msb first 	
	CALL EEPWAIT
	
	CALL	MEMDATAIN	; get address 37
	movwf	outd1

	CALL	MEMDATAIN	; get address 38
	movwf	outd2

	movlw	B'10001101'	; command to write to apos register 
	movwf spi		; call spi control write to apos reg
	movlw	D'16'		; number of bits
	movwf	wordlen
	bsf	mcsb		; chip select high 
	CALL 	SPI7756	; sets spi port to talk to 7756 data latch on the falling edge.
	CALL	SPIDX		; output outd1 and outd2 to 7756

;-------------------------------------------------------------------------------------------------------------

;------------------------------icoef---------------------------------------------------------------------

	CALL 	SPIEEPROM	; call routine to setup spi port for eeprom rising edge transfer
 
	bcf	mcsb		; clear chip select for eeprom 	

	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5    ; set to bank 0
	movlw	B'00000011'	; read instruction 
	movwf	SSPBUF	; output 8 bit word msb first (mode and A8 bit) 	
	CALL EEPWAIT

	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5    ; set to bank 0
	movlw	D'21'		; start at address 21 PAGE 2  
	movwf	SSPBUF	; output 8 bit word msb first 	
	CALL EEPWAIT
	
	CALL	MEMDATAIN	; get address 21
	movwf outd1

	movlw	B'10001000'	; command to write to ch1os register 
	movwf spi		; call spi control write to ch1os reg
	movlw	D'8'		; number of bits
	movwf	wordlen
	bsf	mcsb		; chip select high 
	CALL 	SPI7756	; sets spi port to talk to 7756 data latch on the falling edge.
	CALL	SPIDX		; output outd1 to 7756 

;-------------------------------------------------------------------------------------------------------------

;------------------------------ch2os read-------------------------------------------------------------

	CALL 	SPIEEPROM	; call routine to setup spi port for eeprom rising edge transfer
 
	bcf	mcsb		; clear chip select for eeprom 	

	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5    ; set to bank 0
	movlw	B'00000011'	; read instruction 
	movwf	SSPBUF	; output 8 bit word msb first (mode and A8 bit) 	
	CALL EEPWAIT

	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5    ; set to bank 0
	movlw	D'22'		; start at address 22 PAGE 2  
	movwf	SSPBUF	; output 8 bit word msb first 	
	CALL EEPWAIT
	
	CALL	MEMDATAIN	; get address 22
	movwf outd1

	movlw	B'10001001'	; command to write to ch2os register 
	movwf spi		; call spi control write to ch2os reg
	movlw	D'8'		; number of bits
	movwf	wordlen
	bsf	mcsb		; chip select high 
	CALL 	SPI7756	; sets spi port to talk to 7756 data latch on the falling edge.
	CALL	SPIDX		; output outd1 to 7756

;-------------------------------------------------------------------------------------------------------------

;------------------------------gain read-------------------------------------------------------------

	CALL 	SPIEEPROM	; call routine to setup spi port for eeprom rising edge transfer
 
	bcf	mcsb		; clear chip select for eeprom 	

	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5    ; set to bank 0
	movlw	B'00000011'	; read instruction 
	movwf	SSPBUF	; output 8 bit word msb first (mode and A8 bit) 	
	CALL EEPWAIT

	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5    ; set to bank 0
	movlw	D'23'		; start at address 23 PAGE 2  
	movwf	SSPBUF	; output 8 bit word msb first 	
	CALL EEPWAIT
	
	CALL	MEMDATAIN	; get address 23
	movwf	outd1

	movlw	B'10001010'	; command to write to gain register 
	movwf spi		; call spi control write to gain reg
	movlw	D'8'		; number of bits
	movwf	wordlen
	bsf	mcsb		; chip select high 
	CALL 	SPI7756	; sets spi port to talk to 7756 data latch on the falling edge.
	CALL	SPIDX		; output outd1 to 7756

;-------------------------------------------------------------------------------------------------------------
;------------------------------phcal  read-------------------------------------------------------------

	CALL 	SPIEEPROM	; call routine to setup spi port for eeprom rising edge transfer
 
	bcf	mcsb		; clear chip select for eeprom 	

	bsf   STATUS,5   	; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5    ; set to bank 0
	movlw	B'00000011'	; read instruction 
	movwf	SSPBUF	; output 8 bit word msb first (mode and A8 bit) 	
	CALL EEPWAIT

	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5    ; set to bank 0
	movlw	D'24'		; start at address 24 PAGE 2  
	movwf	SSPBUF	; output 8 bit word msb first 	
	CALL EEPWAIT
	
	CALL	MEMDATAIN	; get address 24
	movwf outd1

	movlw	B'10001100'	; command to write to phcal register 
	movwf spi		; call spi control write to phcal reg
	movlw	D'8'		; number of bits
	movwf	wordlen
	bsf	mcsb		; chip select high 
	CALL 	SPI7756	; sets spi port to talk to 7756 data latch on the falling edge.
	CALL	SPIDX		; output outd1 to 7756

;-------------------------------------------------------------------------------------------------------------

;------------------------------sagcyc  read-------------------------------------------------------------

	CALL 	SPIEEPROM	; call routine to setup spi port for eeprom rising edge transfer
 
	bcf	mcsb		; clear chip select for eeprom 	

	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5    ; set to bank 0
	movlw	B'00000011'	; read instruction 
	movwf	SSPBUF	; output 8 bit word msb first (mode and A8 bit) 	
	CALL EEPWAIT

	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5    ; set to bank 0
	movlw	D'25'		; start at address 25 PAGE 2  
	movwf	SSPBUF	; output 8 bit word msb first 	
	CALL EEPWAIT
	
	CALL	MEMDATAIN	; get address 25
	movwf outd1

	movlw	B'10001111'	; command to write to sagcyc register 
	movwf spi		; call spi control write to sagcyc reg
	movlw	D'8'		; number of bits
	movwf	wordlen
	bsf	mcsb		; chip select high 
	CALL 	SPI7756	; sets spi port to talk to 7756 data latch on the falling edge.
	CALL	SPIDX		; output outd1 to 7756

;-------------------------------------------------------------------------------------------------------------

;------------------------------saglvl  read-------------------------------------------------------------

	CALL 	SPIEEPROM	; call routine to setup spi port for eeprom rising edge transfer
 
	bcf	mcsb		; clear chip select for eeprom 	

	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5    ; set to bank 0
	movlw	B'00000011'	; read instruction 
	movwf	SSPBUF	; output 8 bit word msb first (mode and A8 bit) 	
	CALL EEPWAIT

	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5    ; set to bank 0
	movlw	D'26'		; start at address 26 PAGE 2  
	movwf	SSPBUF	; output 8 bit word msb first 	
	CALL EEPWAIT
	
	CALL	MEMDATAIN	; get address 26
	movwf outd1

	movlw	B'10010001'	; command to write to saglvl register 
	movwf spi		; call spi control write to saglvl reg
	movlw	D'8'		; number of bits
	movwf	wordlen
	bsf	mcsb		; chip select high 
	CALL 	SPI7756	; sets spi port to talk to 7756 data latch on the falling edge.
	CALL	SPIDX		; output outd1 and outd2 to 7756

;-------------------------------------------------------------------------------------------------------------

;------------------------------mask  read-------------------------------------------------------------

	CALL 	SPIEEPROM	; call routine to setup spi port for eeprom rising edge transfer
 
	bcf	mcsb		; clear chip select for eeprom 	

	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5    ; set to bank 0
	movlw	B'00000011'	; read instruction 
	movwf	SSPBUF	; output 8 bit word msb first (mode and A8 bit) 	
	CALL EEPWAIT

	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5    ; set to bank 0
	movlw	D'27'		; start at address 27 PAGE 2  
	movwf	SSPBUF	; output 8 bit word msb first 	
	CALL EEPWAIT
	
	CALL	MEMDATAIN	; get address 27
	movlw	b'00000010'
	movwf outd1
	
	movlw	B'10010000'	; command to write to mask register 
	movwf spi		; call spi control write to mask reg
	movlw	D'8'		; number of bits
	movwf	wordlen
	bsf	mcsb		; chip select high 
	CALL 	SPI7756	; sets spi port to talk to 7756 data latch on the falling edge.
	CALL	SPIDX		; output outd1 to 7756

;-------------------------------------------------------------------------------------------------------------

;------------------------------mode read-------------------------------------------------------------

	CALL 	SPIEEPROM	; call routine to setup spi port for eeprom rising edge transfer
 
	bcf	mcsb		; clear chip select for eeprom 	

	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5    ; set to bank 0
	movlw	B'00000011'	; read instruction 
	movwf	SSPBUF	; output 8 bit word msb first (mode and A8 bit) 	
	CALL EEPWAIT

	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5    ; set to bank 0
	movlw	D'28'		; start at address 28 PAGE 2  
	movwf	SSPBUF	; output 8 bit word msb first 	
	CALL EEPWAIT
	
	CALL	MEMDATAIN	; get address 28
	movwf outd1
	movwf	mode0
	CALL	MEMDATAIN	; get address 29
	movwf outd2
	movwf	mode1
	movlw	B'10000110'	; command to write to mode register 
	movwf spi		; call spi control write to mode reg
	movlw	D'16'		; number of bits
	movwf	wordlen
	bsf	mcsb		; chip select high 
	CALL 	SPI7756	; sets spi port to talk to 7756 data latch on the falling edge.
	CALL	SPIDX		; output outd1 and outd2 to 7756

;-------------------------------------------------------------------------------------------------------------

;------------------------------zxout read-------------------------------------------------------------

	CALL 	SPIEEPROM	; call routine to setup spi port for eeprom rising edge transfer
 
	bcf	mcsb		; clear chip select for eeprom 	

	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5  	; set to bank 0
	movlw	B'00000011'	; read instruction 
	movwf	SSPBUF	; output 8 bit word msb first (mode and A8 bit) 	
	CALL EEPWAIT

	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5    ; set to bank 0
	movlw	D'30'		; start at address 30 PAGE 2  
	movwf	SSPBUF	; output 8 bit word msb first 	
	CALL EEPWAIT
	
	CALL	MEMDATAIN	; get address 30
	movwf outd1
	CALL	MEMDATAIN	; get address 31
	movwf outd2

	movlw	B'10001110'	; command to write to zxout register 
	movwf spi		; call spi control write to zxout reg
	movlw	D'16'		; number of bits
	movwf	wordlen
	bsf	mcsb		; chip select high 
	CALL 	SPI7756	; sets spi port to talk to 7756 data latch on the falling edge.
	CALL	SPIDX		; output outd1 and outd2 to 7756

;-------------------------------------------------------------------------------------------------------------

;------------------------------constant1  read-------------------------------------------------------------

	CALL 	SPIEEPROM	; call routine to setup spi port for eeprom rising edge transfer
 
	bcf	mcsb		; clear chip select for eeprom 	

	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5    ; set to bank 0
	movlw	B'00000011'	; read instruction 
	movwf	SSPBUF		; output 8 bit word msb first (mode and A8 bit) 	
	CALL EEPWAIT

	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5    ; set to bank 0
	movlw	D'32'		; start at address 32 PAGE 3  
	movwf	SSPBUF	; output 8 bit word msb first 	
	CALL EEPWAIT
	
	CALL	MEMDATAIN	; get address 32
	movwf	econstant0

	CALL	MEMDATAIN	; get address 33
	movwf econstant1

	CALL	MEMDATAIN	; get address 34
	movwf	econstant2

	CALL	MEMDATAIN	; get address 35 set bit 7 to show watts clr to show tenths of watts 
	movwf	point 

	CALL	MEMDATAIN	; get address 36 temp offset 
	movwf	tempof 
	
	bsf	mcsb		; chip select high 
	CALL 	SPI7756	; sets spi port to talk to 7756 data latch on the falling edge.


;-------------------------------------------------------------------------------------------------------------

;------------------------------Current Offset and voltage offset for rms------------------------------------

	CALL 	SPIEEPROM	; call routine to setup spi port for eeprom rising edge transfer
 
	bcf	mcsb		; clear chip select for eeprom 	

	bsf   STATUS,5        ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5        ; set to bank 0
	movlw	B'00000011'	; read instruction 
	movwf	SSPBUF		; output 8 bit word msb first (mode and A8 bit) 	
	CALL EEPWAIT

	bsf   STATUS,5    ; set to bank 1
	bcf	SSPSTAT,0	; clear buffer full flag 	  	
	bcf   STATUS,5    ; set to bank 0
	movlw	D'48'		; start at address 48 PAGE 2  
	movwf	SSPBUF	; output 8 bit word msb first 	
	CALL  EEPWAIT
	
	CALL	MEMDATAIN	; get address 48
	bsf	STATUS,5
	movwf	icof1
	bcf	STATUS,5

	CALL	MEMDATAIN	; get address 49
	bsf	STATUS,5
	movwf icof2
	bcf	STATUS,5

	CALL	MEMDATAIN	; get address 50
	bsf	STATUS,5
	movwf vcof1
	bcf	STATUS,5

	CALL	MEMDATAIN	; get address 51
	bsf	STATUS,5
	movwf vcof2
	bcf	STATUS,5

	CALL	MEMDATAIN	; get address 48
	bsf	STATUS,5
	movwf	ioffset1
	bcf	STATUS,5

	CALL	MEMDATAIN	; get address 49
	bsf	STATUS,5
	movwf ioffset2
	bcf	STATUS,5

	CALL	MEMDATAIN	; get address 50
	bsf	STATUS,5
	movwf voffset1
	bcf	STATUS,5

	CALL	MEMDATAIN	; get address 51
	bsf	STATUS,5
	movwf voffset2
	bcf	STATUS,5
	
	bsf	mcsb		; clear chip select for eeprom 	

	CALL 	SPI7756	; sets spi port to talk to 7756 data latch on the falling edge.
	CALL	SPIDX		; 

	RETURN
;-------------------------------------------------------------------------------------------------------------

LCD:
	movwf	lcdout		; mov lcd data+ins/char into lcdout
LCDL:   
	bcf 	lcde		; set lcde low
 	bcf	lcdrw		; set lcd to write 
	bcf	lcdrs		; set rs bit low 
	bcf	lcd4		; clears lcd databit 4-7
	bcf	lcd5
	bcf	lcd6
	bcf	lcd7
	btfsc	lcdout,0	; test lcd data bit 0 if set set lcd4
	bsf	lcd4
	btfsc	lcdout,1	; test lcd data bit 1 if set set lcd5
	bsf	lcd5
	btfsc	lcdout,2	; test lcd data bit 2 if set set lcd6
	bsf	lcd6
	btfsc	lcdout,3	; test lcd data bit 3 if set set lcd7
	bsf	lcd7
	btfsc	lcdout,4	; test lcd data bit 4 if set set lcdrs instruction or character 
	bsf	lcdrs
	CALL	DELAY		; wait for data to stablize before enable 
	CALL	DELAY2	;removed 45 CALL DELAY2's incase of problem 20 mhz

	bsf	lcde		; set lcde high for enable 
	CALL	DELAY		; sets enable pulse width
	CALL	DELAY		; sets enable pulse width 

	CALL	DELAY2	;removed 45 CALL DELAY2's incase of problem 20 mhz
	bcf	lcde		; set lcde low to latch data 	

	RETURN
;------------------------------------------------------------------------------	

DELCD:			; called in initLCD routine

	movlw	D'100'
	movwf	wait3		; mov 100 into wait3 loop 	
WAIT3:
	decfsz	wait3,1		; dec wait if zero return 
 
	GOTO	WAIT3
	RETURN 			; return to lcd routine


;-----------------end of ram to ad7756 register transfer----------------
	RETURN

;-----------------------------------------------------------
;       This is a delay loop USED EVERYWHERE for the LCD routine		    
;-----------------------------------------------------------



DELAY:				; called in rs232 routine
	movlw	D'27'
	movwf	wait	  		; mov 20 into wait loop 	
WAIT:
	decfsz	wait,1	; dec wait if zero return 
	GOTO	WAIT
	RETURN 			; return to rs232 routine



DELAY2:				; called in initLCD routine
	movlw	D'255'
	movwf	wait2	 		; mov 255 into wait2 loop 	
WAIT2:
	decfsz	wait2,1	; dec wait if zero return 
	GOTO	WAIT2
	RETURN 			; return to initlcd routine
;---------------------------end serial output routine-----------------------------

INITLCD:

; sets lcd up for 4bit mode. setup from lcd datasheet

	bCf 	STATUS,5	; GOTO PAGE 0
	movlw	D'150'
	movwf	wait
LCDLOOP:
	CALL	DELAY2	;wait loop1
	decfsz  wait,1
	GOTO 	LCDLOOP

	movlw	B'00000011'	; send 3 to lcd for the 1st time
	CALL 	LCD 

	movlw	D'60'
	movwf	wait
LCDLOOP1:
	CALL	DELAY2	;wait loop 2
	decfsz  wait,1
	goto 	LCDLOOP1

	movlw	B'00000011'	; send 3 to lcd for the 2nd time 
	CALL 	LCD		; call lcd output routine 

 	CALL	DELAY2		;removed 45 CALL DELAY2's incase of problem 20 mhz
	CALL	DELAY2		;removed 45 CALL DELAY2's incase of problem 20 mhz
	CALL	DELAY2		;removed 45 CALL DELAY2's incase of problem 20 mhz
	CALL	DELAY2		;removed 45 CALL DELAY2's incase of problem 20 mhz
		 			
	movlw	B'00000011'	; send 3 to lcd for the 3rd and last time
	CALL 	LCD		; call lcd output routine
 	 		   			
	movlw	B'00000010' 	; set display to 4 bit mode
	CALL 	LCD		; output command
 
	movlw	B'00000010'	; upper 4 bits of next command		
	CALL 	LCD		; output command	
 	
	movlw	B'00001000'	; lower 4 bits of last command     Disp line and font
	CALL 	LCD		; output command
  
	movlw	B'00000000'	; upper 4 bits of next command
	CALL 	LCD		; output command	
 	
	movlw	B'00001000'	; lower 4 bits of last command	   Display off 
	CALL 	LCD		; output command
	
	movlw	B'00000000'	; upper 4 bits of next command
	CALL 	LCD		; output command	
 
	movlw	B'00000001'	; lower 4 bits of last command      Clear display
	CALL 	LCD		; output command		    

	movlw	D'30'
	movwf	wait
LCDLOOP2:
	CALL	DELCD
	decfsz  wait,1
	GOTO 	LCDLOOP2


	movlw	B'00000000'	; upper 4 bits of next command
	CALL 	LCD		; output command	
 	 
	movlw	B'00000110'	; lower 4 bits of last command     Entry mode 
	CALL 	LCD		; output command
	
	movlw	B'00000000'	; upper 4 bits of next command
	CALL 	LCD		; output command	
 
	movlw	B'00001100'	; lower 4 bits of last command     Display on,cursor off
	CALL 	LCD		; output command		   blink off
	 	

	RETURN

;----------------------------end initialization-----------------------------


;-------------------------------------------------------------------------------
;	24-bit binary to BCD conversion.
;
;	Binary input data is taken from bin0-bin4 which is destroyed.
;	The result is stored in bcd0..bcd3, bcd0 holds the two LS Digits.
;
;
;-------------------------------------------------------------------------------

BIN2BCD:
	 
	 
do_b2b:
	movlw	D'32'		; 
	movwf	wordlen	;
	clrf	bcd0		; clear bcd0
	clrf	bcd1		; clear bcd1
	clrf	bcd2		; clear bcd2
	clrf	bcd3		; clear bcd3
	clrf	bcd4		; clear bcd4
BCDLOOP:
	bcf     STATUS,0 
	rlf	bin0,f		; rotate bin to left through carry
	rlf	bin1,f
	rlf	bin2,f
	rlf	bin3,f
	btfsc STATUS,0          
     	bsf   0x0C,0     
	rlf	bcd0,f  		; ...into bcd
	rlf	bcd1,f
	rlf	bcd2,f
	rlf	bcd3,f
	rlf 	bcd4,f
	decfsz	wordlen,f
	GOTO	ADJUST
	RETURN

ADJUST:
	movlw	H'2E'		; make magic adjustment to each BCD digit

	movwf	FSR		; mov address of bcd0 to indirect pointer 
	CALL	ADJBCD
	incf	FSR,f		; increment pointer to bcd1
	CALL	ADJBCD
	incf	FSR,f		; increment pointer to bcd2
	CALL	ADJBCD
	incf	FSR,f		; increment pointer ro bcd3
	CALL	ADJBCD
	incf	FSR,f		; increment pointer ro bcd4
	CALL	ADJBCD
	GOTO	BCDLOOP

ADJBCD:
 	movf    INDF,w                    ; 
        movwf   bcdtemp                 ; 
        movlw   0x33                    ; 
        addwf   bcdtemp,f               ; 
        clrw                            ; 
        btfss   bcdtemp,3               ; 
        iorlw   0x03                    ; 
        btfss   bcdtemp,7               ; 
        iorlw   0x30                    ; 
        subwf   bcdtemp,f               ; 
        movf    bcdtemp,w               ; 
        movwf   INDF                    ; 

	RETURN                      	 

;-------------------end bcd convert-----------------------------------

 
LCDUPDATE:

	btfss	point,6
	GOTO 	KWHDIGIT	; 

	bsf	STATUS,5
	btfsc	rmsch,0
	GOTO 	RMSSPACE

	bcf	STATUS,5


;	movlw	B'00000000'	; upper 4 bits of next command
;	CALL 	LCD		; output command	
 
;	movlw	B'00000010'	; lower 4 bits of last command      Clear display
;	CALL 	LCD		; output command		    
 
	movlw	B'00001010'	; upper 4 bits of next command
	CALL 	LCD		; output command	
	movlw	B'00001000'	; lower 4 bits of last command  display shift to location 40
	CALL 	LCD		; output command
	 
	movlw	A'R'		; ascii "R"
	LCALL	LCDCHAR	; output rms to display 

	movlw	A'M'		; ascii "M"
	LCALL	LCDCHAR

	movlw	A'S'		; ascii "S"
	LCALL	LCDCHAR

	movlw	A' '		; ascii " "
	LCALL	LCDCHAR

	GOTO 	RMSDIGIT
	
RMSSPACE:

	GOTO 	RMSDIGIT

KWHDIGIT:
		 
;--------------outputs aenergy to LCD--------------------------------------------------
	
 	bcf	point,1	; clr decimal pointers 
	bcf	point,2
	bcf	point,3
	 
	movf	bcd4,w	; mov aenergy to w
	CALL	BCD2ASCII	; output aenergy to serial or lcd 2 character per call
 
	movf	bcd3,w	; mov aenergy to w
	CALL	BCD2ASCII	; output aenergy to serial or lcd 2 character per call	
 

; need to move 38 characters for 16 character display

;	movlw	B'00001010'	; upper 4 bits of next command
;	CALL 	LCD		; output command	
;	movlw	B'00001000'	; lower 4 bits of last command  display shift to location 40
;	CALL 	LCD		; output command
		    
	movf	bcd2,w		; mov aenergy to w
	CALL	BCD2ASCII	; output aenergy to serial or lcd 2 character per call	
 

;--------------------displays tenths of kwh .x

	
	bcf	STATUS,5
	bsf	point,1		; set bit 2 to display 0.0000   1 for 0.000 or  0 for 0.00
	movf	bcd1,w		; mov aenergy to w
	CALL	BCD2ASCII	; output aenergy to serial or lcd 2 character per call
	bcf	point,1


;-----------------remove rem to show watts .xxx

	btfss	point,7	; if this bit is clear don't display last 2 digits from eeprom 
	GOTO 	NOWATT
	movf	bcd0,w	; mov aenergy to w
	CALL	BCD2ASCII	; output aenergy to serial or lcd 2 character per call


NOWATT:  

	RETURN

;--------------------displays tenths of kwh .x
RMSDIGIT:
	bcf	STATUS,5	; Page 0
	bcf	point,0	; set bit 2 to display 0.0000   1 for 0.000 or  0 for 0.00	
	bcf	point,1

	btfss	point,5	; this bit is used to select .0 or .00 for rms output allow the same 
				;routine to be used for Irms and Vrms 
	bsf	point,0	; set bit 2 to display 0.0000   1 for 0.000 or  0 for 0.00
	
	movf	bcd1,w	; mov aenergy to w
	CALL	BCD2ASCII	; output aenergy to serial or lcd 2 character per call
	bcf	point,0	; clear decimal pointers 
	bcf	point,1

	btfsc	point,5	; test for I rms or vrms see above 	
	bsf	point,1	; set bit 2 to display 0.0000   1 for 0.000 or  0 for 0.00
	btfss	point,7	
	GOTO 	NOWATT
	movf	bcd0,w	; mov aenergy to w
	CALL	BCD2ASCII	; output aenergy to serial or lcd 2 character per call
	btfsc	point,6
	GOTO 	RMSDIGGAP  

	RETURN


RMSDIGGAP:
	movlw	A' '		; ascii " " to put space between Irms and vrms 
	CALL	LCDCHAR
	movlw	A' '		; ascii " "
	CALL	LCDCHAR

	RETURN
	
;-------------end output to lcd--------------------------------------------

 
  				 
;****------------------end of read power routine-----------------------------------------
 
;*****************************************************************************************

 
BCD2ASCII:
;--------------------------------bcd0-4 to ascii convert----------------------------------
        
;	btfsc 	point,3	
				; mov aenergy value into w before calling routine 
	movwf	msdbcd     	; msdbcd 
	movwf	lsdbcd    	; lsdbcd      
	movlw	B'11110000'	; for masking lower bits
	andwf msdbcd,1	; msdbcd = xxxx0000        
	swapf	msdbcd,1	; msdbcd = 0000xxxx	
	movlw	B'00110000'	; add 48 to change bcd to ascii character of bcd value 
	addwf	msdbcd,0	; "0011xxxx"           

	btfsc	point,2
	GOTO	NODIGIT
	CALL	LCDCHAR	; output upper 4 bits to lcd	
	
NODIGIT:
	btfsc	point,1	; test for point
	CALL	POINT		; 
	movlw	B'00001111'	; for masking upper bits
	andwf lsdbcd ,1	; lcdlower= 0000xxxx	
 	movlw	B'00110000'	; add 48 to change bcd to ascii character of bcd value
	addwf	lsdbcd ,0	; "          "                "er
	CALL	LCDCHAR	;  output lower 4 bits to lcd

	btfsc	point,0	; test for point
	CALL	POINT	 
	RETURN

POINT:

	movlw	A'.'		; ascii "."
	CALL	LCDCHAR

	RETURN
;--------------------------------end bcd to ascii to lcd character output-------------------

 
START1:
;	CALL 	GETDATA;------------------------------------------------LOOP-------------------------------------------------------

;	CALL	ENGREAD1		; Initial read before loop 

	GOTO	START1		; loop until interrupt 


;------------------- interrupt routine--------------------------------

INTERRUPT:

	CALL 	GETDATA		; dump waveform data
	
	RETFIE			; return from interrupt



;-----------------LCD write routine--------------------------
;
;	Data can be entered by movlw then CALL LCD
;------------------------------------------------------------




;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% rms routine %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


MODEMASK:
	
	movf	mode0,w
	movwf outd1
	movlw B'01011000'	; set mode register for waveform sampling
	iorwf	mode1,w
	movwf outd2
	movlw	B'10000110'	; command to write to mode register 
	movwf spi		; call spi control write to mode reg
	movlw	D'16'		; number of bits
	movwf	wordlen
	bsf	mcsb		; chip select high 
	LCALL SPI7756	; sets spi port to talk to 7756 data latch on the falling edge.
	LCALL	SPIDX		; mov lsb of word to output to outd2

	
	movlw	B'00001000'	; set disable sag
	movwf outd1
	movlw	B'10010000'	; command to write to mask register 
	movwf spi		; call spi control write to mask reg
	movlw	D'8'		; number of bits
	movwf	wordlen
	bsf	mcsb		; chip select high 
	CALL 	SPI7756	; sets spi port to talk to 7756 data latch on the falling edge.
	CALL	SPIDX		; 

	RETURN

;------------------- Read Waveform register--------------------------------

GETDATA:
	incf	contint,1	; get every other sample 
	bcf	INTCON,1	; clear int
	btfsc	contint,0	; if second interrupt then skip next 
	RETURN		; return to interrupt routine
	

	clrf 	contint	; clear int count for next interrupt 

	movlw	B'00000001'	; mov 01 into w register get wav sample 
	movwf	spi		; output to spi read active energy and reset 
	movlw	b'00000100'	; number of bytes to download B'000(5)(4)(3)(2)(1)' 
	movwf	wordlen	; wordlen is 24 bits. reg is actually 24 bits
	CALL	SPIRX		; CALL SPI read 24 bit word data will be in 
 				; insd1,2,3.  3 being msb 1 being lsb
 	
	movf 	insd3,w	; mov in serial data (insd1-3) to sample low to high
	movwf	sample_high

	movf 	insd2,w
	movwf	sample_middle

	movf 	insd1,w
	movwf	sample_low

	LCALL START		; preform abs value then sqr samples
	CALL 	SAMPMINY	; pass sqr samples through iir filter 4096 times befor sqr root

	bcf 	STATUS,0	; clear carry 
	movlw	D'1'		; 
	addwf	dave1,1	; +1 until overflow then skip 
	btfsc	STATUS,0
	incf	dave2,1
	btfss	dave2,4 	; filter 4096 samples then skip next 
	RETURN		

	CALL	SQROOT	; sqroot after filtering all samples 
	
	LCALL	CORRECTION	;Take y1,y2,y3 results of squareroot multiply by 16 bit coeff the shift right by 16 
	LCALL	DISPLAYRMS	;display rms to lcd v or I depending on the condition of rmsch
	LCALL BIN2BCD	;convert sqroot to bcd for conversion to ascII 
	LCALL LCDUPDATE	;then dislay
DEBUG:
	bsf	STATUS,5	; page 1
	incf	rmsch		; inc to change wav sample ch

				; if rmsch=00000000 then display ch1 rms 
				; if rmsch=00000001 then display ch2 rms 
	btfss	rmsch,1	; if rmsch=00000010 then read eng , display energy , clear rms chanel then repeat
	GOTO 	NOENG

	bcf	STATUS,5
	bcf	INTCON,7
	bcf	point,6
	LCALL	ENGREAD1	; get energy from 7756 mult by coef then display
	bsf	point,6
	bsf	STATUS,5
	clrf	rmsch		; clr rmsch for repeat ch1 then ch2 then energy then repeat


NOENG:	
	bcf	STATUS,5
	clrf	y1		; clear all register for rms calculation
	clrf	y2
	clrf	y3
	clrf	y4
	clrf	y5
	clrf	y6

	clrf	x1
	clrf	x2
	clrf	x3
	clrf	x4
	clrf	x5
	clrf	x6

	clrf	dave1
	clrf 	dave2

	LCALL	CHANNEL
	bsf	INTCON,7	; enable interrupts 

	GOTO 	START1	; return to start loop and wait for wav sample interrupt 



; this is to compensate for above 2047 jump in program mem space 

NOCARRY11:
	LGOTO NOCARY11
NOCARRY12:
	LGOTO	NOCARY12
NOCARRY13:
	LGOTO	NOCARY13	
NOCARRY14:
	LGOTO	NOCARY14
NOCARRY15:
	LGOTO	NOCARY15

ADD:				; addend to be added to 
	bcf	STATUS,0	; add number to be added 
	movf	add1,w
	addwf	addend1,1	 
 	CALL	CARRYCHK1	; add routine used through out rms calculation. add each 8 bit word
	btfss	carry,0	; ripple any carry through 
	GOTO	NOCARRY11
	movf	carry,w
	addwf	addend2,1
	CALL 	CARRYCHK1
	btfss	carry,0
	GOTO	NOCARRY11
	movf	carry,w
	addwf	addend3,1
	CALL 	CARRYCHK1
	btfss	carry,0
	GOTO	NOCARRY11
	movf	carry,w
	addwf	addend4,1
	CALL 	CARRYCHK1
	btfss	carry,0
	GOTO	NOCARRY11
	movf	carry,w
	addwf	addend5,1
	CALL 	CARRYCHK1
	btfss	carry,0
	GOTO	NOCARRY11
	movf	carry,w
	addwf	addend6,1
	bcf	STATUS,0	
NOCARY11:
	movf	add2,w
	addwf	addend2,1	 
 	CALL 	CARRYCHK1
	btfss	carry,0
	GOTO	NOCARRY12
	movf	carry,w
	addwf	addend3,1
	CALL 	CARRYCHK1
	btfss	carry,0
	GOTO	NOCARRY12
	movf	carry,w
	addwf	addend4,1
	CALL 	CARRYCHK1
	btfss	carry,0
	GOTO	NOCARRY12
	movf	carry,w
	addwf	addend5,1
	CALL 	CARRYCHK1
	btfss	carry,0
	GOTO	NOCARRY12
	movf	carry,w
	addwf	addend6,1
	bcf	STATUS,0	
NOCARY12:
	movf	add3,w
	addwf	addend3,1	 
 	CALL 	CARRYCHK1
	btfss	carry,0
	GOTO	NOCARRY13
	movf	carry,w
	addwf	addend4,1
	CALL 	CARRYCHK1
	btfss	carry,0
	GOTO	NOCARRY13
	movf	carry,w
	addwf	addend5,1
	CALL 	CARRYCHK1
	btfss	carry,0
	GOTO	NOCARRY13
	movf	carry,w
	addwf	addend6,1
	bcf	STATUS,0	
NOCARY13:
	movf	add4,w
	addwf	addend4,1
	CALL 	CARRYCHK1
	btfss	carry,0
	GOTO	NOCARRY14
	movf	carry,w
	addwf	addend5,1
	CALL 	CARRYCHK1
	btfss	carry,0
	GOTO	NOCARRY14
	movf	carry,w
	addwf	addend6,1
	bcf	STATUS,0		 
NOCARY14:
	movf	add5,w
	addwf	addend5,1
	CALL 	CARRYCHK1
	btfss	carry,0
	GOTO	NOCARRY15
	movf	carry,w
	addwf	addend6,1
	bcf	STATUS,0	 	
NOCARRY15:
	bcf	STATUS,0
	movf	add6,w
	addwf	addend6,1
	
 	RETURN

CARRYCHK1:
	clrf	carry		; clear carry register 
	btfsc	STATUS,0	; test status reg carry bit. skip if clr
	incf	carry,1	; increment carry 
	RETURN

; this multiplication by shift and add if the current multiplier bit is 1 shift only if zero 

MULT1:
	movlw	D'8'		; number of bits to multiply
	movwf	wordlen	; mov 8 into wordlen

MULTLOOP:			;					 
				;  
	btfsc	mem,0		; if bit is 1 add word		
	CALL	ADD		;  
	bcf	STATUS,0	;  
	rrf	mem,1		; rotate constant for next bit to multiply 
	bcf	STATUS,0
	rlf 	add1,1		; rotate for next add 
	rlf 	add2,1		; rotate for next add 
	rlf 	add3,1		; rotate for next add 
	rlf 	add4,1		; rotate for next add 
	rlf 	add5,1		; rotate for next add 
	rlf 	add6,1		; rotate for next add 
	bcf	STATUS,0
	decfsz	wordlen,1	  
 	GOTO	MULTLOOP	; repeat 
 
	
	RETURN 

;------------------- Square routine--------------------------------

SQR:
	;------------------- clear register--------------------------------
	clrf	square1	; multiply 24 bit word by itself (shift and add)
 	clrf	square2
 	clrf	square3
 	clrf	square4
 	clrf	square5
 	clrf	square6
	
	clrf	add1
	clrf	add2
	clrf	add3
	clrf	add4
	clrf	add5
	clrf	add6

	clrf	addend1
	clrf	addend2
	clrf	addend3
	clrf	addend4
	clrf	addend5
	clrf	addend6

	;------------------- Load the register--------------------------------
	movf 	sample_low,w	;load adder with sample data  
	movwf	add1
	movf 	sample_middle,w
	movwf	add2
	movf 	sample_high,w
	movwf	add3

	;------------ Square the register results in square registers-------------------------
	movf 	sample_low,w	; test sample work shift and add as indicated 	
	movwf	mem	
	CALL	MULT1
	movf 	sample_middle,w	
	movwf	mem		
	CALL	MULT1
	movf 	sample_high,w	
	movwf	mem		
	CALL	MULT1

	RETURN
 

; this is the add one routine used after compliment to make positive or negative 
PLUSONE:

	bcf	STATUS,0	; clear carry
	movlw	D'1'
	addwf	sample_low,1
	btfss	STATUS,0
	RETURN
	bcf	STATUS,0	; clear carry
	movlw	D'1'
	addwf	sample_middle,1
	btfss	STATUS,0
	RETURN
	bcf	STATUS,0	; clear carry
	movlw	D'1'	 
	addwf	sample_high,1
	btfss	STATUS,0
	RETURN	

; necessary for lcall's 
ADDJUMP:
	CALL	ADD
	RETURN	


;------------------- IIR filter--------------------------------
; y(n)=(x(n)^2 x 2^9 - y(n)) x 2^(-9) + y(n-1)

SAMPMINY:

;	x1	output of filter before sqr root 
;	x2
;	x3
;	x4
;	x5
;	x6

	;------------------- process (-y(n)) ------------------------
	comf	x1,1		; change to negative then add 
	comf	x2,1
	comf	x3,1
	comf	x4,1
	comf	x5,1
	comf	x6,1
	
				; add one 
	bcf	STATUS,0	; clear carry
	movlw	D'1'
	addwf	x1,1
	btfss	STATUS,0
	GOTO	SKIP
	bcf	STATUS,0	; clear carry
	movlw	D'1'
	addwf	x2,1
	btfss	STATUS,0
	GOTO	SKIP
	bcf	STATUS,0	; clear carry
	movlw	D'1'	 
	addwf	x3,1
	btfss	STATUS,0
	GOTO	SKIP 
	bcf	STATUS,0	; clear carry
	movlw	D'1'
	addwf	x4,1
	btfss	STATUS,0
	GOTO	SKIP
	bcf	STATUS,0	; clear carry
	movlw	D'1'
	addwf	x5,1
	btfss	STATUS,0
	GOTO	SKIP
	bcf	STATUS,0	; clear carry
	movlw	D'1'	 
	addwf	x6,1
	bcf	STATUS,0
	
	;--------mov -x values  adder then multiply samples by 2^9 load 2nd adder variable then add(subtract) ------
SKIP:
	movf	x1,w		
	movwf	add1
	movf	x2,w
	movwf	add2
	movf	x3,w
	movwf	add3
	movf	x4,w
	movwf	add4
	movf	x5,w
	movwf	add5
	movf	x6,w
	movwf	add6
	
	movlw	D'9'
	movwf	div

	;--------Multiply x(n)^2 by 2^9 ------
DIVBYN1:
	bcf	STATUS,0	
	rlf	square1,1
	rlf	square2,1
	rlf	square3,1
	rlf	square4,1
	rlf	square5,1
	rlf	square6,1
	bcf	STATUS,0
	decfsz	div,1
	GOTO	DIVBYN1	


	movf	square1,w	; load 2nd variable into adder 
	movwf	addend1	
	movf	square2,w
	movwf	addend2	
	movf	square3,w
	movwf	addend3	
	movf	square4,w
	movwf	addend4	
	movf	square5,w
	movwf	addend5	
	movf	square6,w
	movwf	addend6	

	;--------ADD 2^9 x square with (-x) results in Addend registers------
	CALL	ADD
	
	movlw	D'9'	; this is the IIR filter coefficent 
	movwf	div
	
;--------Multiply (2^9 x square - y) by 2^-9 ------

DIVBYN:
	bcf	STATUS,0				; rotate right and keep sign extension 
	btfsc	addend6,7
	bsf 	STATUS,0
	rrf	addend6,1
	rrf	addend5,1
	rrf	addend4,1
	rrf	addend3,1
	rrf	addend2,1
	rrf	addend1,1
	BCF	STATUS,0
	decfsz	div,1
	GOTO	DIVBYN	

;test for neg 1					; if result = -1 then make result = to 0  

	bcf	STATUS,Z 				; with smaller neg numbers it is posible to rotate in ffffffffffff 
	incfsz  addend1,w				; causing -1 this is why this is done, each increment is done in the 
	GOTO	NOTM1					; w reg leaving data intact for adding later 
	bcf	STATUS,Z 
	incfsz  addend2,w
	GOTO	NOTM1
	bcf	STATUS,Z 
	incfsz  addend3,w
	GOTO	NOTM1
	bcf	STATUS,Z 
	incfsz  addend4,w
	GOTO	NOTM1
	bcf	STATUS,Z 
	incfsz  addend5,w
	GOTO	NOTM1
	bcf	STATUS,Z 
	incfsz  addend6,w
	GOTO	NOTM1
	bcf	STATUS,Z 

	clrf	addend1		; make 0 if -1 
	clrf	addend2
	clrf	addend3	
	clrf	addend4
	clrf	addend5
	clrf	addend6
	
;-------Add y(n-1) to the previous calculation -------------------------
;------the result is the output of the IIR filter (Addend registers)-----------	
NOTM1:	

	comf	x1,1		; change -x back to positive x for add output of times coef routine 
	comf	x2,1
	comf	x3,1
	comf	x4,1
	comf	x5,1
	comf	x6,1
	
				; add one 
	bcf	STATUS,0	; clear carry	; skip if no carry to save time.
	movlw	D'1'
	addwf	x1,1
	btfss	STATUS,0
	GOTO	SKIP1
	bcf	STATUS,0	; clear carry
	movlw	D'1'
	addwf	x2,1
	btfss	STATUS,0
	GOTO	SKIP1
	bcf	STATUS,0	; clear carry
	movlw	D'1'	 
	addwf	x3,1
	btfss	STATUS,0
	GOTO	SKIP1 
	bcf	STATUS,0	; clear carry
	movlw	D'1'
	addwf	x4,1
	btfss	STATUS,0
	GOTO	SKIP1
	bcf	STATUS,0	; clear carry
	movlw	D'1'
	addwf	x5,1
	btfss	STATUS,0
	GOTO	SKIP1
	bcf	STATUS,0	; clear carry
	movlw	D'1'	 
	addwf	x6,1
	bcf	STATUS,0
SKIP1:			; mov x to adder
	movf	x1,w
	movwf	add1
	movf	x2,w
	movwf	add2
	movf	x3,w
	movwf	add3
	movf	x4,w
	movwf	add4
	movf	x5,w
	movwf	add5
	movf	x6,w
	movwf	add6

	CALL	ADD		; add (((samp^2 * 2^9)-x) * 2^-9) to x(z-1)

	movf	addend1,w	; mov results of adder to new value of x (output of iir filter)
	movwf	x1
	movf	addend2,w
	movwf	x2
	movf	addend3,w
	movwf	x3
	movf	addend4,w
	movwf	x4
	movf	addend5,w
	movwf	x5
	movf	addend6,w
	movwf	x6
	RETURN		; return to repeat 4096 times 

; more lcall correction 
NRESULT:
	LGOTO 	NRESULT1

SQFILT1:
	LGOTO 	SQFILT



;--------Successive Approximation square root routine------
	
SQROOT:


; x1-6 is the output of the iir filter or the square root of the input
; divide output of iir filter by 2^9 to negate the multiply sample by 2^9 this was done so
; no lsb's would be lost in the filter 

	movlw	D'9'
	movwf	div
	
DIVBYN5:			; div by 2^9

	bcf 	STATUS,0
	rrf	x6,1
	rrf	x5,1
	rrf	x4,1
	rrf	x3,1
	rrf	x2,1
	rrf	x1,1
	BCF	STATUS,0
	decfsz div,1
	GOTO	DIVBYN5	



;run till sar^2 = x
;
;  x=4 time=16.6ms 14849 cycles clock=4 mhz
;  x=fefe0001 time=26.97ms 24126 cycles clock=4 mhz
;
;  x=4 time=2.97ms 14848 cycles clock=20 mhz
;  x=fefe0001 time=4.83ms 24126 cycles clock=20 mhz
;
;x=6bytes	incomming 
;y=3bytes 	outging 
;sar=3bytes	

	clrf	y1	; clr output of the sqrt routine.
	clrf	y2
	clrf	y3

	clrf	sar1	;initialize sar reg
	clrf	sar2
	clrf	sar3	
	bsf	sar3,7
	bsf	y3,7	; set msb of y reg 
			; if sar reg^2 - x1-x6>0 keep bit yn shift sar ior sar with yn results in sar then repeat
			; IF  sar reg^2 - x1-x6<=0 clr bit do not ior with yn shift sar and repeat

;--------process the square of the square root approximation register------
SQFILT:


	movf	y1,w		; prepare to sqr y1 
	movwf	add1
	movf	y2,w
	movwf	add2
	movf	y3,w
	movwf	add3

	clrf	add4		; clr upper 3 bytes for shift and add
	clrf	add5
	clrf	add6

	clrf	addend1	; clr output of adder 
	clrf	addend2
	clrf	addend3
	clrf	addend4
	clrf	addend5
	clrf	addend6

	movf	y1,w		; multiply y by y
	movwf	mem
	CALL	MULT1
	movf	y2,w
	movwf	mem
	CALL	MULT1
	movf	y3,w
	movwf	mem
	CALL	MULT1


	movf	addend1,w	; mov y^2 to add1-6 
	movwf	add1
	movf	addend2,w
	movwf	add2
	movf	addend3,w
	movwf	add3
	movf	addend4,w
	movwf	add4
	movf	addend5,w
	movwf	add5
	movf	addend6,w
	movwf	add6

	comf	add1,1	; make y(guess) negative to subtract from x1-6(output of filter)
	comf	add2,1
	comf	add3,1
	comf	add4,1
	comf	add5,1
	comf	add6,1

;--------process (-)add------
	LCALL	Y1	; add1 to -y ( compliment and add1 )


	movf	x1,w		; mov x to addend to -y (add1-6)
	movwf	addend1
	movf	x2,w
	movwf	addend2
	movf	x3,w
	movwf	addend3
	movf	x4,w
	movwf	addend4
	movf	x5,w
	movwf	addend5
	movf	x6,w
	movwf	addend6

;--------Add input + (-square (square root approximation))------

	LCALL	ADDJUMP		; long call to add routine 
	nop
	nop
 	nop
	nop 	; keep these long call problem do not remove 
	nop
	nop
 	nop
	nop 

;--------if difference is > or = 0 add 2^i to the approximation register---------
;--------otherwise substract 2^(i+1) to the approximation register------

	btfss	STATUS,0	; test results of add routine for negative 
	GOTO 	NRESULT	
	movf	sar1,w	; if positive ior sar with y 
	iorwf	y1,1
	movf	sar2,w
	iorwf	y2,1
	movf	sar3,w
	iorwf	y3,1

	bcf	STATUS,0	; rotate sar fro next guess 
	rrf	sar3,1
	rrf	sar2,1
	rrf	sar1,1

	movf 	sar1,w	; or new guess with old guess 
	iorwf	y1,1
	movf 	sar2,w
	iorwf	y2,1
	movf 	sar3,w
	iorwf	y3,1

	btfss	STATUS,0	; sar register rotated right to carry job done.
	GOTO 	SQFILT1	; complete
	RETURN		; not complete process new guess

NRESULT1:
	comf	sar1,w	; remove previous guess from new guess results were to big.
	andwf	y1,1
	comf	sar2,w
	andwf	y2,1
	comf	sar3,w
	andwf	y3,1

	bcf	STATUS,0	; shit sar and ior with old guess to make new guess 
	rrf	sar3,1
	rrf	sar2,1
	rrf	sar1,1

	movf 	sar1,w
	iorwf	y1,1
	movf 	sar2,w
	iorwf	y2,1
	movf 	sar3,w
	iorwf	y3,1

	btfss	STATUS,0	; sar reg shifted into carry job done 
	GOTO	SQFILT2	; complete 

	RETURN		; not complete process new guess 

SQFILT2:				; more long call stuff 
	LGOTO 	SQFILT
SKIP2:
	LGOTO 	SKIPNC


Y1:

				; add one 
	bcf	STATUS,0	; clear carry
	movlw	D'1'
	addwf	add1,1
	btfss	STATUS,0
	GOTO 	SKIP2
	bcf	STATUS,0	; clear carry
	movlw	D'1'
	addwf	add2,1
	btfss	STATUS,0
	GOTO	SKIP2
	bcf	STATUS,0	; clear carry
	movlw	D'1'	 
	addwf	add3,1
	btfss	STATUS,0
	GOTO	SKIP2
	bcf	STATUS,0
	movlw	D'1'
	addwf	add4,1
	btfss	STATUS,0
	GOTO 	SKIP2
	bcf	STATUS,0	; clear carry
	movlw	D'1'
	addwf	add5,1
	btfss	STATUS,0
	GOTO	SKIP2
	bcf	STATUS,0	; clear carry
	movlw	D'1'	 
	addwf	add6,1
	bcf	STATUS,0	; clear carry

SKIPNC:

	RETURN


;---After calculation of the square root put the result 
;----in bins for display	
DISPLAYRMS:
	
	movf 	addend1,w
	movwf	bin0		; mov energy 2-6 to bin 0-5 for bcd conversion 
	movf 	addend2,w
	movwf	bin1
	movf 	addend3,w
	movwf	bin2
	movf 	addend4,w
	movwf	bin3
	movf	addend5,w
	movwf	bin4

		
	RETURN


ADDVOFF:	
	GOTO 	ADDVOFF1	: long call stuff 

COEFDIV:				; last part of coeficient 
	movlw	D'16'
	movwf	div
	
DIVBY16:				; div by 2^16
	bcf	STATUS,0	
	rrf	addend6,1
	rrf	addend5,1
	rrf	addend4,1
	rrf	addend3,1
	rrf	addend2,1
	rrf	addend1,1
	BCF	STATUS,0
	decfsz	div,1
	GOTO	DIVBY16

	RETURN

;---Configure the Mode register for Current or Voltage RMS
;----calculation
;set mode register depending rmsch 0 or 1 this is incremented in getdata routine 
CHANNEL:

	bsf     STATUS,5        ; set to bank 1
	btfsc	rmsch,0
	GOTO 	CH2

	bcf     STATUS,5        ; set to bank 1
	bcf	point,5		; point5 aux channel indicator
	movlw	B'00001000'		; sets mode reg for ch1 wav samp at 3.5kps
	movwf  	outd1
	movwf	mode0
	movlw	B'01011000'
	movwf  	outd2
	movwf	mode1
CH2:
	bsf   STATUS,5        	; set to bank 1
	btfss	rmsch,0
	GOTO 	SETCH

	bcf   STATUS,5        	; set to bank 1
	bsf	point,5		; point5 aux channel indicator
	movlw	B'00001000'		; sets mode reg for ch2 wav samp at 3.5kps
	movwf	outd1
	movwf	mode0
	movlw	B'01111000'
	movwf	outd2
	movwf	mode1
SETCH:
	bcf	STATUS,5
	movlw	B'10000110'	; command to write to mode register 
	movwf	spi		; call spi control write to mode reg
	movlw	D'16'		; number of bits
	movwf	wordlen
	bsf	mcsb		; chip select high 
	LCALL	SPI7756	; sets spi port to talk to 7756 data latch on the falling edge.
	LCALL	SPIDX		; mov lsb of word to output to outd2

	RETURN


START:

	
	btfss sample_high,7	; test sign bit if neg compliment and add 1 to get absolute value
	GOTO 	POSITIVE	; in not negative skip to truncate to 16 bit 

	comf	sample_high,1	; compliment 
	comf	sample_middle,1
	comf	sample_low,1

				; add one 
	bcf	STATUS,0	; clear carry
	movlw	D'1'
	addwf	sample_low,1
	btfss	STATUS,0
	GOTO 	POSITIVE
	bcf	STATUS,0	; clear carry
	movlw	D'1'
	addwf	sample_middle,1
	btfss	STATUS,0
	GOTO 	POSITIVE
	bcf	STATUS,0	; clear carry
	movlw	D'1'	 
	addwf	sample_high,1
	btfss	STATUS,0

POSITIVE:

	bcf	STATUS,0	; truncate to 16 bit
	rrf	sample_high,1
	rrf	sample_middle,1
	rrf	sample_low,1
	bcf	STATUS,0	
	rrf	sample_high,1
	rrf	sample_middle,1
	rrf	sample_low,1
	bcf	STATUS,0
	rrf	sample_high,1
	rrf	sample_middle,1
	rrf	sample_low,1
	bcf	STATUS,0	

	LCALL	SQR		; square sample 

	movf	addend1,w	; mov results of sqr routine into square1-6
	movwf	square1
	movf	addend2,w
	movwf	square2
	movf	addend3,w
	movwf	square3
	movf	addend4,w
	movwf	square4
	movf	addend5,w
	movwf	square5
	movf	addend6,w
	movwf	square6

	RETURN	

COFFCOMP1:			; more long call stuff 
	LGOTO	COFFCOMP


;------------------------------- end of lcd out routine------------------------------	

CORRECTION:

;	Gain correction
;	Take y1,y2,y3 results of squareroot multiply by 16 bit coeff the shift right by 16 
	
	clrf	add1		; clr adder 
	clrf	add2
	clrf	add3
	clrf	add4
	clrf	add5
	clrf	add6

	clrf	addend1	;clr adder 
	clrf	addend2
	clrf	addend3
	clrf	addend4
	clrf	addend5
	clrf	addend6

	movf 	y1,w		; results of sqrt into adder for coef adjustment
	movwf	add1
	movf 	y2,w
	movwf	add2
	movf 	y3,w
	movwf	add3
	
	bsf     STATUS,5        ; set to bank 1
	btfsc	rmsch,0		; depending on rmsch use I or v coef and i or v offset 
	GOTO 	CH2COFF	
	
	movf 	icof1,w		; muli by i coef 
	bcf     STATUS,5        ; set to bank 0
	movwf	mem	
	LCALL	MULT1
	bsf     STATUS,5        ; set to bank 1
	movf 	icof2,w	
	bcf     STATUS,5        ; set to bank 0
	movwf	mem		
	LCALL	MULT1
	LCALL 	COEFDIV

	;------Offset correction-------add i offset 
	bsf     STATUS,5        ; set to bank 1
	movf	ioffset1,w
	bcf     STATUS,5        ; set to bank 0
	movwf	add1
	bsf     STATUS,5        ; set to bank 1
	movf	ioffset2,w
	bcf     STATUS,5        ; set to bank 0
	movwf	add2
	clrf 	add3			; clr add3-6
	clrf 	add4
	clrf 	add5
	clrf 	add6
	btfss	add2,7		; SKIP IF NEGATIVE 
	GOTO 	ADDIOFF
	comf	add3,1		; SIGN EXTEND NEGATIVE 
	comf	add4,1		
	comf	add5,1
	comf	add6,1

ADDIOFF:
	LCALL	ADD			; add ioffset



	
CH2COFF:

	bsf     STATUS,5        ; set to bank 1
	btfsc	rmsch,0
	GOTO 	WHY
	LGOTO 	COFFCOMP
WHY:
	movf 	vcof1,w		; multiply by vcoef
	bcf     STATUS,5        ; set to bank 0
	movwf	mem	
	LCALL	MULT1
	bsf     STATUS,5        ; set to bank 1
	movf 	vcof2,w	
	bcf     STATUS,5        ; set to bank 0
	movwf	mem		
	LCALL	MULT1
	LCALL 	COEFDIV

					; add v offset 
	bsf     STATUS,5        ; set to bank 1	
	movf	voffset1,w
	bcf     STATUS,5        ; set to bank 0
	movwf	add1
	bsf     STATUS,5        ; set to bank 1
	movf	voffset2,w
	bcf     STATUS,5        ; set to bank 0
	movwf	add2
	clrf 	add3
	clrf 	add4
	clrf 	add5
	clrf 	add6
	btfss	add2,7		; SKIP IF NEGATIVE 
	GOTO 	ADDVOFF
	comf	add3,1		; SIGN EXTEND NEGATIVE 
	comf	add4,1
	comf	add5,1
	comf	add6,1

ADDVOFF1:				; more long call stuff 
	LCALL	ADD

COFFCOMP:
	bcf     STATUS,5        ; set to bank 0
	RETURN





 

	END