;****************************************************************************** ; ; Telescope Battery Monitor System ; ; The PIC 16F88 pin layout: ; ; ; RA0 LCD Data ; RA1 LCD Data ; RA2 LCD Data ; RA3 LCD Data ; RA4 AD for Battery Voltage ; RA5 ; RA6 LCD RS ; RA7 LCD EN ; ; RB0 Switch input for Display Dimming - low when pressed ; RB1 ; RB2 ; RB3 PWM for Display Backlight ; RB4 ; RB5 ; RB6 AD for Plug 1 current ; RB7 AD for Plug 2 current ; ;****************************************************************************** ; ; Filename: telescope.asm ; Date: 1 July 2004 ; File Version: 1.0 ; ; Author: A.Round ; Company: Round Innovations ; ; ;****************************************************************************** ; ; Files required: "m_lcd.h" ; ;****************************************************************************** ; ; Notes: Version 1.0 - Initial Baseline ; ; ; ;***************************************************************************** list p=16f88 ; list directive to define processor #include ; processor specific variable definitions __CONFIG _CONFIG1, _CP_OFF & _CCP1_RB3 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_IO __CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF ; '__CONFIG' directive is used to embed configuration word within .asm file. ; The lables following the directive are located in the respective .inc file. ; See data sheet for additional information on configuration word settings. ;***** LCD HARDWARE DECLARATION ***** LCD_CONTROL EQU PORTA LCD_CONTROL_TRIS EQU TRISA #define R_S LCD_CONTROL,6 ; LCD Register Select control line RA6 #define EN LCD_CONTROL,7 ; LCD Enable control line RA7 LCD_DATA EQU PORTA ; LCD data byte using PortA LCD_DATA_TRIS EQU TRISA ;***** VARIABLE DECLARATION ***** CBLOCK 0X20 TEST ; Used in Keyboard debounce routine TEMP1 ; Used in LCD subroutines TEMP2 ; Used in LCD_Hex subroutine CNTR ; Used in LCD Screen subroutines DELAY1 ; Used in Delay macros DELAY2 ; Used in Delay macros HALF_SEC_COUNT ; Used for Timer1 ISR routines PLUG1H ; High byte of Plug 1 current A/D PLUG1L ; Low byte of Plug 1 current A/D CALCPLUG1H ; High byte of Plug 1 current in 10's mA CALCPLUG1L ; Low byte of Plug 1 current in 10's mA PLUG2H ; High byte of Plug 2 current A/D PLUG2L ; Low byte of Plug 2 current A/D CALCPLUG2H ; High byte of Plug 2 current in 10's mA CALCPLUG2L ; Low byte of Plug 2 current in 10's mA VOLTH ; High byte of Battery voltage A/D VOLTL ; Low byte of Battery voltage A/D AHH ; High byte of Amp seconds count AHL ; Low byte of Amp seconds count CALCH ; Working MS byte CALCL ; Working LS byte P11 ; ASCII Plug 1 amps 1's P101 ; ASCII Plug 1 amps 0.1's P1001 ; ASCII Plug 1 amps 0.01's P21 ; ASCII Plug 2 amps 1's P201 ; ASCII Plug 2 amps 0.1's P2001 ; ASCII Plug 2 amps 0.01's V10 ; ASCII Battery Voltage 10's V1 ; ASCII Battery Voltage 1's V01 ; ASCII Battery Voltage 0.1's AH10 ; ASCII Amp Hours 10's AH1 ; ASCII Amp Hours 1's AH01 ; ASCII Amp Hours 0.1's AH001 ; ASCII Amp Hours 0.01's SUBH ; Used in 16BIT subtraction routine SUBL ; Used in 16BIT subtraction routine DIGIT ; Used in binary to ASCII conversion DIM ; Used in display dimming routine ENDC CBLOCK 0X70 W_TEMP STATUS_TEMP PCLATH_TEMP ENDC ;********************************************************************** ORG 0x000 ; processor reset vector GOTO MAIN ; go to beginning of program ORG 0x004 ; interrupt vector location GIE_CLEAR BANKSEL INTCON BCF INTCON, GIE ; turn off interupts BTFSC INTCON, GIE ; make sure they are really turned off GOTO GIE_CLEAR MOVWF W_TEMP ; save off current W register contents MOVF STATUS, W ; move status register into W register MOVWF STATUS_TEMP ; save off contents of STATUS register MOVF PCLATH,W ; move PCLATH register into W register MOVWF PCLATH_TEMP ; save off contents of PCLATH register BTFSC PIR1, TMR1IF ; test to see if Timer1 overflow GOTO HALF_SEC ; if yes, go to time counting routine GOTO TEST_SWITCH ; if no, go to TEST_SWITCH HALF_SEC BCF PIR1, TMR1IF ; clear Timer1 interrupt flag INCF HALF_SEC_COUNT,F ; increment half seconds count BTFSC HALF_SEC_COUNT,0 GOTO HEARTBEAT GOTO HEARTBEAT1 HEARTBEAT MOVLW 0X87 CALL LCD_Cmd MOVLW ' ' CALL LCD_Nbl MOVLW 0x7E CALL LCD_Nbl GOTO HEARTBEAT2 HEARTBEAT1 MOVLW 0X87 CALL LCD_Cmd MOVLW 0x7F CALL LCD_Nbl MOVLW ' ' CALL LCD_Nbl HEARTBEAT2 MOVFW HALF_SEC_COUNT ; check to see if 60 seconds has elapsed SUBLW b'01111000' SKPNZ GOTO HALF_SEC1 ; if yes, update amp hour calculation GOTO ISR_OVER ; if no, go to ISR_OVER and wait for next interrupt HALF_SEC1 MOVF CALCPLUG1L,W ADDWF AHL,F MOVF CALCPLUG1H,W BTFSC STATUS,C ADDLW D'1' ADDWF AHH,F MOVF CALCPLUG2L,W ADDWF AHL,F MOVF CALCPLUG2H,W BTFSC STATUS,C ADDLW D'1' ADDWF AHH,F MOVF AHH, W MOVWF CALCH MOVF AHL, W MOVWF CALCL CALL AMP_ASCII CLRF HALF_SEC_COUNT ; clear half seconds count GOTO ISR_OVER ; go to ISR_OVER and wait for next interrupt TEST_SWITCH BTFSC INTCON, INTF ; test to see if switch 1 is pushed GOTO TEST_SWITCH1 ; if yes, change dimming GOTO ISR_OVER ; if no, go to ISR_OVER and wait for next interupt TEST_SWITCH1 BANKSEL STATUS BCF STATUS, C ; if no, clear Carry bit of STATUS RLF DIM, F ; rotate DIM right one bit BTFSS DIM, 4 ; test to see if we need to go back to bit 0 GOTO DIM_SEL ; no, go to DIM_SEL BCF DIM, 4 ; yes, clear DIM bit 4 BSF DIM, 0 ; set MODE bit 0 DIM_SEL BTFSS DIM, 0 ; 100%? GOTO DIM_SEL1 ; no, check again GOTO DIM_100 ; yes, set PWM to 100% DIM_SEL1 BTFSS DIM, 1 ; 5%? GOTO DIM_SEL2 ; no, check again GOTO DIM_05 ; yes, set PWM to 5% DIM_SEL2 BTFSS DIM, 2 ; 01%? GOTO DIM_00 ; no, only 00% left GOTO DIM_01 ; yes, set PWM to 01% DIM_00 MOVLW b'00000000' ; PWM duty cycle of 00% MOVWF CCPR1L GOTO DIM_OVER DIM_01 MOVLW b'00000001' ; PWM duty cycle of 01% MOVWF CCPR1L GOTO DIM_OVER DIM_05 MOVLW b'00000011' ; PWM duty cycle of 05% MOVWF CCPR1L GOTO DIM_OVER DIM_100 MOVLW b'00111111' ; PWM duty cycle of 100% MOVWF CCPR1L DIM_OVER BANKSEL PORTB MOVF PORTB, W ; read PORTB MOVWF TEST ; store PORTB in TEST BTFSS TEST, 0 ; has display key been released? GOTO DIM_OVER ; if no, go to DIM_OVER CALL DELAY_KB ; if yes, 10 ms Keyboard debounce MOVF PORTB, W ; read PORTB MOVWF TEST ; store PORTB in TEST BTFSS TEST, 0 ; has display key been released? GOTO DIM_OVER ; if no, go to DIM_OVER BCF INTCON, INTF ; if yes, clear RB0 interupt flag ISR_OVER CALL DISPLAY_UPDATE ; Update display BANKSEL PCLATH_TEMP MOVF PCLATH_TEMP,W ; retrieve copy of PCLATH register MOVWF PCLATH ; restore pre-isr PCLATH register contents MOVF STATUS_TEMP,W ; retrieve copy of STATUS register MOVWF STATUS ; restore pre-isr STATUS register contents SWAPF W_TEMP,F SWAPF W_TEMP,W ; restore pre-isr W register contents RETFIE ; return from interrupt ;***** INCLUDE FILES ***** #include "m_lcd.h" ;*************************************** TABLES ************************************* ;***** SCREEN TABLES ***** SCREEN1 MOVWF PCL DT "V= . V . AH",0x00 SCREEN2 MOVWF PCL DT "I1= . A I2= . A",0x00 ;*************************************** DELAY MACROS ************************************* ;***** SHORT DELAY MACRO ***** D10USEC MACRO TCNST ; provides a delay equal to TCNST * 10 usecs MOVLW TCNST MOVWF DELAY1 CALL D10USEC1 ENDM D10USEC1 NOP NOP NOP NOP NOP NOP NOP DECFSZ DELAY1, F GOTO D10USEC1 RETURN ;***** LONG DELAY MACRO ***** DLONG MACRO TCNST ; provided a delay of TCNST * msec MOVLW TCNST MOVWF DELAY1 CALL OUTER ENDM OUTER MOVLW D'110' ; close to 1.0 msec delay when set to 110 MOVWF DELAY2 INNER NOP NOP NOP NOP NOP NOP DECFSZ DELAY2, F GOTO INNER DECFSZ DELAY1, F GOTO OUTER RETURN ;*************************************** DELAY SUBROUTINES ************************************* DELAY_KB DLONG D'10' RETURN ;*************************************** LCD MODULE SUBROUTINES ************************************* ; For HD44780 controller chips ; Note that lower bits of Port are being used ;***** LCD MODULE INITALIZATION SUBROUTINE ***** LCD_Init BANKSEL LCD_DATA CLRF LCD_DATA BCF R_S ;write to the HD44780's IR. MOVLW b'00000011' ;Command for 8-bit interface MOVWF LCD_DATA BSF EN NOP BCF EN DLONG D'5' ;have to wait 4.1 ms here BSF EN NOP BCF EN D10USEC D'10' ;have to wait 100us here BSF EN NOP BCF EN D10USEC D'10' ;have to wait 100us here BCF R_S MOVLW b'00000010' ;Command for 4-bit interface MOVWF LCD_DATA BSF EN NOP BCF EN MOVLW FUNC_SET ;Function Set CALL LCD_Cmd MOVLW DISP_OFF ;Display Off CALL LCD_Cmd MOVLW CLR_DISP ;Clear the Display CALL LCD_Cmd MOVLW ENTRY_INC ;Entry Cursor Increment CALL LCD_Cmd MOVLW DISP_ON ;Display On, No Cursor CALL LCD_Cmd RETURN ;***** LCD_Nbl SUBROUTINE ***** LCD_Nbl BANKSEL TEMP1 MOVWF TEMP1 ; Character to be sent is in ; W so put in Temp1 DLONG D'2' ; Wait 2ms instead of Busy Check SWAPF TEMP1, W ANDLW 0x0F ; Get upper nibble into lower half port MOVWF LCD_DATA ; Send data to LCD BSF R_S ; Set LCD to data mode CALL LCDtglclk ; Toggle EN MOVF TEMP1, W ANDLW 0x0F ; Get lower nibble into upper half port MOVWF LCD_DATA ; Send data to LCD BSF R_S ; Set LCD to data mode CALL LCDtglclk ; Toggle EN RETURN LCDtglclk BSF EN ; Toggle EN for LCD NOP NOP BCF EN RETURN ;***** LCD_Cmd SUBROUTINE ***** LCD_Cmd BANKSEL TEMP1 MOVWF TEMP1 ; Command to be sent is in ; W so put in Temp1 DLONG D'2' SWAPF TEMP1, W ANDLW 0x0F ; Get upper nibble into lower half port MOVWF LCD_DATA ; Send data to LCD BCF R_S ; Set LCD to command mode CALL LCDtglclk ; Toggle EN MOVF TEMP1, W ANDLW 0x0F ; Get lower nibble into lower half port MOVWF LCD_DATA ; Send data to LCD BCF R_S ; Set LCD to command mode CALL LCDtglclk ; Toggle EN RETURN ;***** LCD_Hex SUBROUTINE ***** LCD_Hex BANKSEL TEMP2 MOVWF TEMP2 ; Character to be sent is in ; W so put in Temp2 SWAPF TEMP2, W ANDLW 0x0F ; Get upper nibble into lower half port CALL LCD_Hex1 ; Convert upper nybble to ASCII CALL LCD_Nbl ; Output ASCII on LCD display MOVF TEMP2, W ANDLW 0x0F ; Get lower nibble into lower half port CALL LCD_Hex1 ; Convert lower nybble to ASCII CALL LCD_Nbl ; Output ASCII on LCD display RETURN LCD_Hex1 ADDLW 0xF6 ; This routine converts a number in w to an BTFSC STATUS, C ; ASCII hex number. Result in W ADDLW 0x07 ADDLW 0x3A RETURN ;***** LCD_Clear SUBROUTINE ***** LCD_Clear MOVLW CLR_DISP CALL LCD_Cmd RETURN ;***************************************LCD MODULE MACROS ************************************* ;***** LCD_Move Macro ***** LCD_Move MACRO Address MOVLW Address ;(Address|0x80) CALL LCD_Cmd ENDM ;***************************************LCD SCREEN SUBROUTINES ************************************* ;***** START SCREEN ***** START_SCREEN CALL LCD_Clear CLRF CNTR START_SCREEN1 MOVLW HIGH SCREEN1 MOVWF PCLATH MOVLW LOW SCREEN1 + 1 ADDWF CNTR,W BTFSC STATUS,C INCF PCLATH,F CALL SCREEN1 ANDLW 0xFF BTFSC STATUS, Z GOTO START_SCREEN2 CALL LCD_Nbl INCF CNTR,F GOTO START_SCREEN1 START_SCREEN2 LCD_Move 0xC0 CLRF CNTR START_SCREEN3 MOVLW HIGH SCREEN2 MOVWF PCLATH MOVLW LOW SCREEN2 + 1 ADDWF CNTR,W BTFSC STATUS,C INCF PCLATH,F CALL SCREEN2 ANDLW 0xFF BTFSC STATUS, Z GOTO START_SCREEN4 CALL LCD_Nbl INCF CNTR,F GOTO START_SCREEN3 START_SCREEN4 RETURN ;***** DISPLAY UPDATE ***** DISPLAY_UPDATE LCD_Move 0x82 MOVF V10,W CALL LCD_Nbl MOVF V1,W CALL LCD_Nbl LCD_Move 0x85 MOVF V01,W CALL LCD_Nbl LCD_Move 0x89 MOVF AH10,W CALL LCD_Nbl MOVF AH1,W CALL LCD_Nbl LCD_Move 0X8C MOVF AH01,W CALL LCD_Nbl MOVF AH001,W CALL LCD_Nbl LCD_Move 0xC3 MOVF P11,W CALL LCD_Nbl LCD_Move 0xC5 MOVF P101,W CALL LCD_Nbl LCD_Move 0xCC MOVF P21,W CALL LCD_Nbl LCD_Move 0xCE MOVF P201,W CALL LCD_Nbl RETURN ;***************************************MATH SUBROUTINES ************************************* ;***** 16 BIT SUBTRACTION ***** ; Input: CALCH, CALCL , SUBH, SUBL ; Output: CALCH=CALCH-SUBH, CALCL=CALCL-SUBL SUB16 BCF STATUS,C MOVF SUBL,W SUBWF CALCL,F MOVF SUBH,W BTFSS STATUS,C ADDLW D'1' SUBWF CALCH,F RETURN ;***** 16 BIT ADDITION ***** ; Input: CALCH, CALCL , SUBH, SUBL ; Output: CALCH=CALCH+SUBH, CALCL=CALCL+SUBL ADD16 MOVF SUBL,W ADDWF CALCL,F MOVF SUBH,W BTFSC STATUS,C ADDLW D'1' ADDWF CALCH,F RETURN ;***** 16 BIT MACRO ***** ; Loads SUBH, SUBL with ARGL LOADS MACRO ARGL MOVLW HIGH(ARGL) MOVWF SUBH MOVLW LOW(ARGL) MOVWF SUBL ENDM ;***** BINARY TO ASCII CONVERSION MACRO***** ; Input: CALCH, CALCL, ARGL ; Output: ASCII value in DIGIT based on CALCH,CALCL divided by ARGL DODIGIT MACRO ARGL LOADS ARGL CALL DOSUB ENDM DOSUB MOVLW '0'-1 MOVWF DIGIT ; tracks ASCII value of count DOSUB1 INCF DIGIT,F ; increment ASCII character CALL SUB16 BTFSC STATUS,C ; any carry? GOTO DOSUB1 ; no, keep subtracting CALL ADD16 ; yes, reverse the last subtraction MOVF DIGIT,W ; place ASCII value of count in W BCF STATUS,C RETURN ;***** PLUG 1 CURRENT DATA TO ASCII CONVERSION ***** ; Input: Current data is in CALCH, CALCL ; Output: ASCII characters in P11, P101, P1001 PLUG1_ASCII DODIGIT D'100' ; count 1's of amps MOVWF P11 ; store result in P11 DODIGIT D'10' ; count 0.1's of amps MOVWF P101 ; store result in P101 DODIGIT D'1' ; count 0.01's of amps MOVWF P1001 ; store result in P1001 RETURN ;***** PLUG 2 CURRENT DATA TO ASCII CONVERSION ***** ; Input: Current data is in CALCH, CALCL ; Output: ASCII characters in P21, P201, P2001 PLUG2_ASCII DODIGIT D'100' ; count 1's of amps MOVWF P21 ; store result in P21 DODIGIT D'10' ; count 0.1's of amps MOVWF P201 ; store result in P201 DODIGIT D'1' ; count 0.01's of amps MOVWF P2001 ; store result in P2001 RETURN ;***** VOLTAGE DATA TO ASCII CONVERSION ***** ; Input: Current data is in CALCH, CALCL ; Output: ASCII characters in V10, V1, V01 VOLT_ASCII DODIGIT D'100' ; count 10's of volts MOVWF V10 ; store result in V10 DODIGIT D'10' ; count 1's of volts MOVWF V1 ; store result in V1 DODIGIT D'1' ; count 0.1's of volts MOVWF V01 ; store result in V01 RETURN ;***** AMP HOUR TO ASCII CONVERSION ***** ; Input: Current data is in CALCH, CALCL ; Output: ASCII characters in AH10, AH1, AH01, AH001 AMP_ASCII DODIGIT D'60000' ; count 10's of amp hours MOVWF AH10 ; store result in AH10 DODIGIT D'6000' ; count 1's of amp hours MOVWF AH1 ; store result in AH1 DODIGIT D'600' ; count 0.1's of amp hours MOVWF AH01 ; store result in AH01 DODIGIT D'60' ; count 0.01's of amp hours MOVWF AH001 ; store result in AH001 RETURN ;************** MAIN ************** MAIN ;***** INITALIZE ***** BANKSEL TRISA MOVLW b'00010000' MOVWF TRISA BANKSEL PORTA CLRF PORTA BANKSEL TRISB MOVLW b'11000001' MOVWF TRISB BANKSEL PORTB CLRF PORTB CLRF HALF_SEC_COUNT CLRF AHH CLRF AHL CLRF CALCPLUG1H CLRF CALCPLUG1L CLRF CALCPLUG2H CLRF CALCPLUG2L MOVLW b'00000001' MOVWF DIM MOVLW '0' MOVWF P11 MOVWF P101 MOVWF P1001 MOVWF P21 MOVWF P201 MOVWF P2001 MOVWF V10 MOVWF V1 MOVWF V01 MOVWF AH10 MOVWF AH1 MOVWF AH01 MOVWF AH001 BANKSEL OPTION_REG MOVLW b'00000000' ; Port B pullups, int falling edge RB0 MOVWF OPTION_REG BANKSEL INTCON MOVLW b'11010000' ; GIE, PIE enabled MOVWF INTCON BANKSEL PIE1 MOVLW b'00000001' ; TMR1I enabled MOVWF PIE1 BANKSEL OSCCON MOVLW b'01100010' ; 4MHZ clock MOVWF OSCCON BANKSEL T1CON MOVLW b'00110000' ; 1:8 pre-scale, Internal Clock, Timer1 disabled MOVWF T1CON BANKSEL ANSEL MOVLW b'01110000' MOVWF ANSEL BANKSEL ADCON1 MOVLW b'10000000' ; Right justified, VDD/VSS as refs MOVWF ADCON1 BANKSEL PR2 MOVLW b'00111110' ; PWM frequency of 1kHz MOVWF PR2 BANKSEL CCPR1L MOVLW b'00111111' ; PWM duty cycle of 100% MOVWF CCPR1L BANKSEL T2CON MOVLW b'00000111' ; TMR2 prescale value 16, TMR2 on MOVWF T2CON BANKSEL CCP1CON MOVLW b'00001111' ; set PWM in CCP1CON MOVWF CCP1CON BANKSEL PORTA DLONG D'200' ; LCD power up delay CALL LCD_Init ; Initialize LCD Module CALL START_SCREEN ; display start screen CALL DISPLAY_UPDATE BANKSEL T1CON BSF T1CON, TMR1ON ; Turn Timer1 on CONVERT BANKSEL ADCON0 ; Convert Plug 1 current MOVLW b'10101001' ; TAD = 32TOSC, convert AN5, AD on MOVWF ADCON0 BANKSEL DELAY1 D10USEC D'2' ; have to wait 20us here BANKSEL ADCON0 BSF ADCON0, GO CONVERT1 BTFSC ADCON0, GO GOTO CONVERT1 BANKSEL ADRESH MOVF ADRESH, W BANKSEL PLUG1H MOVWF PLUG1H BANKSEL ADRESL MOVF ADRESL, W BANKSEL PLUG1L MOVWF PLUG1L RRF PLUG1H, F ; divide by 4 to get value in #s of 10mA RRF PLUG1L, F BCF STATUS, C RRF PLUG1H, F RRF PLUG1L, F BCF STATUS, C MOVF PLUG1H, W MOVWF CALCPLUG1H MOVWF CALCH MOVF PLUG1L, W MOVWF CALCPLUG1L MOVWF CALCL CALL PLUG1_ASCII BANKSEL ADCON0 ; Convert Plug 2 current MOVLW b'10110001' ; TAD = 32TOSC, convert AN6, AD on MOVWF ADCON0 BANKSEL DELAY1 D10USEC D'2' ; have to wait 20us here BANKSEL ADCON0 BSF ADCON0, GO CONVERT2 BTFSC ADCON0, GO GOTO CONVERT2 BANKSEL ADRESH MOVF ADRESH, W BANKSEL PLUG2H MOVWF PLUG2H BANKSEL ADRESL MOVF ADRESL, W BANKSEL PLUG2L MOVWF PLUG2L RRF PLUG2H, F ; divide by 4 to get value in #s of 10mA RRF PLUG2L, F BCF STATUS, C RRF PLUG2H, F RRF PLUG2L, F BCF STATUS, C MOVF PLUG2H, W MOVWF CALCPLUG2H MOVWF CALCH MOVF PLUG2L, W MOVWF CALCPLUG2L MOVWF CALCL CALL PLUG2_ASCII BANKSEL ADCON0 ; Convert Battery voltage MOVLW b'10100001' ; TAD = 32TOSC, convert AN4, AD on MOVWF ADCON0 BANKSEL DELAY1 D10USEC D'2' ; have to wait 20us here BANKSEL ADCON0 BSF ADCON0, GO CONVERT3 BTFSC ADCON0, GO GOTO CONVERT3 BANKSEL ADRESH MOVF ADRESH, W BANKSEL VOLTH MOVWF VOLTH BANKSEL ADRESL MOVF ADRESL, W BANKSEL VOLTL MOVWF VOLTL RRF VOLTH, F ; divide by 4 to get value in #s of 100mV RRF VOLTL, F BCF STATUS, C RRF VOLTH, F RRF VOLTL, F BCF STATUS, C MOVF VOLTH, W MOVWF CALCH MOVF VOLTL, W MOVWF CALCL CALL VOLT_ASCII GOTO CONVERT ; Wait for interrupts END