;************************************************************ ; 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