; VU and peak level meter
; revised to include default loading if Mode switch pressed at power up

	list P=16F88
	#include p16f88.inc
	ERRORLEVEL -302
	ERRORLEVEL -306

;Program Configuration Register 1
		__CONFIG    _CONFIG1, _CP_ALL & _CCP1_RB3 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_ON & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _INTRC_IO

;Program Configuration Register 2
		__CONFIG    _CONFIG2, _IESO_OFF & _FCMEN_OFF

; Define variables at memory locations
; dB values below 0 (0 = 0dB) (30 = -30dB)
; dB values above 0 have bit 7 set (1dB = H'81') (2dB = H82, 3dB = H83, 4dB = H84)
EEPROM1			equ	H'00'	; non-volatile storage for segment 1  channel top row
EEPROM2			equ	H'01'	; non-volatile storage for segment 2 left
EEPROM3			equ	H'02'	; non-volatile storage for segment 3 
EEPROM4			equ	H'03'	; non-volatile storage for segment 4 
EEPROM5			equ	H'04'	; non-volatile storage for segment 5 
EEPROM6			equ	H'05'	; non-volatile storage for segment 6 
EEPROM7			equ	H'06'	; non-volatile storage for segment 7 
EEPROM8			equ	H'07'	; non-volatile storage for segment 8 
EEPROM9			equ	H'08'	; non-volatile storage for segment 9 
EEPROM10		equ	H'09'	; non-volatile storage for segment 10 
EEPROM11		equ	H'0A'	; non-volatile storage for segment 11 
EEPROM12		equ	H'0B'	; non-volatile storage for segment 12 
EEPROM13		equ	H'0C'	; non-volatile storage for segment 13 
EEPROM14		equ	H'0D'	; non-volatile storage for segment 14 
EEPROM15		equ	H'0E'	; non-volatile storage for segment 15 
EEPROM16		equ	H'0F'	; non-volatile storage for segment 16 

EEPROM17		equ	H'10'	; options (for custom only)

; Bank 0 RAM
; A/D values
VU_LEFT_MS		equ	H'20'	; VU input left channel ms byte
VU_LEFT_LS		equ	H'21'	; VU input left channel ls byte
VU_RIGHT_MS		equ	H'22'	; VU input right channel ms byte
VU_RIGHT_LS		equ	H'23'	; VU input right channel ls byte
PEAK_LEFT_MS	equ	H'24'	; peak input left channel ms byte
PEAK_LEFT_LS	equ	H'25'	; peak input left channel ls byte
PEAK_RIGHT_MS	equ	H'26'	; peak input right channel ms byte
PEAK_RIGHT_LS	equ	H'27'	; peak input right channel ls byte

; General

MODE			equ	H'29'	; display mode
BCD_0			equ	H'2A'	; MS bcd value
BCD_1			equ	H'2B'	; LS binary coded decimal value
BIN_0			equ	H'2C'	; 8-bit binary value
TEMP			equ	H'2D'	; data storage (BCD convert)
CNT_8			equ	H'2E'	; counter in BCD routine
CONVERSION		equ	H'2F'	; conversion wait delay
OUT1			equ	H'30'	; ms decimal display value
OUT2			equ	H'31'	; mid decimal display value
OUT3			equ	H'32'	; ls decimal display value
STORE1			equ	H'33'	; delay counter	
STORE2			equ	H'34'	; delay counter
STORE3			equ	H'35'	; delay counter
D_STO			equ	H'36'	; display data storage
OPTIONS			equ	H'37'	; display options
NORMALISE		equ	H'38'	; normalise value
DISPLAY			equ	H'39'	; display
PORTB_STO		equ	H'3A'	; storage of PORTB
TEMP_DATA		equ	H'3B'	; storage of data

VALUE_A_D_16_M	equ	H'3C'	; right hand A/D value for bar graph ms byte
VALUE_A_D_16_L	equ	H'3D'	; right hand A/D value for bar graph ls byte	
VALUE_A_D_15_M	equ	H'3E'	; A/D value for bar graph ms byte
VALUE_A_D_15_L	equ	H'3F'	; A/D value for bar graph ls byte
VALUE_A_D_14_M	equ	H'40'	; A/D value for bar graph ms byte
VALUE_A_D_14_L	equ	H'41'	; A/D value for bar graph ls byte
VALUE_A_D_13_M	equ	H'42'	; A/D value for bar graph ms byte
VALUE_A_D_13_L	equ	H'43'	; A/D value for bar graph ls byte
VALUE_A_D_12_M	equ	H'44'	; A/D value for bar graph ms byte
VALUE_A_D_12_L	equ	H'45'	; A/D value for bar graph ls byte
VALUE_A_D_11_M	equ	H'46'	; A/D value for bar graph ms byte
VALUE_A_D_11_L	equ	H'47'	; A/D value for bar graph ls byte
VALUE_A_D_10_M	equ	H'48'	; A/D value for bar graph ms byte
VALUE_A_D_10_L	equ	H'49'	; A/D value for bar graph ls byte
VALUE_A_D_9_M	equ	H'4A'	; A/D value for bar graph ms byte
VALUE_A_D_9_L	equ	H'4B'	; A/D value for bar graph ls byte

VALUE_A_D_8_M	equ	H'4C'	; A/D value for bar graph ms byte
VALUE_A_D_8_L	equ	H'4D'	; A/D value for bar graph ls byte	
VALUE_A_D_7_M	equ	H'4E'	; A/D value for bar graph ms byte
VALUE_A_D_7_L	equ	H'4F'	; A/D value for bar graph ls byte
VALUE_A_D_6_M	equ	H'50'	; A/D value for bar graph ms byte
VALUE_A_D_6_L	equ	H'51'	; A/D value for bar graph ls byte
VALUE_A_D_5_M	equ	H'52'	; A/D value for bar graph ms byte
VALUE_A_D_5_L	equ	H'53'	; A/D value for bar graph ls byte
VALUE_A_D_4_M	equ	H'54'	; A/D value for bar graph ms byte
VALUE_A_D_4_L	equ	H'55'	; A/D value for bar graph ls byte
VALUE_A_D_3_M	equ	H'56'	; A/D value for bar graph ms byte
VALUE_A_D_3_L	equ	H'57'	; A/D value for bar graph ls byte
VALUE_A_D_2_M	equ	H'58'	; A/D value for bar graph ms byte
VALUE_A_D_2_L	equ	H'59'	; A/D value for bar graph ls byte
VALUE_A_D_1_M	equ	H'5A'	; A/D value for bar graph ms byte
VALUE_A_D_1_L	equ	H'5B'	; A/D value for bar graph ls byte

TEMP_X			equ	H'5C'	; temporary register
DIGITAL_L		equ H'5D'	; digital left value in dB
DIGITAL_R		equ H'5E'	; digital right value in dB		 
DISPLAY_RATE	equ	H'5F'	; display rate counter
DIGITAL_RATE	equ	H'60'	; digital display rate
TEMP_Y			equ	H'61'	; temporary register
DISP_FLG		equ	H'62'	; display flag
A_TO_DL			equ	H'63'	; A/D slow down
A_TO_DM			equ	H'64'	; A/D slow down rate

; All Banks RAM

W_TMP			equ	H'72'	; storage of w before interrupt
STATUS_TMP		equ	H'73'	; status storage before interrupt
PCLATH_STO		equ	H'74'	; PCLATH store 

; preprogram EEPROM DATA 
	
 ORG     H'2100'
 DE	D'28', D'25', D'22', D'19', D'16', D'13', D'10', D'7', D'5', D'3', D'2', D'1', D'0', H'81', H'82', H'83'
 DE	D'0'

; start at memory 0
	org	0	; reset vector
	goto	SETUP
	org 4	; interrupt vector

; start interrupt by saving w and status registers  
	movwf	W_TMP		; w to w_tmp storage
	swapf	STATUS,w	; status to w
	movwf	STATUS_TMP	; status in status_tmp 
	bcf		STATUS,RP0	; select bank 0
	bcf		STATUS,RP1	; bank 0
	movf	PCLATH,w	; keep PCLATH	
	movwf	PCLATH_STO
	bsf		PCLATH,3	; page 1
	goto	INTERRUPT	; interrupt at page 1 address


; lookup table for 0.5dB changes in level
DECIBEL
	andlw	B'00111111'	; max of 64
 	addwf	PCL,f		; add value to program counter
; add 768
	retlw	D'255'		; 1023 when added to 768 (0dB)
	retlw	D'145'		; 913 when added to 768 (-1dB)
	retlw	D'45'		; 813 when added to 768 (-2dB)
; add 512
	retlw	D'213'		; 725 when added to 512 (-3dB)
	retlw	D'134'		; 646 when added to 512 (-4dB)
	retlw	D'64'		; 576 when added to 512 (-5dB)
	retlw	D'1'		; 513 when added to 512 (-6dB)
; add 255
	retlw	D'202'		; 457 when added to 255 (-7dB)
	retlw	D'153'		; 408 when added to 255 (-8dB)
	retlw	D'108'		; 363 when added to 255 (-9dB)
	retlw	D'69'		; 324 when added to 255 (-10dB)
	retlw	D'34'		; 289 when added to 255 (-11dB)
	retlw	D'2'		; 257 when added to 255 (-12dB)
; add 0
	retlw	D'229'		; (-13dB)
	retlw	D'204'		; (-14dB)
	retlw	D'182'		; (-15dB)
	retlw	D'162'		; (-16dB)
	retlw	D'145'		; (-17dB)
	retlw	D'129'		; (-18dB)
	retlw	D'115'		; (-19dB)
	retlw	D'102'		; (-20dB)
	retlw	D'91'		; (-21dB)
	retlw	D'81'		; (-22dB)
	retlw	D'72'		; (-23dB)
	retlw	D'65'		; (-24dB)
	retlw	D'58'		; (-25dB)
	retlw	D'51'		; (-26dB)
	retlw	D'46'		; (-27dB)
	retlw	D'41'		; (-28dB)
	retlw	D'36'		; (-29dB)
	retlw	D'32'		; (-30dB)
	retlw	D'29'		; (-31dB)
	retlw	D'26'		; (-32dB)
	retlw	D'23'		; (-33dB)
	retlw	D'20'		; (-34dB)
	retlw	D'18'		; (-35dB)
	retlw	D'16'		; (-36dB)
	retlw	D'14'		; (-37dB)
	retlw	D'13'		; (-38dB)
	retlw	D'11'		; (-39dB)
	retlw	D'10'		; (-40dB)
	retlw	D'9'		; (-41dB)
	retlw	D'8'		; (-42dB)
	retlw	D'7'		; (-43dB)
	retlw	D'6'		; (-44dB)
	retlw	D'6'		; (-45dB)
	retlw	D'5'		; (-46dB)
	retlw	D'5'		; (-47dB)
	retlw	D'4'		; (-48dB)
	retlw	D'3'		; (-49dB)
	retlw	D'3'		; (-50dB)
	retlw	D'3'		; (-51dB)
	retlw	D'3'		; (-52dB)
	retlw	D'3'		; (-52dB stop)

	retlw	D'3'		; (-52dB)
	retlw	D'3'		; (-52dB)
	retlw	D'3'		; (-52dB)
	retlw	D'3'		; (-52dB)
	retlw	D'3'		; (-52dB stop)
	retlw	D'3'		; (-52dB)
	retlw	D'3'		; (-52dB)
	retlw	D'3'		; (-52dB)
	retlw	D'3'		; (-52dB)
	retlw	D'3'		; (-52dB stop)
	retlw	D'3'		; (-52dB)
	retlw	D'3'		; (-52dB)
	retlw	D'3'		; (-52dB)
	retlw	D'3'		; (-52dB)
	retlw	D'3'		; (-52dB stop)

; **********************************************************************************************

SETUP
	clrf	PORTB		; port B outputs low
	clrf	PORTA		; port A output low
	clrf	DISPLAY
	clrf	MODE		; display MODE
	bsf		STATUS,RP0	; select memory bank 1

; set inputs/outputs
	movlw	B'00000111'	; comparators off
	movwf	CMCON
	movlw	B'11110000'	; port B outputs/ inputs set 
	movwf	TRISB		; port B data direction register
	movlw	B'10101111'	; outputs (0) and inputs (1)
	movwf	TRISA		; port A data direction register
	movlw	B'00000111'	; settings (pullups enabled, TMR0/256)
	movwf	OPTION_REG

; analog inputs, A/D

	movlw	B'00001111'	; AN0 to AN3 are analog inputs
	movwf	ANSEL
	movlw	B'11000000'	; right justified A/D result, Vdd to Vss A/D
	movwf	ADCON1
	bcf		STATUS,RP0	; select memory bank 0
	movlw	B'01000000'	; Fosc, channel etc
	movwf	ADCON0
	bsf		ADCON0,ADON	; A/D on
	bsf		STATUS,RP0	; select memory bank 1
	movlw	B'01111000'	; 0111 for 8MHz
	movwf	OSCCON		; 
	bcf		STATUS,RP0	; select memory bank 0
	
; initial conditions

 	clrf	VU_LEFT_MS	; VU input left channel ms byte
	clrf	VU_LEFT_LS	; VU input left channel ls byte
	clrf	VU_RIGHT_MS	; VU input right channel ms byte
	clrf	VU_RIGHT_LS	; VU input right channel ls byte
	clrf	PEAK_LEFT_MS; peak input left channel ms byte
	clrf	PEAK_LEFT_LS; peak input left channel ls byte
	clrf	PEAK_RIGHT_MS; peak input right channel ms byte
	clrf	PEAK_RIGHT_LS; peak input right channel ls byte
	clrf	DISPLAY_RATE ; display rate timer
	clrf	DIGITAL_RATE ; digital display rate timer
	clrf	DISP_FLG	; display flag
	clrf	A_TO_DM		; A/D slow down 
	incf	A_TO_DM,f	; to a 1


; Return to default conditions if Mode switch pressed at startup

;	btfsc	PORTB,6		; Mode switch low reload defaults	
	goto	READ_EEP

; meter	D'28', D'25', D'22', D'19', D'16', D'13', D'10', D'7', D'5', D'3', D'2', D'1', D'0', H'81', H'82', H'83'
; options	D'0'

; rewrite EEPROM 1 to 17
	movlw	EEPROM1
	call	EEREAD
	movlw	D'28'
	call	EWRITE	
	movlw	EEPROM2
	call	EEREAD
	movlw	D'25'
	call	EWRITE
	movlw	EEPROM3
	call	EEREAD
	movlw	D'22'
	call	EWRITE
	movlw	EEPROM4
	call	EEREAD
	movlw	D'19'
	call	EWRITE
	movlw	EEPROM5
	call	EEREAD
	movlw	D'16'
	call	EWRITE
	movlw	EEPROM6
	call	EEREAD
	movlw	D'13'
	call	EWRITE
	movlw	EEPROM7
	call	EEREAD
	movlw	D'10'
	call	EWRITE	
	movlw	EEPROM8
	call	EEREAD
	movlw	D'7'
	call	EWRITE
	movlw	EEPROM9
	call	EEREAD
	movlw	D'5'
	call	EWRITE
	movlw	EEPROM10
	call	EEREAD
	movlw	D'3'
	call	EWRITE
	movlw	EEPROM11
	call	EEREAD
	movlw	D'2'
	call	EWRITE
	movlw	EEPROM12
	call	EEREAD
	movlw	D'1'
	call	EWRITE
	movlw	EEPROM13
	call	EEREAD
	movlw	D'0'
	call	EWRITE	
	movlw	EEPROM14
	call	EEREAD
	movlw	H'81'
	call	EWRITE
	movlw	EEPROM15
	call	EEREAD
	movlw	H'82'
	call	EWRITE
	movlw	EEPROM16
	call	EEREAD
	movlw	H'83'
	call	EWRITE

	movlw	EEPROM17
	call	EEREAD
	movlw	D'00'
	call	EWRITE
WAIT_MODE ; wait til mode switch opened	
	call	DELAYX	
	btfss	PORTB,6
	goto	WAIT_MODE
	

; read EEPROM 
READ_EEP	
	movlw	EEPROM17
	call	EEREAD		; sets EEADR
	movwf	OPTIONS		; display options

	call	INIT_LC	
	movlw	H'FF'		; start up delay
	call	DELAYX
	call	INIT_LC
	call	DELAYms
	call	INIT_LC
	call	DELAYms

	movlw	B'00101100'	; display function (4-bits, 2 lines, 5x10 dots)
	call	LOAD
	movlw	B'00001110'	; blinking off, cursor off
	call	LOAD
	movlw	B'00000001'	; display clear
	call	LOAD
	movlw	H'FF'		; delay 
	call	DELAYX		; 
	movlw	B'00000110'	; entry mode. cursor moves right, display not shifted
	call	LOAD
	movlw	B'00001110'	; blinking off, cursor off
	call	LOAD
	movlw	B'00101100'	; display function (4-bits, 2 lines, 5x10 dots)
	call	LOAD		; 
	movlw	B'00000001'	; display clear
	call	LOAD
	movlw	H'FF'		; delay 
	call	DELAYX
	
	call	CHARACTR_GEN;generate characters for display
	
; allow interrupts
	bsf		INTCON,TMR0IE	; timer 0 interrupt enable
	bcf		INTCON,TMR0IF	; clear flag
CYCLE1
	call	DISPLAY_CALC	; calculate out meter values
	clrf	DISPLAY			; bargraph display
CYCLE	
; code cycle
	movf	DISPLAY,w		; if zero check mode
	btfss	STATUS,Z
	goto	CK_SW
	movf	MODE,w			; if zero run a/d
	btfss	STATUS,Z
	goto	CK_SW			; check switches

; Channel 0 A/D value (Peak right)
CH_0AD
	bsf 	INTCON,GIE		; set global interrupt enable

	decfsz	A_TO_DL,f		; counters to slow down 
	goto	CK_SW
;	decfsz	A_TO_DM,f
;	goto	CK_SW
;	movlw	D'01'
;	movwf	A_TO_DM

	bcf		ADCON0,3
	bcf		ADCON0,4
	bcf		ADCON0,5		; channel 0
	call	ACQUIRE_AD 
; increase value but do not decrease till displayed
	bcf 	INTCON,GIE		; clear global interrupt enable 
	movf	ADRESH,w		; peak input left channel ms byte
	subwf	PEAK_RIGHT_MS,w	; high byte 
	movwf	TEMP_Y
	bsf		STATUS,RP0		; select memory bank 1
	movf	ADRESL,w		; ls byte
	bcf		STATUS,RP0		; select memory bank 0
	subwf	PEAK_RIGHT_LS,w	; ls byte
	btfss	STATUS,C
	decf	TEMP_Y,f
	iorwf	TEMP_Y,w		; equal to zero
	btfsc	STATUS,Z
	goto	CHNG_PK_R		; change peak
	btfsc	TEMP_Y,7
	goto	CHNG_PK_R		; 
	btfsc	DISP_FLG,0		; if flag set wait to clear (when displayed) bit 0 for peak right
	goto	CH_2AD
CHNG_PK_R
	movf	ADRESH,w		; ms byte
	movwf	PEAK_RIGHT_MS
	bsf		STATUS,RP0		; select memory bank 1
	movf	ADRESL,w		; ls byte
	bcf		STATUS,RP0		; select memory bank 0
	movwf	PEAK_RIGHT_LS
	bsf		DISP_FLG,0		; bit 0 = peak richt ch0

; Channel 2 A/D value (VU right)
CH_2AD
	bsf 	INTCON,GIE		; set global interrupt enable 
	bcf		ADCON0,3
	bsf		ADCON0,4		; channel 2
	call	ACQUIRE_AD		; convert
; increase value but do not decrease till displayed
	bcf 	INTCON,GIE		; clear global interrupt enable 
	movf	ADRESH,w		; peak input left channel ms byte
	subwf	VU_RIGHT_MS,w	; high byte 
	movwf	TEMP_Y
	bsf		STATUS,RP0		; select memory bank 1
	movf	ADRESL,w		; ls byte
	bcf		STATUS,RP0		; select memory bank 0
	subwf	VU_RIGHT_LS,w	; ls byte
	btfss	STATUS,C
	decf	TEMP_Y,f
	iorwf	TEMP_Y,w		; equal to zero
	btfsc	STATUS,Z
	goto	CHNG_VU_R		; change VU
	btfsc	TEMP_Y,7
	goto	CHNG_VU_R		; 
	btfsc	DISP_FLG,2		; if flag set wait to clear (when displayed) bit 2 for VU right
	goto	CH_1AD
CHNG_VU_R
	movf	ADRESH,w		; ms byte
	movwf	VU_RIGHT_MS
	bsf		STATUS,RP0		; select memory bank 1
	movf	ADRESL,w		; ls byte
	bcf		STATUS,RP0		; select memory bank 0
	movwf	VU_RIGHT_LS
	bsf		DISP_FLG,2

; Channel 1 A/D value (Peak left)
CH_1AD
	bsf 	INTCON,GIE		; set global interrupt enable 
	bsf		ADCON0,3		; channel 1
	bcf		ADCON0,4
	call	ACQUIRE_AD		; convert
; increase value but do not decrease till displayed
	bcf 	INTCON,GIE		; clear global interrupt enable 
	movf	ADRESH,w		; peak input left channel ms byte
	subwf	PEAK_LEFT_MS,w	; high byte 
	movwf	TEMP_Y
	bsf		STATUS,RP0		; select memory bank 1
	movf	ADRESL,w		; ls byte
	bcf		STATUS,RP0		; select memory bank 0
	subwf	PEAK_LEFT_LS,w	; ls byte
	btfss	STATUS,C
	decf	TEMP_Y,f
	iorwf	TEMP_Y,w		; equal to zero
	btfsc	STATUS,Z
	goto	CHNG_PK_L		; change peak
	btfsc	TEMP_Y,7
	goto	CHNG_PK_L		; 
	btfsc	DISP_FLG,1		; if flag set wait to clear (when displayed) bit 1 for peak left
	goto	CH_3AD
CHNG_PK_L
	movf	ADRESH,w		; ms byte
	movwf	PEAK_LEFT_MS
	bsf		STATUS,RP0		; select memory bank 1
	movf	ADRESL,w		; ls byte
	bcf		STATUS,RP0		; select memory bank 0
	movwf	PEAK_LEFT_LS
	bsf		DISP_FLG,1		; bit 1 = peak left ch1

; Channel 3 A/D value (VU left)
CH_3AD
	bsf 	INTCON,GIE		; set global interrupt enable 
	bsf		ADCON0,3		; channel 3
	bsf		ADCON0,4
	call	ACQUIRE_AD		; convert
; increase value but do not decrease till displayed
	bcf 	INTCON,GIE		; clear global interrupt enable 
	movf	ADRESH,w		; peak input left channel ms byte
	subwf	VU_LEFT_MS,w	; high byte 
	movwf	TEMP_Y
	bsf		STATUS,RP0		; select memory bank 1
	movf	ADRESL,w		; ls byte
	bcf		STATUS,RP0		; select memory bank 0
	subwf	VU_LEFT_LS,w	; ls byte
	btfss	STATUS,C
	decf	TEMP_Y,f
	iorwf	TEMP_Y,w		; equal to zero
	btfsc	STATUS,Z
	goto	CHNG_VU_L		; change VU
	btfsc	TEMP_Y,7
	goto	CHNG_VU_L		; 
	btfsc	DISP_FLG,3		; if flag set wait to clear (when displayed) bit 1 for peak left
	goto	CH_AD_OUT
CHNG_VU_L
	movf	ADRESH,w		; ms byte
	movwf	VU_LEFT_MS
	bsf		STATUS,RP0		; select memory bank 1
	movf	ADRESL,w		; ls byte
	bcf		STATUS,RP0		; select memory bank 0
	movwf	VU_LEFT_LS
	bsf		DISP_FLG,3	
CH_AD_OUT
	bsf 	INTCON,GIE		; set global interrupt enable 

; check switches
CK_SW
	movf	PORTB,w			; switches at RB4-7
	iorlw	B'00001111'		; lower bits high
	xorlw	H'FF'			; if all 1's then no switch pressed
	btfsc	STATUS,Z
	goto	CYCLE			; all 1's so bypass switch check
	
; which switch
	bcf 	INTCON,GIE		; clear global interrupt enable 
	btfss	PORTB,6
	goto	MODE_DSP
	btfss	PORTB,7
	goto	OPTIONS_DSP
	btfss	PORTB,4
	goto	UP
	btfss	PORTB,5
	goto	DN
	goto	CYCLE

MODE_DSP
; shows current mode on display

	incf	MODE,f			; mode switch increases by 1 each time
	movf	MODE,w
	sublw	D'16'	
	btfss	STATUS,C		; when >16 set at 0
	clrf	MODE
	movf	MODE,w
	btfss	STATUS,Z		; when zero bypass custom
	goto	CUSTOM
	goto	CYCLE

CUSTOM ; customise meter
	movlw	D'01'
	movwf	DISPLAY			; display 
	movlw	H'80'			; line 1 position 1
	call	LOAD
	call	SPACE4			; clear display
	call	SPACE4
	call	SPACE4
	call	SPACE4
	movlw	H'7F'			; 1 less than because mode is 1 or more line 1 position 1
	addwf	MODE,w			; add mode value
	call	LOAD
	movlw	H'FF'		; 	; bar in mode position
	call	DRV_LCD

	movlw	H'C0'			; line 2 position 1
	call	LOAD
	movlw	A'S'		; Set
	call	DRV_LCD
	movlw	A'E'		; 
	call	DRV_LCD
	movlw	A'T'		; 
	call	DRV_LCD
	call	SPACE1
	movlw	A'V'		; value
	call	DRV_LCD
	movlw	A'A'		; value
	call	DRV_LCD
	movlw	A'L'		; value
	call	DRV_LCD
	movlw	A'U'		; value
	call	DRV_LCD
	movlw	A'E'		; value
	call	DRV_LCD
	movf	MODE,w		; display position
	call	SPACE1
	decf	MODE,w		; address of current value
	call	EEREAD	
	movwf	BIN_0		;
	btfss	BIN_0,7		; set is +
	goto	MINUS1
	movlw	A'+'		; write plus
	call 	DRV_LCD
	goto	VAL_1
MINUS1
	movf	BIN_0,w		; value
	btfss	STATUS,Z	; if zero; space
	goto	JUST_MINUS
	call	SPACE1
	goto	VAL_1
JUST_MINUS
	movlw	A'-'		; write minus
	call 	DRV_LCD
VAL_1
	bcf		BIN_0,7

	call	BCD_ASCII	; get ASCII values
	
	movf	OUT2,w		; middle digit
	xorlw	H'30'		; is it 0
	btfss	STATUS,Z
	goto	LOADL1
	call	SPACE1 
	goto	LOADL2
LOADL1	
	movf	OUT2,w		; not zero so load value
	call 	DRV_LCD
LOADL2
	movf	OUT3,w
	call	DRV_LCD
	movlw	A'd'		; dB
	call 	DRV_LCD
	movlw	A'B'		; 
	call 	DRV_LCD
	call	SPACE2
	
	call	DELAY_SWITCH
	goto	CYCLE

OPTIONS_DSP
	movlw	D'02'
	movwf	DISPLAY			; display 
	movlw	H'80'			; line 1 position 1
	call	LOAD
	btfss	OPTIONS,2		; if set then digital
	goto	BAR				; bar only
; digital
	movlw	A'D'			; 
	call	DRV_LCD
	movlw	A'I'			;
	call	DRV_LCD
	movlw	A'G'		; 
	call	DRV_LCD
	movlw	A'I'		; 
	call	DRV_LCD
	movlw	A'T'			;
	call	DRV_LCD
	movlw	A'A'		; 
	call	DRV_LCD
	movlw	A'L'
	call	DRV_LCD		;
	call	SPACE1
	movlw	A'&'
	call	DRV_LCD		;
	call	SPACE1
BAR
	movlw	A'B'		;
	call	DRV_LCD
	movlw	A'A'		; 
	call	DRV_LCD
	movlw	A'R'
	call	DRV_LCD	
	call	SPACE4
	call	SPACE4
	call	SPACE4
	call	SPACE1
	
; line 2
; VU on or off
	movlw	H'C0'			; line 2 position 1
	call	LOAD
	movlw	A'V'		;
	call	DRV_LCD
	movlw	A'U'		; 
	call	DRV_LCD
	call	SPACE1
	movlw	A'O'			;
	call	DRV_LCD
	btfss	OPTIONS,0
	goto	ON_ON1
	movlw	A'F'		; 
	call	DRV_LCD
	movlw	A'F'
	call	DRV_LCD		;
	goto	BY_ON_ON1
ON_ON1
	movlw	A'N'
	call	DRV_LCD	
	call	SPACE1
BY_ON_ON1
	call	SPACE1

; peak on or off	
	movlw	A'P'		;
	call	DRV_LCD
	movlw	A'E'		; 
	call	DRV_LCD
	movlw	A'A'		;
	call	DRV_LCD
	movlw	A'K'		; 
	call	DRV_LCD
	call	SPACE1
	movlw	A'O'			;
	call	DRV_LCD
	btfss	OPTIONS,1
	goto	ON_ON2
	movlw	A'F'		; 
	call	DRV_LCD
	movlw	A'F'
	call	DRV_LCD		;
	goto	BY_ON_ON2
ON_ON2
	movlw	A'N'
	call	DRV_LCD	
	call	SPACE1
BY_ON_ON2
	call	SPACE1
	call	DELAY_SWITCH
	goto	CYCLE

UP
	movf	DISPLAY,w
	btfsc	STATUS,Z	; if zero no change
	goto	CYCLE		; when MODE is 0 (VU/PK display) no increase so bypass
	movf	DISPLAY,w
	xorlw	D'1'		; when 1 increase current dB setting value
	btfss	STATUS,Z
	goto	CK_OPT
; mode, increase current dB setting value for SETTINGs 1-16 only. Goto to CUSTOM 
	decf	MODE,w		; eeprom address of data
	call	EEREAD		; value in w	
	movwf	TEMP_DATA
	sublw	H'8F'		; stop at +16dB (the '8' flags a + sign)
	btfss	STATUS,C
	goto	OUT_UP
	movf	TEMP_DATA,w	; get value again
	btfss	STATUS,Z	; when zero increase to 81 (equals +1dB)
	goto	CK_VAL1
; zero
	movlw	H'81'
	call	EEWRITE		; write value to EEPROM
	goto	OUT_UP
CK_VAL1
	btfss	TEMP_DATA,7	; if positive (bit 7 set) increase
	goto	DEC_DATA1
	incf	TEMP_DATA,w
	call	EEWRITE		; write value to EEPROM
	goto	OUT_UP
DEC_DATA1
	decf	TEMP_DATA,w
	call	EEWRITE		; write value to EEPROM
OUT_UP
	goto	CUSTOM
	
CK_OPT
; When DISPLAY is 2 (OPTIONS) increase OPTIONS (store) and go to OPTIONS Display
	movf	DISPLAY,w
	btfsc	STATUS,Z	; if zero no change
	goto	CYCLE		; when DISPLAY is 0 (VU/PK display) no increase so bypass
	incf	OPTIONS,f
	btfss	OPTIONS,0	; if bits 0,1,2 set then CLEAR
	goto	WRI_EEP17
	btfss	OPTIONS,1	; if bits 0,1,2 set then CLEAR
	goto	WRI_EEP17
	btfss	OPTIONS,2	; if bits 0,1,2 set then CLEAR
	goto	NXT_OPT
	clrf	OPTIONS		; CLEAR OPTIONS
	goto	WRI_EEP17
NXT_OPT
	incf	OPTIONS,f	; next option		
WRI_EEP17
	movlw	EEPROM17	; options eeprom
	call	EEREAD		; sets EEADR
	movf	OPTIONS,w
	call	EEWRITE		; write to eeprom
	goto	OPTIONS_DSP

DN
	movf	DISPLAY,w
	btfsc	STATUS,Z	; if zero no change
	goto	CYCLE		; when Display is 0 (VU/PK display) no increase so bypass
	movf	DISPLAY,w
	xorlw	D'1'		; when 1 decrease current dB setting value
	btfss	STATUS,Z
	goto	CK_OPT
; mode, decrease current dB setting value for SETTINGs 1-16 only. Goto to CUSTOM 
	decf	MODE,w		; eeprom address of data
	call	EEREAD		; value in w	
	movwf	TEMP_DATA
	btfsc	TEMP_DATA,7	; if set ignore minimum check
	goto	NO_MIN_CK
	sublw	D'47'		; stop at -48dB 
	btfss	STATUS,C
	goto	OUT_DN
NO_MIN_CK
	movf	TEMP_DATA,w	; get value again
	xorlw	H'81'
	btfss	STATUS,Z	; when 81 decrease to 0 (+1dB to 0dB)
	goto	CK_VAL2
; zero
	movlw	H'00'
	call	EEWRITE		; write value to EEPROM
	goto	OUT_DN
CK_VAL2
	btfss	TEMP_DATA,7	; if positive (bit 7 set) decrease
	goto	INC_DATA1
	decf	TEMP_DATA,f
	movlw	H'FF'
	xorwf	TEMP_DATA,w	; if FF then set at 1
	btfss	STATUS,Z
	goto	USE_TMP_DATA
	movlw	H'01'		; was 00 so set at -1
	call	EEWRITE		; write value to EEPROM
	goto	OUT_DN
USE_TMP_DATA
	movf	TEMP_DATA,w
	call	EEWRITE
	goto	OUT_DN
INC_DATA1
	incf	TEMP_DATA,w
	call	EEWRITE		; write value to EEPROM
OUT_DN
	goto	CUSTOM
	
 
; ***************************************************************
; subroutines

DISPLAY_CALC
; calculates values for display
; get maximum 
NXT_16; bar 16
	movlw	EEPROM16		; max display
	call	EEREAD			; 
	movwf	NORMALISE		; take or add this value from each display value before finding equivalent A/D value
; if plus then set at 1024
	btfsc	NORMALISE,7
	goto	SET_AT1024
	movf	NORMALISE,w
	btfsc	STATUS,Z		; if zero set at 1024
	goto	SET_AT1024
; if - set at value set
	movwf	TEMP_DATA
	call	CK_ADDITION		; check if need to add 768, 512 or 255 or 0
	movwf	VALUE_A_D_16_M	; right hand A/D value for bar graph ms byte
	movf	TEMP_DATA,w
	call	DECIBEL			; get A/D value
	movwf	VALUE_A_D_16_L	; right hand A/D value for bar graph ls byte
	clrf	NORMALISE
	goto	NXT_15
SET_AT1024; 1024
	movlw	B'00000011'
	movwf	VALUE_A_D_16_M	; right hand A/D value for bar graph ms byte
	movlw	H'FF'
	movwf	VALUE_A_D_16_L	; right hand A/D value for bar graph ls byte

NXT_15; bar 15
	movf	NORMALISE,w
	andlw	B'01111111'		; strip ms sign bit
	movwf	NORMALISE		; new normalise value 
	
	movlw	EEPROM15
	call	EEREAD
	movwf	TEMP_DATA		
	btfsc	TEMP_DATA,7		; if set then TEMP_DATA from NORMALISE
	goto	TAKE_NORM15
	movf	NORMALISE,w

	addwf	TEMP_DATA,f		; normalised
	bcf		TEMP_DATA,7		; ms bit out
	sublw	D'48'
	movlw	D'48'
	btfss	STATUS,C		; when negative set at maximum (48)
	movwf	TEMP_DATA		; maximum	
	goto	DATA15
TAKE_NORM15
	bcf		TEMP_DATA,7
	movf	TEMP_DATA,w
	subwf	NORMALISE,w
	movwf	TEMP_DATA
; check value to determine if a value needs to be added to A/D value in lookup table			
; breaks are
; 0-2dB add 768
; -3--6dB add 512
; -7dB--12dB add 255
; -13 add 0
DATA15
	movf	TEMP_DATA,w		
	call	CK_ADDITION		; check if need to add 768, 512 or 255 or 0
	movwf	VALUE_A_D_15_M	; right hand A/D value for bar graph ms byte
	movf	TEMP_DATA,w
	call	DECIBEL			; get A/D value
	movwf	VALUE_A_D_15_L	; right hand A/D value for bar graph ls byte

NXT_14; bar 14
	
	movlw	EEPROM14
	call	EEREAD
	movwf	TEMP_DATA		
	btfsc	TEMP_DATA,7		; if set then TEMP_DATA from NORMALISE
	goto	TAKE_NORM14
	movf	NORMALISE,w

	addwf	TEMP_DATA,f		; normalised
	bcf		TEMP_DATA,7		; ms bit out
	sublw	D'48'
	movlw	D'48'
	btfss	STATUS,C		; when negative set at maximum (48)
	movwf	TEMP_DATA		; maximum	
	goto	DATA14
TAKE_NORM14
	bcf		TEMP_DATA,7
	movf	TEMP_DATA,w
	subwf	NORMALISE,w
	movwf	TEMP_DATA
; check value to determine if a value needs to be added to A/D value in lookup table			
; breaks are
; 0-2dB add 768
; -3--6dB add 512
; -7dB--12dB add 255
; -13 add 0
DATA14
	movf	TEMP_DATA,w		
	call	CK_ADDITION		; check if need to add 768, 512 or 255 or 0
	movwf	VALUE_A_D_14_M	; right hand A/D value for bar graph ms byte
	movf	TEMP_DATA,w
	call	DECIBEL			; get A/D value
	movwf	VALUE_A_D_14_L	; right hand A/D value for bar graph ls byte

NXT_13; bar 13
		
	movlw	EEPROM13
	call	EEREAD
	movwf	TEMP_DATA		
	btfsc	TEMP_DATA,7		; if set then TEMP_DATA from NORMALISE
	goto	TAKE_NORM13
	movf	NORMALISE,w

	addwf	TEMP_DATA,f		; normalised
	bcf		TEMP_DATA,7		; ms bit out
	sublw	D'48'
	movlw	D'48'
	btfss	STATUS,C		; when negative set at maximum (48)
	movwf	TEMP_DATA		; maximum	
	goto	DATA13
TAKE_NORM13
	bcf		TEMP_DATA,7
	movf	TEMP_DATA,w
	subwf	NORMALISE,w
	movwf	TEMP_DATA
; check value to determine if a value needs to be added to A/D value in lookup table			
; breaks are
; 0-2dB add 768
; -3--6dB add 512
; -7dB--12dB add 255
; -13 add 0
DATA13
	movf	TEMP_DATA,w		
	call	CK_ADDITION		; check if need to add 768, 512 or 255 or 0
	movwf	VALUE_A_D_13_M	; right hand A/D value for bar graph ms byte
	movf	TEMP_DATA,w
	call	DECIBEL			; get A/D value
	movwf	VALUE_A_D_13_L	; right hand A/D value for bar graph ls byte

NXT_12; bar 12
	
	movlw	EEPROM12
	call	EEREAD
	movwf	TEMP_DATA		
	btfsc	TEMP_DATA,7		; if set then TEMP_DATA from NORMALISE
	goto	TAKE_NORM12
	movf	NORMALISE,w

	addwf	TEMP_DATA,f		; normalised
	bcf		TEMP_DATA,7		; ms bit out
	sublw	D'48'
	movlw	D'48'
	btfss	STATUS,C		; when negative set at maximum (48)
	movwf	TEMP_DATA		; maximum	
	goto	DATA12
TAKE_NORM12
	bcf		TEMP_DATA,7
	movf	TEMP_DATA,w
	subwf	NORMALISE,w
	movwf	TEMP_DATA
; check value to determine if a value needs to be added to A/D value in lookup table			
; breaks are
; 0-2dB add 768
; -3--6dB add 512
; -7dB--12dB add 255
; -13 add 0
DATA12
	movf	TEMP_DATA,w		
	call	CK_ADDITION		; check if need to add 768, 512 or 255 or 0
	movwf	VALUE_A_D_12_M	; right hand A/D value for bar graph ms byte
	movf	TEMP_DATA,w
	call	DECIBEL			; get A/D value
	movwf	VALUE_A_D_12_L	; right hand A/D value for bar graph ls byte

NXT_11; bar 11

	movlw	EEPROM11
	call	EEREAD
	movwf	TEMP_DATA		
	btfsc	TEMP_DATA,7		; if set then TEMP_DATA from NORMALISE
	goto	TAKE_NORM11
	movf	NORMALISE,w

	addwf	TEMP_DATA,f		; normalised
	bcf		TEMP_DATA,7		; ms bit out
	sublw	D'48'
	movlw	D'48'
	btfss	STATUS,C		; when negative set at maximum (48)
	movwf	TEMP_DATA		; maximum	
	goto	DATA11
TAKE_NORM11
	bcf		TEMP_DATA,7
	movf	TEMP_DATA,w
	subwf	NORMALISE,w
	movwf	TEMP_DATA
; check value to determine if a value needs to be added to A/D value in lookup table			
; breaks are
; 0-2dB add 768
; -3--6dB add 512
; -7dB--12dB add 255
; -13 add 0
DATA11
	movf	TEMP_DATA,w		
	call	CK_ADDITION		; check if need to add 768, 512 or 255 or 0
	movwf	VALUE_A_D_11_M	; right hand A/D value for bar graph ms byte
	movf	TEMP_DATA,w
	call	DECIBEL			; get A/D value
	movwf	VALUE_A_D_11_L	; right hand A/D value for bar graph ls byte

NXT_10; bar 10
	
	movlw	EEPROM10
	call	EEREAD
	movwf	TEMP_DATA		
	btfsc	TEMP_DATA,7		; if set then TEMP_DATA from NORMALISE
	goto	TAKE_NORM10
	movf	NORMALISE,w

	addwf	TEMP_DATA,f		; normalised
	bcf		TEMP_DATA,7		; ms bit out
	sublw	D'48'
	movlw	D'48'
	btfss	STATUS,C		; when negative set at maximum (48)
	movwf	TEMP_DATA		; maximum	
	goto	DATA10
TAKE_NORM10
	bcf		TEMP_DATA,7
	movf	TEMP_DATA,w
	subwf	NORMALISE,w
	movwf	TEMP_DATA
; check value to determine if a value needs to be added to A/D value in lookup table			
; breaks are
; 0-2dB add 768
; -3--6dB add 512
; -7dB--12dB add 255
; -13 add 0
DATA10
	movf	TEMP_DATA,w		
	call	CK_ADDITION		; check if need to add 768, 512 or 255 or 0
	movwf	VALUE_A_D_10_M	; right hand A/D value for bar graph ms byte
	movf	TEMP_DATA,w
	call	DECIBEL			; get A/D value
	movwf	VALUE_A_D_10_L	; right hand A/D value for bar graph ls byte

NXT_9; bar 9
	
	movlw	EEPROM9
	call	EEREAD
	movwf	TEMP_DATA		
	btfsc	TEMP_DATA,7		; if set then TEMP_DATA from NORMALISE
	goto	TAKE_NORM9
	movf	NORMALISE,w

	addwf	TEMP_DATA,f		; normalised
	bcf		TEMP_DATA,7		; ms bit out
	sublw	D'48'
	movlw	D'48'
	btfss	STATUS,C		; when negative set at maximum (48)
	movwf	TEMP_DATA		; maximum	
	goto	DATA9
TAKE_NORM9
	bcf		TEMP_DATA,7
	movf	TEMP_DATA,w
	subwf	NORMALISE,w
	movwf	TEMP_DATA
; check value to determine if a value needs to be added to A/D value in lookup table			
; breaks are
; 0-2dB add 768
; -3--6dB add 512
; -7dB--12dB add 255
; -13 add 0
DATA9
	movf	TEMP_DATA,w		
	call	CK_ADDITION		; check if need to add 768, 512 or 255 or 0
	movwf	VALUE_A_D_9_M	; right hand A/D value for bar graph ms byte
	movf	TEMP_DATA,w
	call	DECIBEL			; get A/D value
	movwf	VALUE_A_D_9_L	; right hand A/D value for bar graph ls byte

NXT_8; bar 8
	
	movlw	EEPROM8
	call	EEREAD
	movwf	TEMP_DATA		
	btfsc	TEMP_DATA,7		; if set then TEMP_DATA from NORMALISE
	goto	TAKE_NORM8
	movf	NORMALISE,w

	addwf	TEMP_DATA,f		; normalised
	bcf		TEMP_DATA,7		; ms bit out
	sublw	D'48'
	movlw	D'48'
	btfss	STATUS,C		; when negative set at maximum (48)
	movwf	TEMP_DATA		; maximum	
	goto	DATA8
TAKE_NORM8
	bcf		TEMP_DATA,7
	movf	TEMP_DATA,w
	subwf	NORMALISE,w
	movwf	TEMP_DATA
; check value to determine if a value needs to be added to A/D value in lookup table			
; breaks are
; 0-2dB add 768
; -3--6dB add 512
; -7dB--12dB add 255
; -13 add 0
DATA8
	movf	TEMP_DATA,w		
	call	CK_ADDITION		; check if need to add 768, 512 or 255 or 0
	movwf	VALUE_A_D_8_M	; right hand A/D value for bar graph ms byte
	movf	TEMP_DATA,w
	call	DECIBEL			; get A/D value
	movwf	VALUE_A_D_8_L	; right hand A/D value for bar graph ls byte

NXT_7; bar 7

	movlw	EEPROM7
	call	EEREAD
	movwf	TEMP_DATA		
	btfsc	TEMP_DATA,7		; if set then TEMP_DATA from NORMALISE
	goto	TAKE_NORM7
	movf	NORMALISE,w

	addwf	TEMP_DATA,f		; normalised
	bcf		TEMP_DATA,7		; ms bit out
	sublw	D'48'
	movlw	D'48'
	btfss	STATUS,C		; when negative set at maximum (48)
	movwf	TEMP_DATA		; maximum	
	goto	DATA7
TAKE_NORM7
	bcf		TEMP_DATA,7
	movf	TEMP_DATA,w
	subwf	NORMALISE,w
	movwf	TEMP_DATA
; check value to determine if a value needs to be added to A/D value in lookup table			
; breaks are
; 0-2dB add 768
; -3--6dB add 512
; -7dB--12dB add 255
; -13 add 0
DATA7
	movf	TEMP_DATA,w		
	call	CK_ADDITION		; check if need to add 768, 512 or 255 or 0
	movwf	VALUE_A_D_7_M	; right hand A/D value for bar graph ms byte
	movf	TEMP_DATA,w
	call	DECIBEL			; get A/D value
	movwf	VALUE_A_D_7_L	; right hand A/D value for bar graph ls byte

NXT_6; bar 6
	
	movlw	EEPROM6
	call	EEREAD
	movwf	TEMP_DATA		
	btfsc	TEMP_DATA,7		; if set then TEMP_DATA from NORMALISE
	goto	TAKE_NORM6
	movf	NORMALISE,w

	addwf	TEMP_DATA,f		; normalised
	bcf		TEMP_DATA,7		; ms bit out
	sublw	D'48'
	movlw	D'48'
	btfss	STATUS,C		; when negative set at maximum (48)
	movwf	TEMP_DATA		; maximum	
	goto	DATA6
TAKE_NORM6
	bcf		TEMP_DATA,7
	movf	TEMP_DATA,w
	subwf	NORMALISE,w
	movwf	TEMP_DATA
; check value to determine if a value needs to be added to A/D value in lookup table			
; breaks are
; 0-2dB add 768
; -3--6dB add 512
; -7dB--12dB add 255
; -13 add 0
DATA6
	movf	TEMP_DATA,w		
	call	CK_ADDITION		; check if need to add 768, 512 or 255 or 0
	movwf	VALUE_A_D_6_M	; right hand A/D value for bar graph ms byte
	movf	TEMP_DATA,w
	call	DECIBEL			; get A/D value
	movwf	VALUE_A_D_6_L	; right hand A/D value for bar graph ls byte

NXT_5; bar 5

	movlw	EEPROM5
	call	EEREAD
	movwf	TEMP_DATA		
	btfsc	TEMP_DATA,7		; if set then TEMP_DATA from NORMALISE
	goto	TAKE_NORM5
	movf	NORMALISE,w

	addwf	TEMP_DATA,f		; normalised
	bcf		TEMP_DATA,7		; ms bit out
	sublw	D'48'
	movlw	D'48'
	btfss	STATUS,C		; when negative set at maximum (48)
	movwf	TEMP_DATA		; maximum	
	goto	DATA5
TAKE_NORM5
	bcf		TEMP_DATA,7
	movf	TEMP_DATA,w
	subwf	NORMALISE,w
	movwf	TEMP_DATA
; check value to determine if a value needs to be added to A/D value in lookup table			
; breaks are
; 0-2dB add 768
; -3--6dB add 512
; -7dB--12dB add 255
; -13 add 0
DATA5
	movf	TEMP_DATA,w		
	call	CK_ADDITION		; check if need to add 768, 512 or 255 or 0
	movwf	VALUE_A_D_5_M	; right hand A/D value for bar graph ms byte
	movf	TEMP_DATA,w
	call	DECIBEL			; get A/D value
	movwf	VALUE_A_D_5_L	; right hand A/D value for bar graph ls byte

NXT_4 ; bar 4
	
	movlw	EEPROM4
	call	EEREAD
	movwf	TEMP_DATA		
	btfsc	TEMP_DATA,7		; if set then TEMP_DATA from NORMALISE
	goto	TAKE_NORM4
	movf	NORMALISE,w

	addwf	TEMP_DATA,f		; normalised
	bcf		TEMP_DATA,7		; ms bit out
	sublw	D'48'
	movlw	D'48'
	btfss	STATUS,C		; when negative set at maximum (48)
	movwf	TEMP_DATA		; maximum	
	goto	DATA4
TAKE_NORM4
	bcf		TEMP_DATA,7
	movf	TEMP_DATA,w
	subwf	NORMALISE,w
	movwf	TEMP_DATA
; check value to determine if a value needs to be added to A/D value in lookup table			
; breaks are
; 0-2dB add 768
; -3--6dB add 512
; -7dB--12dB add 255
; -13 add 0
DATA4
	movf	TEMP_DATA,w		
	call	CK_ADDITION		; check if need to add 768, 512 or 255 or 0
	movwf	VALUE_A_D_4_M	; right hand A/D value for bar graph ms byte
	movf	TEMP_DATA,w
	call	DECIBEL			; get A/D value
	movwf	VALUE_A_D_4_L	; right hand A/D value for bar graph ls byte

NXT_3; bar 3
	
	movlw	EEPROM3
	call	EEREAD
	movwf	TEMP_DATA		
	btfsc	TEMP_DATA,7		; if set then TEMP_DATA from NORMALISE
	goto	TAKE_NORM3
	movf	NORMALISE,w

	addwf	TEMP_DATA,f		; normalised
	bcf		TEMP_DATA,7		; ms bit out
	sublw	D'48'
	movlw	D'48'
	btfss	STATUS,C		; when negative set at maximum (48)
	movwf	TEMP_DATA		; maximum	
	goto	DATA3
TAKE_NORM3
	bcf		TEMP_DATA,7
	movf	TEMP_DATA,w
	subwf	NORMALISE,w
	movwf	TEMP_DATA
; check value to determine if a value needs to be added to A/D value in lookup table			
; breaks are
; 0-2dB add 768
; -3--6dB add 512
; -7dB--12dB add 255
; -13 add 0
DATA3
	movf	TEMP_DATA,w		
	call	CK_ADDITION		; check if need to add 768, 512 or 255 or 0
	movwf	VALUE_A_D_3_M	; right hand A/D value for bar graph ms byte
	movf	TEMP_DATA,w
	call	DECIBEL			; get A/D value
	movwf	VALUE_A_D_3_L	; right hand A/D value for bar graph ls byte

NXT_2; bar 2
	
	movlw	EEPROM2
	call	EEREAD
	movwf	TEMP_DATA		
	btfsc	TEMP_DATA,7		; if set then TEMP_DATA from NORMALISE
	goto	TAKE_NORM2
	movf	NORMALISE,w

	addwf	TEMP_DATA,f		; normalised
	bcf		TEMP_DATA,7		; ms bit out
	sublw	D'48'
	movlw	D'48'
	btfss	STATUS,C		; when negative set at maximum (48)
	movwf	TEMP_DATA		; maximum	
	goto	DATA2
TAKE_NORM2
	bcf		TEMP_DATA,7
	movf	TEMP_DATA,w
	subwf	NORMALISE,w
	movwf	TEMP_DATA
; check value to determine if a value needs to be added to A/D value in lookup table			
; breaks are
; 0-2dB add 768
; -3--6dB add 512
; -7dB--12dB add 255
; -13 add 0
DATA2
	movf	TEMP_DATA,w		
	call	CK_ADDITION		; check if need to add 768, 512 or 255 or 0
	movwf	VALUE_A_D_2_M	; right hand A/D value for bar graph ms byte
	movf	TEMP_DATA,w
	call	DECIBEL			; get A/D value
	movwf	VALUE_A_D_2_L	; right hand A/D value for bar graph ls byte

NXT_1; bar 1
	
	movlw	EEPROM1
	call	EEREAD
	movwf	TEMP_DATA		
	btfsc	TEMP_DATA,7		; if set then TEMP_DATA from NORMALISE
	goto	TAKE_NORM1
	movf	NORMALISE,w

	addwf	TEMP_DATA,f		; normalised
	bcf		TEMP_DATA,7		; ms bit out
	sublw	D'48'
	movlw	D'48'
	btfss	STATUS,C		; when negative set at maximum (48)
	movwf	TEMP_DATA		; maximum	
	goto	DATA1
TAKE_NORM1
	bcf		TEMP_DATA,7
	movf	TEMP_DATA,w
	subwf	NORMALISE,w
	movwf	TEMP_DATA
; check value to determine if a value needs to be added to A/D value in lookup table			
; breaks are
; 0-2dB add 768
; -3--6dB add 512
; -7dB--12dB add 255
; -13 add 0
DATA1
	movf	TEMP_DATA,w		
	call	CK_ADDITION		; check if need to add 768, 512 or 255 or 0
	movwf	VALUE_A_D_1_M	; right hand A/D value for bar graph ms byte
	movf	TEMP_DATA,w
	call	DECIBEL			; get A/D value
	movwf	VALUE_A_D_1_L	; right hand A/D value for bar graph ls byte
	return
	
CK_ADDITION
	movf	TEMP_DATA,w
	sublw	D'02'			; 	
	btfsc	STATUS,C		; if plus add 768
	retlw	H'03'			; 768	
	movf	TEMP_DATA,w
	sublw	D'06'			; 	
	btfsc	STATUS,C		; if plus add 512
	retlw	H'02'			; 512
	movf	TEMP_DATA,w
	sublw	D'12'			; 	
	btfsc	STATUS,C		; if plus add 255
	retlw	H'01'			; 255
	retlw	D'00'

; subroutine to wait for conversion

ACQUIRE_AD
; wait for >20us
	movlw	D'50'
	movwf	CONVERSION
LOOP_CONV
	decfsz	CONVERSION,f	; decrease 
	goto	LOOP_CONV	
	bsf		ADCON0,2		; GO/DONE bit start conversion
WAIT_CONV
	btfsc	ADCON0,2		; conversion complete when cleared ~11 cycles
	goto	WAIT_CONV
	return


; add space in display

SPACE4
	movlw	H'20'		; space
	call	DRV_LCD
SPACE3
	movlw	H'20'		; space
	call	DRV_LCD
SPACE2
	movlw	H'20'		; space
	call	DRV_LCD
SPACE1
	movlw	H'20'		; space
	call	DRV_LCD
	return

; switch delay loop
DELAY_SWITCH
	movlw	H'08'
DELAY_SWITCH1
	movwf	STORE3
LOOP_SWITCH
	movlw	H'FF'		; delay 
	call	DELAYX
	decfsz	STORE3,f	; next store3
	goto	LOOP_SWITCH	
	return

; delay loop 

DELAYms
	movlw	D'23'		; delay value
DELAYX
	movwf	STORE1		; STORE1 is number of loops value
LOOP8	
	movlw	H'B0'
DELDSP
	movwf	STORE2		; STORE2 is internal loop value	
LOOP9
	decfsz	STORE2,f
	goto	LOOP9
	decfsz	STORE1,f
	goto	LOOP8		; decrease till STORE1 is zero
	return

; initialise display

INIT_LC
	movlw	B'00000011'	; initialise module
	movwf	PORTB
	nop
	bsf		PORTA,4		; enable high
	nop
	bcf		PORTA,4		; low
	return

; preload display commands (4-bit) 

LOAD
	movwf	D_STO		; store data	
	movf	D_STO,w
	andlw	H'F0'		; get upper bits
; place display commands in portB
	movwf	PORTB_STO
	bcf		PORTB,0
	bcf		PORTB,1
	bcf		PORTB,2
	bcf		PORTB,3
	btfsc	PORTB_STO,7
	bsf		PORTB,3	
	btfsc	PORTB_STO,6
	bsf		PORTB,2	
	btfsc	PORTB_STO,5
	bsf		PORTB,1	
	btfsc	PORTB_STO,4
	bsf		PORTB,0	

	bcf		PORTA,6		; register select low
	nop
	bsf		PORTA,4		; enable set
	nop
	bcf		PORTA,4		; enable clear

	swapf	D_STO,w
	andlw	H'F0'		; get lower bits
; place display commands in portB
	movwf	PORTB_STO
	bcf		PORTB,0
	bcf		PORTB,1
	bcf		PORTB,2
	bcf		PORTB,3
	btfsc	PORTB_STO,7
	bsf		PORTB,3	
	btfsc	PORTB_STO,6
	bsf		PORTB,2	
	btfsc	PORTB_STO,5
	bsf		PORTB,1	
	btfsc	PORTB_STO,4
	bsf		PORTB,0	
	bcf		PORTA,6		; register select low
	nop
	bsf		PORTA,4		; enable set
	nop
	bcf		PORTA,4		; enable clear
	goto	BUS_CK		; check busy flag
	
; driving the LCD module with display data

DRV_LCD	
	movwf	D_STO		; store data
	andlw	H'F0'		; upper bits
	movwf	PORTB_STO
	bcf		PORTB,0
	bcf		PORTB,1
	bcf		PORTB,2
	bcf		PORTB,3
	btfsc	PORTB_STO,7
	bsf		PORTB,3	
	btfsc	PORTB_STO,6
	bsf		PORTB,2	
	btfsc	PORTB_STO,5
	bsf		PORTB,1	
	btfsc	PORTB_STO,4
	bsf		PORTB,0	
	bsf		PORTA,6		; register select
	bsf		PORTA,4		; enable high
	nop
	bcf		PORTA,4		; enable low

	swapf	D_STO,w
	andlw	H'F0'		; lower bits
	movwf	PORTB_STO
	bcf		PORTB,0
	bcf		PORTB,1
	bcf		PORTB,2
	bcf		PORTB,3
	btfsc	PORTB_STO,7
	bsf		PORTB,3	
	btfsc	PORTB_STO,6
	bsf		PORTB,2	
	btfsc	PORTB_STO,5
	bsf		PORTB,1	
	btfsc	PORTB_STO,4
	bsf		PORTB,0	
	bsf		PORTA,6		; register select
	bsf		PORTA,4		; enable high
	nop
	bcf		PORTA,4		; enable low

BUS_CK
	movlw 	D'2'		; was 30
	movwf	STORE1		; delay values
	movlw	D'255'		; delay for busy flag to clear
	goto	DELDSP

; subroutine to read EEPROM memory 

EEREAD
	bcf		STATUS,RP1	; select bank 0
	bsf 	STATUS,RP1	; select memory bank 2
	movwf 	EEADR		; indirect special function register
	bsf 	STATUS,RP0	; select memory bank 3
	bcf		EECON1,EEPGD; data memory
	bsf		EECON1,RD	; read EEPROM
	bcf 	STATUS,RP0	; select memory bank 2
	movf	EEDATA,w	; EEPROM value in w
	bcf		STATUS,RP1	; select bank 0
	return

; subroutine to write to EEPROM
EWRITE
EEWRITE	
	bcf 	STATUS,RP0	; bank 0
	bsf		STATUS,RP1	; select bank 2
	movwf	EEDATA		; data register
	bsf 	STATUS,RP0	; select memory bank 3
WR3	
	btfsc	EECON1,WR	; check if write complete 
	goto 	WR3			; not written yet
;	bcf		INTCON,GIE	; disable interrupts
	bcf		EECON1,EEPGD; data memory
	bsf		EECON1,WREN	; enable write
	movlw	H'55'		; place 55H in w for write sequence
	movwf 	EECON2 		; write 55H to EECON2
	movlw 	H'AA'		; AAH to w
	movwf	EECON2		; write AA to EECON2
	bsf		EECON1,WR	; set WR bit and begin write sequence
	bcf		EECON1,WREN	; clear WREN bit
;	bsf 	INTCON,GIE	; enable interrupts
WRITE
	btfsc	EECON1,WR	; skip if write complete 
	goto 	WRITE		; not written yet
	bcf		EECON1,EEIF	; clear write interrupt flag
	bcf		STATUS,RP1	; 
	bcf 	STATUS,RP0	; select memory bank 0
	return				; value written 

; Subroutine to convert from 8-bit binary to 2-digit BCD (packed)
; Binary value is in BIN_0  
; Result in BCD is in BCD_0 & BCD_1.  
; BCD_0 is MSB, BCD_1 is LSB
; converts to unpacked ASCII in OUT1, OUT2, OUT3 (out1 is ms byte, out3 is ls byte)

BCD_ASCII
	bcf		STATUS,C	; clear carry bit
	movlw	D'8'
	movwf	CNT_8		; 8 in count
	clrf	BCD_0
	clrf	BCD_1		; set BCD registers to 0 
LOOPBCD
	rlf		BIN_0,f		; shift left binary registers
	rlf		BCD_1,f		; MSB shift left

	rlf		BCD_0,f		; LSB shift left BCD registers
	decfsz	CNT_8,f		; reduce count value return when 0
	goto	DECADJ		; continue decimal adjust

; completed decimal to BCD operation, convert to unpacked ASCII
	
	movf	BCD_1,w		; ls decimal
	andlw	H'0F'		; ls
	addlw	H'30'		; convert to ASCII
	movwf	OUT3
	swapf	BCD_1,w 	; mid decimal value
	andlw	H'0F'
	addlw	H'30'		; convert to ASCII
	movwf	OUT2
	movf	BCD_0,w
	addlw	H'30'		; convert to ASCII
	movwf	OUT1		; ms decimal value
	return				; ASCII values returned in OUT1, OUT2, OUT3 

; subroutine decimal adjust

DECADJ
	movlw	BCD_1		; BCD LSB address
	movwf	FSR			; pointer for BCD1
	call	ADJBCD		; subroutine to adjust BCD
	movlw	BCD_0		; BCD MS address
	movwf	FSR			; pointer for BCD0
	call	ADJBCD
	goto	LOOPBCD

; subroutine adjust BCD

ADJBCD	
	movlw	H'03'		; w has 03 
	addwf	INDF,w		; add 03 to BCDx register (x is 0-1)
	movwf	TEMP		; store w
	btfsc	TEMP,3		; test if >7
	movwf	INDF		; save as LS digit
	movlw	H'30'		; 3 for MSbyte
	addwf	INDF,w		; add 30 to BCDx register
	movwf	TEMP		; store w in temp
	btfsc	TEMP,7		; test if >7
	movwf	INDF		; save as MS digit
	return				; end subroutine

; character generation 	
CHARACTR_GEN

; character 1, Peak 
	movlw	B'01000000'	; address 0
	call	LOAD		; character gen 1 
	movlw	B'00000011'
	call	DRV_LCD
	movlw	B'00000011'
	call	DRV_LCD
	movlw	B'00000011'
	call	DRV_LCD
	movlw	B'00000011'
	call	DRV_LCD
	movlw	B'00000011'
	call	DRV_LCD
	movlw	B'00000011'
	call	DRV_LCD
	movlw	B'00000011'
	call	DRV_LCD
	movlw	B'00000011'
	call	DRV_LCD

	return

; ******************************************************************************************************
; INTERRUPT

; start interrupt already saved w and status registers 
	org	H'800'	
INTERRUPT
	bcf		INTCON,TMR0IF	; clear flag

; display rate
	movf	DISPLAY_RATE,w
	btfsc	STATUS,Z		; when zero update
	goto	DISP_UPDATE	
	decf	DISPLAY_RATE,f	; decrease
	bcf		PCLATH,3		; page 0
	goto	RECLAIM
DISP_UPDATE	
	movlw	D'03'
	movwf	DISPLAY_RATE	; display rate

; left channel	
	movlw	H'7F'
	movwf	DIGITAL_L	; digital value to max so it shows no value
	movlw	H'80'		; line 1 position 1
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1

; VU left channel (if digital reserve space and drive at end) 
VU1	
	movlw	A'L'		; left channel
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1

	movf	VU_LEFT_MS,w	; VU input left channel ms byte
	subwf	VALUE_A_D_1_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	VU_LEFT_LS,w	; VU input left channel ls byte	
	subwf	VALUE_A_D_1_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV1		; drive block
	btfsc	TEMP_X,7
	goto	DRV1		; drive block
; check peak value	
	goto	PEAK_1		; not at VU level
DRV1
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_1	
	btfss	OPTIONS,2 	; if options are for digital display load value to DIGITAL_L
	goto	VU2
	movlw	EEPROM1		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value
	goto	VU2
	
PEAK_1
; Peak left channel (if digital reserve space and drive at end) 
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_1_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_1_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK1		; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK1		; drive peak 
; check peak value
	btfsc	OPTIONS,2	; if digital display
	goto	VU2
	bcf		PCLATH,3	; page 0
	call	SPACE1	
	bsf		PCLATH,3	; page 1
	goto	VU2 
DRV_PK1	
	btfss	OPTIONS,1	; if peak then ck option
	goto	CK_OPTION1
	goto	VU2

CK_OPTION1
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU2
	movlw	EEPROM1		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value
	
; VU left channel (if digital reserve space and drive at end) 
VU2	
	movf	VU_LEFT_MS,w	; VU input left channel ms byte
	subwf	VALUE_A_D_2_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	VU_LEFT_LS,w	; VU input left channel ls byte	
	subwf	VALUE_A_D_2_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV2		; drive block
	btfsc	TEMP_X,7
	goto	DRV2		; drive block
; check peak value	
	goto	PEAK_2		; not at VU level
DRV2
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_2	
	btfsc	OPTIONS,2 	; if options are for digital display move to next block
	goto	NXT_BLOCK2
	movlw	H'FF'		; block
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	goto	VU3
LD_EEP2
	movlw	EEPROM2		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value
	goto	VU3
NXT_BLOCK2
	movlw	H'82'		; next block position
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1
	goto	LD_EEP2
PEAK_2
; Peak left channel (if digital reserve space and drive at end) 
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_2_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_2_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK2		; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK2		; drive peak 
; check peak value
	btfsc	OPTIONS,2	; if digital display
	goto	NXT_BLOCK_PK2
SPACE_L2
	bcf		PCLATH,3	; page 0
	call	SPACE1	
	bsf		PCLATH,3	; page 1
	goto	VU3 
NXT_BLOCK_PK2
	movlw	H'82'
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1
	goto	VU3
DRV_PK2	
	btfsc	OPTIONS,1	; if not peak then next block
	goto	NXT_BLOCK_PK2
	btfsc	OPTIONS,2 	; if options are for digital display leave blank
	goto	NXT_PK_BLOCK2
; only drive peak if next peak location is off
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_3_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_3_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	SPACE_L2
	btfsc	TEMP_X,7
	goto	SPACE_L2
; end next test
	movlw	H'00'		; peak
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	goto	VU3
NXT_PK_BLOCK2
	movlw	H'82'
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1
CK_OPTION2
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU3
	movlw	EEPROM2		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value
	
VU3
	movf	VU_LEFT_MS,w	; VU input left channel ms byte
	subwf	VALUE_A_D_3_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	VU_LEFT_LS,w	; VU input left channel ls byte	
	subwf	VALUE_A_D_3_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV3		; drive block
	btfsc	TEMP_X,7
	goto	DRV3		; drive block
; check peak value	
	goto	PEAK_3		; not at VU level
DRV3
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_3	
	btfsc	OPTIONS,2 	; if options are for digital display move to next block
	goto	NXT_BLOCK3
	movlw	H'FF'		; block
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	goto	VU4
LD_EEP3
	movlw	EEPROM3		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value
	goto	VU4
NXT_BLOCK3
	movlw	H'83'		; next block position
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1
	goto	LD_EEP3
PEAK_3
; Peak left channel (if digital reserve space and drive at end) 
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_3_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_3_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK3		; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK3		; drive peak 
; check peak value
	btfsc	OPTIONS,2	; if digital display
	goto	NXT_BLOCK_PK3
SPACE_L3
	bcf		PCLATH,3	; page 0
	call	SPACE1
	bsf		PCLATH,3	; page 1
	goto	VU4 
NXT_BLOCK_PK3
	movlw	H'83'
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1
	goto	VU4
DRV_PK3	
	btfsc	OPTIONS,1	; if not peak then next block
	goto	NXT_BLOCK_PK3
	btfsc	OPTIONS,2 	; if options are for digital display leave blank
	goto	NXT_PK_BLOCK3
; only drive peak if next peak location is off
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_4_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_4_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	SPACE_L3
	btfsc	TEMP_X,7
	goto	SPACE_L3
; end next test
	movlw	H'00'		; peak
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	goto	VU4
NXT_PK_BLOCK3
	movlw	H'83'
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1

CK_OPTION3
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU4
	movlw	EEPROM3		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value

VU4
	movf	VU_LEFT_MS,w	; VU input left channel ms byte
	subwf	VALUE_A_D_4_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	VU_LEFT_LS,w	; VU input left channel ls byte	
	subwf	VALUE_A_D_4_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV4		; drive block
	btfsc	TEMP_X,7
	goto	DRV4		; drive block
; check peak value	
	goto	PEAK_4		; not at VU level
DRV4
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_4	
	btfsc	OPTIONS,2 	; if options are for digital display move to next block
	goto	NXT_BLOCK4
	movlw	H'FF'		; block
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	goto	VU5
LD_EEP4
	movlw	EEPROM4		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value
	goto	VU5
NXT_BLOCK4
	movlw	H'84'		; next block position
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1
	goto	LD_EEP4
PEAK_4
; Peak left channel (if digital reserve space and drive at end) 
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_4_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_4_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK4		; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK4		; drive peak 
; check peak value
	btfsc	OPTIONS,2	; if digital display
	goto	NXT_BLOCK_PK4
SPACE_L4
	bcf		PCLATH,3	; page 0
	call	SPACE1
	bsf		PCLATH,3	; page 1
	goto	VU5 
NXT_BLOCK_PK4
	movlw	H'84'
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1
	goto	VU5
DRV_PK4	
	btfsc	OPTIONS,1	; if not peak then next block
	goto	NXT_BLOCK_PK4
	btfsc	OPTIONS,2 	; if options are for digital display leave blank
	goto	NXT_PK_BLOCK4
; only drive peak if next peak location is off
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_5_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_5_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	SPACE_L4
	btfsc	TEMP_X,7
	goto	SPACE_L4
; end next test
	movlw	H'00'		; peak
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	goto	VU5
NXT_PK_BLOCK4
	movlw	H'84'
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1
CK_OPTION4
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU5
	movlw	EEPROM4		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value

VU5
	movf	VU_LEFT_MS,w	; VU input left channel ms byte
	subwf	VALUE_A_D_5_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	VU_LEFT_LS,w	; VU input left channel ls byte	
	subwf	VALUE_A_D_5_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV5		; drive block
	btfsc	TEMP_X,7
	goto	DRV5		; drive block
; check peak value	
	goto	PEAK_5		; not at VU level
DRV5
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_5	
	btfsc	OPTIONS,2 	; if options are for digital display move to next block
	goto	NXT_BLOCK5
	movlw	H'FF'		; block
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	goto	VU6
LD_EEP5
	movlw	EEPROM5		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value
	goto	VU6
NXT_BLOCK5
	movlw	H'85'		; next block position
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1
	goto	LD_EEP5
PEAK_5
; Peak left channel (if digital reserve space and drive at end) 
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_5_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_5_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK5		; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK5		; drive peak 
; check peak value
	btfsc	OPTIONS,2	; if digital display
	goto	NXT_BLOCK_PK5
SPACE_L5
	bcf		PCLATH,3	; page 0
	call	SPACE1
	bsf		PCLATH,3	; page 1
	goto	VU6 
NXT_BLOCK_PK5
	movlw	H'85'
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1
	goto	VU6
DRV_PK5	
	btfsc	OPTIONS,1	; if not peak then next block
	goto	NXT_BLOCK_PK5
	btfsc	OPTIONS,2 	; if options are for digital display leave blank
	goto	NXT_PK_BLOCK5
; only drive peak if next peak location is off
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_6_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_6_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	SPACE_L5
	btfsc	TEMP_X,7
	goto	SPACE_L5
; end next test
	movlw	H'00'		; peak
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	goto	VU6
NXT_PK_BLOCK5
	movlw	H'85'
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1
CK_OPTION5
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU6
	movlw	EEPROM5		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value

VU6
	movf	VU_LEFT_MS,w	; VU input left channel ms byte
	subwf	VALUE_A_D_6_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	VU_LEFT_LS,w	; VU input left channel ls byte	
	subwf	VALUE_A_D_6_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV6		; drive block
	btfsc	TEMP_X,7
	goto	DRV6		; drive block
; check peak value	
	goto	PEAK_6		; not at VU level
DRV6
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_6	
	btfsc	OPTIONS,2 	; if options are for digital display move to next block
	goto	NXT_BLOCK6
	movlw	H'FF'		; block
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	goto	VU7
LD_EEP6
	movlw	EEPROM6		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value
	goto	VU7
NXT_BLOCK6
	movlw	H'86'		; next block position
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1
	goto	LD_EEP6
PEAK_6
; Peak left channel (if digital reserve space and drive at end) 
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_6_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_6_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK6		; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK6		; drive peak 
; check peak value
	btfsc	OPTIONS,2	; if digital display
	goto	NXT_BLOCK_PK6
SPACE_L6
	bcf		PCLATH,3	; page 0
	call	SPACE1
	bsf		PCLATH,3	; page 1
	goto	VU7 
NXT_BLOCK_PK6
	movlw	H'86'
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1
	goto	VU7
DRV_PK6	
	btfsc	OPTIONS,1	; if not peak then next block
	goto	NXT_BLOCK_PK6
	btfsc	OPTIONS,2 	; if options are for digital display leave blank
	goto	NXT_PK_BLOCK6
; only drive peak if next peak location is off
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_7_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_7_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	SPACE_L6
	btfsc	TEMP_X,7
	goto	SPACE_L6
; end next test
	movlw	H'00'		; peak
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	goto	VU7
NXT_PK_BLOCK6
	movlw	H'86'
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1
CK_OPTION6
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU7
	movlw	EEPROM6		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value

; different code because of digital display the "l-13dB' for example stops at VU6
VU7
	movf	VU_LEFT_MS,w	; VU input left channel ms byte
	subwf	VALUE_A_D_7_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	VU_LEFT_LS,w	; VU input left channel ls byte	
	subwf	VALUE_A_D_7_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV7		; drive block
	btfsc	TEMP_X,7
	goto	DRV7		; drive block
; check peak value	
	goto	PEAK_7		; not at VU level
DRV7
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_7	
	movlw	H'FF'		; block
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	movlw	EEPROM7		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value
	goto	VU8

PEAK_7
; Peak left channel (if digital reserve space and drive at end) 
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_7_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_7_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK7		; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK7		; drive peak 
; check peak value
SPACE_L7
	bcf		PCLATH,3	; page 0
	call	SPACE1	
	bsf		PCLATH,3	; page 1
	goto	VU8 
DRV_PK7	
	btfsc	OPTIONS,1		; if not peak then next block
	goto	SPACE_L7
; only drive peak if next peak location is off
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_8_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_8_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	SPACE_L7
	btfsc	TEMP_X,7
	goto	SPACE_L7
; end next test
	movlw	H'00'		; peak
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU8
	movlw	EEPROM7		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value

VU8
	movf	VU_LEFT_MS,w	; VU input left channel ms byte
	subwf	VALUE_A_D_8_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	VU_LEFT_LS,w	; VU input left channel ls byte	
	subwf	VALUE_A_D_8_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV8		; drive block
	btfsc	TEMP_X,7
	goto	DRV8		; drive block
; check peak value	
	goto	PEAK_8		; not at VU level
DRV8
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_8	
	movlw	H'FF'		; block
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	movlw	EEPROM8		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value
	goto	VU9

PEAK_8
; Peak left channel (if digital reserve space and drive at end) 
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_8_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_8_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK8		; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK8		; drive peak 
; check peak value
SPACE_L8
	bcf		PCLATH,3	; page 0
	call	SPACE1	
	bsf		PCLATH,3	; page 1
	goto	VU9 
DRV_PK8	
	btfsc	OPTIONS,1		; if not peak then next block
	goto	SPACE_L8
; only drive peak if next peak location is off
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_9_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_9_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	SPACE_L8
	btfsc	TEMP_X,7
	goto	SPACE_L8
; end next test
	movlw	H'00'		; peak
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU9
	movlw	EEPROM8		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value

VU9
	movf	VU_LEFT_MS,w	; VU input left channel ms byte
	subwf	VALUE_A_D_9_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	VU_LEFT_LS,w	; VU input left channel ls byte	
	subwf	VALUE_A_D_9_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV9		; drive block
	btfsc	TEMP_X,7
	goto	DRV9		; drive block
; check peak value	
	goto	PEAK_9		; not at VU level
DRV9
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_9	
	movlw	H'FF'		; block
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	movlw	EEPROM9		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value
	goto	VU10

PEAK_9
; Peak left channel (if digital reserve space and drive at end) 
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_9_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_9_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK9		; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK9		; drive peak 
; check peak value
SPACE_L9
	bcf		PCLATH,3	; page 0
	call	SPACE1
	bsf		PCLATH,3	; page 1
	goto	VU10 
DRV_PK9	
	btfsc	OPTIONS,1		; if not peak then next block
	goto	SPACE_L9
; only drive peak if next peak location is off
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_10_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_10_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	SPACE_L9
	btfsc	TEMP_X,7
	goto	SPACE_L9
; end next test
	movlw	H'00'		; peak
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU10
	movlw	EEPROM9		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value

VU10
	movf	VU_LEFT_MS,w	; VU input left channel ms byte
	subwf	VALUE_A_D_10_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	VU_LEFT_LS,w	; VU input left channel ls byte	
	subwf	VALUE_A_D_10_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV10		; drive block
	btfsc	TEMP_X,7
	goto	DRV10		; drive block
; check peak value	
	goto	PEAK_10		; not at VU level
DRV10
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_10	
	movlw	H'FF'		; block
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	movlw	EEPROM10		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value
	goto	VU11

PEAK_10
; Peak left channel (if digital reserve space and drive at end) 
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_10_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_10_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK10		; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK10		; drive peak 
; check peak value
SPACE_L10
	bcf		PCLATH,3	; page 0
	call	SPACE1	
	bsf		PCLATH,3	; page 1
	goto	VU11 
DRV_PK10	
	btfsc	OPTIONS,1		; if not peak then next block
	goto	SPACE_L10
; only drive peak if next peak location is off
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_11_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_11_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	SPACE_L10
	btfsc	TEMP_X,7
	goto	SPACE_L10
; end next test
	movlw	H'00'		; peak
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU11
	movlw	EEPROM10		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value

VU11
	movf	VU_LEFT_MS,w	; VU input left channel ms byte
	subwf	VALUE_A_D_11_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	VU_LEFT_LS,w	; VU input left channel ls byte	
	subwf	VALUE_A_D_11_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV11		; drive block
	btfsc	TEMP_X,7
	goto	DRV11		; drive block
; check peak value	
	goto	PEAK_11		; not at VU level
DRV11
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_11	
	movlw	H'FF'		; block
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	movlw	EEPROM11		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value
	goto	VU12

PEAK_11
; Peak left channel (if digital reserve space and drive at end) 
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_11_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_11_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK11		; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK11		; drive peak 
; check peak value
SPACE_L11
	bcf		PCLATH,3	; page 0
	call	SPACE1	
	bsf		PCLATH,3	; page 1
	goto	VU12 
DRV_PK11	
	btfsc	OPTIONS,1		; if not peak then next block
	goto	SPACE_L11
; only drive peak if next peak location is off
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_12_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_12_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	SPACE_L11
	btfsc	TEMP_X,7
	goto	SPACE_L11
; end next test
	movlw	H'00'		; peak
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU12
	movlw	EEPROM11		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value

VU12
	movf	VU_LEFT_MS,w	; VU input left channel ms byte
	subwf	VALUE_A_D_12_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	VU_LEFT_LS,w	; VU input left channel ls byte	
	subwf	VALUE_A_D_12_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV12		; drive block
	btfsc	TEMP_X,7
	goto	DRV12		; drive block
; check peak value	
	goto	PEAK_12		; not at VU level
DRV12
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_12	
	movlw	H'FF'		; block
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	movlw	EEPROM12		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value
	goto	VU13

PEAK_12
; Peak left channel (if digital reserve space and drive at end) 
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_12_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_12_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK12		; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK12		; drive peak 
; check peak value
SPACE_L12
	bcf		PCLATH,3	; page 0
	call	SPACE1
	bsf		PCLATH,3	; page 1
	goto	VU13 
DRV_PK12	
	btfsc	OPTIONS,1		; if not peak then next block
	goto	SPACE_L12
; only drive peak if next peak location is off
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_13_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_13_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	SPACE_L12
	btfsc	TEMP_X,7
	goto	SPACE_L12
; end next test
	movlw	H'00'		; peak
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU13
	movlw	EEPROM12		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value

VU13
	movf	VU_LEFT_MS,w	; VU input left channel ms byte
	subwf	VALUE_A_D_13_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	VU_LEFT_LS,w	; VU input left channel ls byte	
	subwf	VALUE_A_D_13_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV13		; drive block
	btfsc	TEMP_X,7
	goto	DRV13		; drive block
; check peak value	
	goto	PEAK_13		; not at VU level
DRV13
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_13	
	movlw	H'FF'		; block
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	movlw	EEPROM13		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value
	goto	VU14

PEAK_13
; Peak left channel (if digital reserve space and drive at end) 
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_13_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_13_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK13		; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK13		; drive peak 
; check peak value
SPACE_L13
	bcf		PCLATH,3	; page 0
	call	SPACE1
	bsf		PCLATH,3	; page 1
	goto	VU14 
DRV_PK13	
	btfsc	OPTIONS,1		; if not peak then next block
	goto	SPACE_L13
; only drive peak if next peak location is off
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_14_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_14_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	SPACE_L13
	btfsc	TEMP_X,7
	goto	SPACE_L13
; end next test
	movlw	H'00'		; peak
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU14
	movlw	EEPROM13		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value

VU14
	movf	VU_LEFT_MS,w	; VU input left channel ms byte
	subwf	VALUE_A_D_14_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	VU_LEFT_LS,w	; VU input left channel ls byte	
	subwf	VALUE_A_D_14_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV14		; drive block
	btfsc	TEMP_X,7
	goto	DRV14		; drive block
; check peak value	
	goto	PEAK_14		; not at VU level
DRV14
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_14	
	movlw	H'FF'		; block
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	movlw	EEPROM14		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value
	goto	VU15

PEAK_14
; Peak left channel (if digital reserve space and drive at end) 
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_14_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_14_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK14		; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK14		; drive peak 
; check peak value
SPACE_L14
	bcf		PCLATH,3	; page 0
	call	SPACE1
	bsf		PCLATH,3	; page 1
	goto	VU15 
DRV_PK14	
	btfsc	OPTIONS,1		; if not peak then next block
	goto	SPACE_L14
; only drive peak if next peak location is off
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_15_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_15_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	SPACE_L14
	btfsc	TEMP_X,7
	goto	SPACE_L14
; end next test
	movlw	H'00'		; peak
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU15
	movlw	EEPROM14		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value

VU15
	movf	VU_LEFT_MS,w	; VU input left channel ms byte
	subwf	VALUE_A_D_15_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	VU_LEFT_LS,w	; VU input left channel ls byte	
	subwf	VALUE_A_D_15_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV15		; drive block
	btfsc	TEMP_X,7
	goto	DRV15		; drive block
; check peak value	
	goto	PEAK_15		; not at VU level
DRV15
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_15	
	movlw	H'FF'		; block
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	movlw	EEPROM15		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value
	goto	VU16

PEAK_15
; Peak left channel (if digital reserve space and drive at end) 
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_15_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_15_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK15		; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK15		; drive peak 
; check peak value
SPACE_L15
	bcf		PCLATH,3	; page 0
	call	SPACE1
	bsf		PCLATH,3	; page 1
	goto	VU16 
DRV_PK15	
	btfsc	OPTIONS,1		; if not peak then next block
	goto	SPACE_L15
; only drive peak if next peak location is off
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_16_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_16_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	SPACE_L15
	btfsc	TEMP_X,7
	goto	SPACE_L15
; end next test
	movlw	H'00'		; peak
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU16
	movlw	EEPROM15		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value

VU16
	movf	VU_LEFT_MS,w	; VU input left channel ms byte
	subwf	VALUE_A_D_16_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	VU_LEFT_LS,w	; VU input left channel ls byte	
	subwf	VALUE_A_D_16_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV16		; drive block
	btfsc	TEMP_X,7
	goto	DRV16		; drive block
; check peak value	
	goto	PEAK_16		; not at VU level
DRV16
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_16	
	movlw	H'FF'		; block
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	movlw	EEPROM16		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value
	goto	VU_RIGHT

PEAK_16
; Peak left channel (if digital reserve space and drive at end) 
	movf	PEAK_LEFT_MS,w	; peak input left channel ms byte
	subwf	VALUE_A_D_16_M,w	; high byte of left hand bar value
	movwf	TEMP_X
	movf	PEAK_LEFT_LS,w	; peak input left channel ls byte	
	subwf	VALUE_A_D_16_L,w	; low byte of left hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK16		; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK16		; drive peak 
; check peak value
SPACE_L16
	bcf		PCLATH,3	; page 0
	call	SPACE1	
	bsf		PCLATH,3	; page 1
	goto	VU_RIGHT
DRV_PK16	
	btfsc	OPTIONS,1		; if not peak then next block
	goto	SPACE_L16
	movlw	H'00'		; peak
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU_RIGHT
	movlw	EEPROM16		; block location value
	call	EREAD
	movwf	DIGITAL_L	; update digital value
; End of left bargraph driving

VU_RIGHT

; Right channel	
	movlw	H'7F'
	movwf	DIGITAL_R	; digital value to max so it shows no value
	movlw	H'C0'		; line 2 position 1
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1

; VU Right channel (if digital reserve space and drive at end) 
VU1_R	
	movlw	A'R'		; Right channel
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1

	movf	VU_RIGHT_MS,w	; VU input right channel ms byte
	subwf	VALUE_A_D_1_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	VU_RIGHT_LS,w	; VU input right channel ls byte	
	subwf	VALUE_A_D_1_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV1_R		; drive block
	btfsc	TEMP_X,7
	goto	DRV1_R		; drive block
; check peak value	
	goto	PEAK_1_R	; not at VU level
DRV1_R
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_1_R	
	btfss	OPTIONS,2 	; if options are for digital display load value to DIGITAL_R
	goto	VU2_R
	movlw	EEPROM1		; block location value
	call	EREAD
	movwf	DIGITAL_R	; update digital value
	goto	VU2_R
	
PEAK_1_R
; Peak right channel (if digital reserve space and drive at end) 
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_1_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_1_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK1_R	; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK1_R	; drive peak 
; check peak value
	btfsc	OPTIONS,2	; if digital display
	goto	VU2_R
	bcf		PCLATH,3	; page 0
	call	SPACE1	
	bsf		PCLATH,3	; page 1
	goto	VU2_R 
DRV_PK1_R	
	btfss	OPTIONS,1	; if peak then ck option
	goto	CK_OPTION1_R
	goto	VU2_R

CK_OPTION1_R
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU2_R
	movlw	EEPROM1		; block location value
	call	EREAD
	movwf	DIGITAL_R	; update digital value
	
; VU right channel (if digital reserve space and drive at end) 
VU2_R	
	movf	VU_RIGHT_MS,w	; VU input right channel ms byte
	subwf	VALUE_A_D_2_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	VU_RIGHT_LS,w	; VU input right channel ls byte	
	subwf	VALUE_A_D_2_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV2_R		; drive block
	btfsc	TEMP_X,7
	goto	DRV2_R		; drive block
; check peak value	
	goto	PEAK_2_R	; not at VU level
DRV2_R
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_2_R	
	btfsc	OPTIONS,2 	; if options are for digital display move to next block
	goto	NXT_BLOCK2_R
	movlw	H'FF'		; block
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	goto	VU3_R
LD_EEP2_R
	movlw	EEPROM2		; block location value
	call	EREAD
	movwf	DIGITAL_R	; update digital value
	goto	VU3_R
NXT_BLOCK2_R
	movlw	H'C2'		; next block position
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1
	goto	LD_EEP2_R
PEAK_2_R
; Peak right channel (if digital reserve space and drive at end) 
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_2_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_2_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK2_R	; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK2_R	; drive peak 
; check peak value
	btfsc	OPTIONS,2	; if digital display
	goto	NXT_BLOCK_PK2_R
SPACE_L2_R
	bcf		PCLATH,3	; page 0
	call	SPACE1	
	bsf		PCLATH,3	; page 1
	goto	VU3_R 
NXT_BLOCK_PK2_R
	movlw	H'C2'
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1
	goto	VU3_R
DRV_PK2_R	
	btfsc	OPTIONS,1	; if not peak then next block
	goto	NXT_BLOCK_PK2_R
	btfsc	OPTIONS,2 	; if options are for digital display leave blank
	goto	NXT_PK_BLOCK2_R
; only drive peak if next peak location is off
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_3_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_3_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	SPACE_L2_R
	btfsc	TEMP_X,7
	goto	SPACE_L2_R
; end next test
	movlw	H'00'		; peak
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	goto	VU3_R
NXT_PK_BLOCK2_R
	movlw	H'C2'
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1
CK_OPTION2_R
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU3_R
	movlw	EEPROM2		; block location value
	call	EREAD
	movwf	DIGITAL_R	; update digital value
	
VU3_R
	movf	VU_RIGHT_MS,w	; VU input right channel ms byte
	subwf	VALUE_A_D_3_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	VU_RIGHT_LS,w	; VU input right channel ls byte	
	subwf	VALUE_A_D_3_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV3_R		; drive block
	btfsc	TEMP_X,7
	goto	DRV3_R		; drive block
; check peak value	
	goto	PEAK_3_R		; not at VU level
DRV3_R
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_3_R	
	btfsc	OPTIONS,2 	; if options are for digital display move to next block
	goto	NXT_BLOCK3_R
	movlw	H'FF'		; block
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	goto	VU4_R
LD_EEP3_R
	movlw	EEPROM3		; block location value
	call	EREAD
	movwf	DIGITAL_R	; update digital value
	goto	VU4_R
NXT_BLOCK3_R
	movlw	H'C3'		; next block position
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1
	goto	LD_EEP3_R
PEAK_3_R
; Peak right channel (if digital reserve space and drive at end) 
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_3_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_3_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK3_R	; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK3_R	; drive peak 
; check peak value
	btfsc	OPTIONS,2	; if digital display
	goto	NXT_BLOCK_PK3_R
SPACE_L3_R
	bcf		PCLATH,3	; page 0
	call	SPACE1
	bsf		PCLATH,3	; page 1
	goto	VU4_R 
NXT_BLOCK_PK3_R
	movlw	H'C3'
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1
	goto	VU4_R
DRV_PK3_R	
	btfsc	OPTIONS,1	; if not peak then next block
	goto	NXT_BLOCK_PK3_R
	btfsc	OPTIONS,2 	; if options are for digital display leave blank
	goto	NXT_PK_BLOCK3_R
; only drive peak if next peak location is off
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_4_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_4_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	SPACE_L3_R
	btfsc	TEMP_X,7
	goto	SPACE_L3_R
; end next test
	movlw	H'00'		; peak
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	goto	VU4_R
NXT_PK_BLOCK3_R
	movlw	H'C3'
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1

CK_OPTION3_R
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU4_R
	movlw	EEPROM3		; block location value
	call	EREAD
	movwf	DIGITAL_R	; update digital value

VU4_R
	movf	VU_RIGHT_MS,w	; VU input right channel ms byte
	subwf	VALUE_A_D_4_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	VU_RIGHT_LS,w	; VU input right channel ls byte	
	subwf	VALUE_A_D_4_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV4_R		; drive block
	btfsc	TEMP_X,7
	goto	DRV4_R		; drive block
; check peak value	
	goto	PEAK_4_R	; not at VU level
DRV4_R
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_4_R	
	btfsc	OPTIONS,2 	; if options are for digital display move to next block
	goto	NXT_BLOCK4_R
	movlw	H'FF'		; block
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	goto	VU5_R
LD_EEP4_R
	movlw	EEPROM4		; block location value
	call	EREAD
	movwf	DIGITAL_R	; update digital value
	goto	VU5_R
NXT_BLOCK4_R
	movlw	H'C4'		; next block position
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1
	goto	LD_EEP4_R
PEAK_4_R
; Peak right channel (if digital reserve space and drive at end) 
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_4_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_4_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK4_R	; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK4_R	; drive peak 
; check peak value
	btfsc	OPTIONS,2	; if digital display
	goto	NXT_BLOCK_PK4_R
SPACE_L4_R
	bcf		PCLATH,3	; page 0
	call	SPACE1
	bsf		PCLATH,3	; page 1
	goto	VU5_R 
NXT_BLOCK_PK4_R
	movlw	H'C4'
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1
	goto	VU5_R
DRV_PK4_R	
	btfsc	OPTIONS,1	; if not peak then next block
	goto	NXT_BLOCK_PK4_R
	btfsc	OPTIONS,2 	; if options are for digital display leave blank
	goto	NXT_PK_BLOCK4_R
; only drive peak if next peak location is off
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_5_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_5_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	SPACE_L4_R
	btfsc	TEMP_X,7
	goto	SPACE_L4_R
; end next test
	movlw	H'00'		; peak
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	goto	VU5_R
NXT_PK_BLOCK4_R
	movlw	H'C4'
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1
CK_OPTION4_R
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU5_R
	movlw	EEPROM4		; block location value
	call	EREAD
	movwf	DIGITAL_R	; update digital value

VU5_R
	movf	VU_RIGHT_MS,w	; VU input right channel ms byte
	subwf	VALUE_A_D_5_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	VU_RIGHT_LS,w	; VU input right channel ls byte	
	subwf	VALUE_A_D_5_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV5_R		; drive block
	btfsc	TEMP_X,7
	goto	DRV5_R		; drive block
; check peak value	
	goto	PEAK_5_R	; not at VU level
DRV5_R
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_5_R	
	btfsc	OPTIONS,2 	; if options are for digital display move to next block
	goto	NXT_BLOCK5_R
	movlw	H'FF'		; block
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	goto	VU6_R
LD_EEP5_R
	movlw	EEPROM5		; block location value
	call	EREAD
	movwf	DIGITAL_R	; update digital value
	goto	VU6_R
NXT_BLOCK5_R
	movlw	H'C5'		; next block position
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1
	goto	LD_EEP5_R
PEAK_5_R
; Peak right channel (if digital reserve space and drive at end) 
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_5_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_5_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK5_R	; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK5_R	; drive peak 
; check peak value
	btfsc	OPTIONS,2	; if digital display
	goto	NXT_BLOCK_PK5_R
SPACE_L5_R
	bcf		PCLATH,3	; page 0
	call	SPACE1
	bsf		PCLATH,3	; page 1
	goto	VU6_R 
NXT_BLOCK_PK5_R
	movlw	H'C5'
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1
	goto	VU6_R
DRV_PK5_R	
	btfsc	OPTIONS,1	; if not peak then next block
	goto	NXT_BLOCK_PK5_R
	btfsc	OPTIONS,2 	; if options are for digital display leave blank
	goto	NXT_PK_BLOCK5_R
; only drive peak if next peak location is off
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_6_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_6_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	SPACE_L5_R
	btfsc	TEMP_X,7
	goto	SPACE_L5_R
; end next test
	movlw	H'00'		; peak
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	goto	VU6_R
NXT_PK_BLOCK5_R
	movlw	H'C5'
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1
CK_OPTION5_R
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU6_R
	movlw	EEPROM5		; block location value
	call	EREAD
	movwf	DIGITAL_R	; update digital value

VU6_R
	movf	VU_RIGHT_MS,w	; VU input right channel ms byte
	subwf	VALUE_A_D_6_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	VU_RIGHT_LS,w	; VU input right channel ls byte	
	subwf	VALUE_A_D_6_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV6_R		; drive block
	btfsc	TEMP_X,7
	goto	DRV6_R		; drive block
; check peak value	
	goto	PEAK_6_R		; not at VU level
DRV6_R
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_6_R	
	btfsc	OPTIONS,2 	; if options are for digital display move to next block
	goto	NXT_BLOCK6_R
	movlw	H'FF'		; block
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	goto	VU7_R
LD_EEP6_R
	movlw	EEPROM6		; block location value
	call	EREAD
	movwf	DIGITAL_R	; update digital value
	goto	VU7_R
NXT_BLOCK6_R
	movlw	H'C6'		; next block position
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1
	goto	LD_EEP6_R
PEAK_6_R
; Peak right channel (if digital reserve space and drive at end) 
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_6_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_6_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK6_R	; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK6_R	; drive peak 
; check peak value
	btfsc	OPTIONS,2	; if digital display
	goto	NXT_BLOCK_PK6_R
SPACE_L6_R
	bcf		PCLATH,3	; page 0
	call	SPACE1
	bsf		PCLATH,3	; page 1
	goto	VU7_R 
NXT_BLOCK_PK6_R
	movlw	H'C6'
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1
	goto	VU7_R
DRV_PK6_R	
	btfsc	OPTIONS,1	; if not peak then next block
	goto	NXT_BLOCK_PK6_R
	btfsc	OPTIONS,2 	; if options are for digital display leave blank
	goto	NXT_PK_BLOCK6_R
; only drive peak if next peak location is off
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_7_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_7_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	SPACE_L6_R
	btfsc	TEMP_X,7
	goto	SPACE_L6_R
; end next test
	movlw	H'00'		; peak
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	goto	VU7_R
NXT_PK_BLOCK6_R
	movlw	H'C6'
	bcf		PCLATH,3	; page 0
	call	LOAD
	bsf		PCLATH,3	; page 1
CK_OPTION6_R
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU7_R
	movlw	EEPROM6		; block location value
	call	EREAD
	movwf	DIGITAL_R	; update digital value

; different code because of digital display the "l-13dB' for example stops at VU6
VU7_R
	movf	VU_RIGHT_MS,w	; VU input right channel ms byte
	subwf	VALUE_A_D_7_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	VU_RIGHT_LS,w	; VU input right channel ls byte	
	subwf	VALUE_A_D_7_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV7_R		; drive block
	btfsc	TEMP_X,7
	goto	DRV7_R		; drive block
; check peak value	
	goto	PEAK_7_R		; not at VU level
DRV7_R
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_7_R	
	movlw	H'FF'		; block
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	movlw	EEPROM7		; block location value
	call	EREAD
	movwf	DIGITAL_R	; update digital value
	goto	VU8_R

PEAK_7_R
; Peak right channel (if digital reserve space and drive at end) 
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_7_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_7_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK7_R	; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK7_R	; drive peak 
; check peak value
SPACE_L7_R
	bcf		PCLATH,3	; page 0
	call	SPACE1	
	bsf		PCLATH,3	; page 1
	goto	VU8_R 
DRV_PK7_R	
	btfsc	OPTIONS,1		; if not peak then next block
	goto	SPACE_L7_R
; only drive peak if next peak location is off
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_8_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_8_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	SPACE_L7_R
	btfsc	TEMP_X,7
	goto	SPACE_L7_R
; end next test
	movlw	H'00'		; peak
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU8_R
	movlw	EEPROM7		; block location value
	call	EREAD
	movwf	DIGITAL_R	; update digital value

VU8_R
	movf	VU_RIGHT_MS,w	; VU input right channel ms byte
	subwf	VALUE_A_D_8_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	VU_RIGHT_LS,w	; VU input right channel ls byte	
	subwf	VALUE_A_D_8_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV8_R		; drive block
	btfsc	TEMP_X,7
	goto	DRV8_R		; drive block
; check peak value	
	goto	PEAK_8_R	; not at VU level
DRV8_R
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_8_R	
	movlw	H'FF'		; block
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	movlw	EEPROM8		; block location value
	call	EREAD
	movwf	DIGITAL_R	; update digital value
	goto	VU9_R

PEAK_8_R
; Peak right channel (if digital reserve space and drive at end) 
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_8_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_8_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK8_R	; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK8_R	; drive peak 
; check peak value
SPACE_L8_R
	bcf		PCLATH,3	; page 0
	call	SPACE1	
	bsf		PCLATH,3	; page 1
	goto	VU9_R 
DRV_PK8_R	
	btfsc	OPTIONS,1		; if not peak then next block
	goto	SPACE_L8_R
; only drive peak if next peak location is off
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_9_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_9_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	SPACE_L8_R
	btfsc	TEMP_X,7
	goto	SPACE_L8_R
; end next test
	movlw	H'00'		; peak
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU9_R
	movlw	EEPROM8		; block location value
	call	EREAD
	movwf	DIGITAL_R	; update digital value

VU9_R
	movf	VU_RIGHT_MS,w	; VU input right channel ms byte
	subwf	VALUE_A_D_9_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	VU_RIGHT_LS,w	; VU input right channel ls byte	
	subwf	VALUE_A_D_9_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV9_R		; drive block
	btfsc	TEMP_X,7
	goto	DRV9_R		; drive block
; check peak value	
	goto	PEAK_9_R	; not at VU level
DRV9_R
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_9_R	
	movlw	H'FF'		; block
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	movlw	EEPROM9		; block location value
	call	EREAD
	movwf	DIGITAL_R	; update digital value
	goto	VU10_R

PEAK_9_R
; Peak right channel (if digital reserve space and drive at end) 
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_9_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_9_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK9_R	; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK9_R	; drive peak 
; check peak value
SPACE_L9_R
	bcf		PCLATH,3	; page 0
	call	SPACE1
	bsf		PCLATH,3	; page 1
	goto	VU10_R 
DRV_PK9_R	
	btfsc	OPTIONS,1		; if not peak then next block
	goto	SPACE_L9_R
; only drive peak if next peak location is off
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_10_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_10_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	SPACE_L9_R
	btfsc	TEMP_X,7
	goto	SPACE_L9_R
; end next test
	movlw	H'00'		; peak
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU10_R
	movlw	EEPROM9		; block location value
	call	EREAD
	movwf	DIGITAL_R	; update digital value

VU10_R
	movf	VU_RIGHT_MS,w	; VU input right channel ms byte
	subwf	VALUE_A_D_10_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	VU_RIGHT_LS,w	; VU input right channel ls byte	
	subwf	VALUE_A_D_10_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV10_R		; drive block
	btfsc	TEMP_X,7
	goto	DRV10_R		; drive block
; check peak value	
	goto	PEAK_10_R		; not at VU level
DRV10_R
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_10_R	
	movlw	H'FF'		; block
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	movlw	EEPROM10		; block location value
	call	EREAD
	movwf	DIGITAL_R	; update digital value
	goto	VU11_R

PEAK_10_R
; Peak right channel (if digital reserve space and drive at end) 
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_10_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_10_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK10_R	; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK10_R	; drive peak 
; check peak value
SPACE_L10_R
	bcf		PCLATH,3	; page 0
	call	SPACE1	
	bsf		PCLATH,3	; page 1
	goto	VU11_R 
DRV_PK10_R	
	btfsc	OPTIONS,1		; if not peak then next block
	goto	SPACE_L10_R
; only drive peak if next peak location is off
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_11_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_11_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	SPACE_L10_R
	btfsc	TEMP_X,7
	goto	SPACE_L10_R
; end next test
	movlw	H'00'		; peak
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU11_R
	movlw	EEPROM10	; block location value
	call	EREAD
	movwf	DIGITAL_R	; update digital value

VU11_R
	movf	VU_RIGHT_MS,w	; VU input right channel ms byte
	subwf	VALUE_A_D_11_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	VU_RIGHT_LS,w	; VU input right channel ls byte	
	subwf	VALUE_A_D_11_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV11_R		; drive block
	btfsc	TEMP_X,7
	goto	DRV11_R		; drive block
; check peak value	
	goto	PEAK_11_R	; not at VU level
DRV11_R
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_11_R	
	movlw	H'FF'		; block
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	movlw	EEPROM11		; block location value
	call	EREAD
	movwf	DIGITAL_R	; update digital value
	goto	VU12_R

PEAK_11_R
; Peak right channel (if digital reserve space and drive at end) 
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_11_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_11_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK11_R		; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK11_R		; drive peak 
; check peak value
SPACE_L11_R
	bcf		PCLATH,3	; page 0
	call	SPACE1	
	bsf		PCLATH,3	; page 1
	goto	VU12_R 
DRV_PK11_R	
	btfsc	OPTIONS,1		; if not peak then next block
	goto	SPACE_L11_R
; only drive peak if next peak location is off
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_12_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_12_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	SPACE_L11_R
	btfsc	TEMP_X,7
	goto	SPACE_L11_R
; end next test
	movlw	H'00'		; peak
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU12_R
	movlw	EEPROM11		; block location value
	call	EREAD
	movwf	DIGITAL_R	; update digital value

VU12_R
	movf	VU_RIGHT_MS,w	; VU input right channel ms byte
	subwf	VALUE_A_D_12_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	VU_RIGHT_LS,w	; VU input right channel ls byte	
	subwf	VALUE_A_D_12_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV12_R		; drive block
	btfsc	TEMP_X,7
	goto	DRV12_R		; drive block
; check peak value	
	goto	PEAK_12_R	; not at VU level
DRV12_R
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_12_R	
	movlw	H'FF'		; block
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	movlw	EEPROM12		; block location value
	call	EREAD
	movwf	DIGITAL_R	; update digital value
	goto	VU13_R

PEAK_12_R
; Peak right channel (if digital reserve space and drive at end) 
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_12_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_12_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK12_R		; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK12_R		; drive peak 
; check peak value
SPACE_L12_R
	bcf		PCLATH,3	; page 0
	call	SPACE1
	bsf		PCLATH,3	; page 1
	goto	VU13_R 
DRV_PK12_R	
	btfsc	OPTIONS,1		; if not peak then next block
	goto	SPACE_L12_R
; only drive peak if next peak location is off
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_13_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_13_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	SPACE_L12_R
	btfsc	TEMP_X,7
	goto	SPACE_L12_R
; end next test
	movlw	H'00'		; peak
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU13_R
	movlw	EEPROM12	; block location value
	call	EREAD
	movwf	DIGITAL_R	; update digital value

VU13_R
	movf	VU_RIGHT_MS,w	; VU input right channel ms byte
	subwf	VALUE_A_D_13_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	VU_RIGHT_LS,w	; VU input right channel ls byte	
	subwf	VALUE_A_D_13_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV13_R		; drive block
	btfsc	TEMP_X,7
	goto	DRV13_R		; drive block
; check peak value	
	goto	PEAK_13_R		; not at VU level
DRV13_R
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_13_R	
	movlw	H'FF'		; block
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	movlw	EEPROM13		; block location value
	call	EREAD
	movwf	DIGITAL_R	; update digital value
	goto	VU14_R

PEAK_13_R
; Peak right channel (if digital reserve space and drive at end) 
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_13_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_13_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK13_R	; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK13_R	; drive peak 
; check peak value
SPACE_L13_R
	bcf		PCLATH,3	; page 0
	call	SPACE1
	bsf		PCLATH,3	; page 1
	goto	VU14_R 
DRV_PK13_R	
	btfsc	OPTIONS,1		; if not peak then next block
	goto	SPACE_L13_R
; only drive peak if next peak location is off
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_14_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_14_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	SPACE_L13_R
	btfsc	TEMP_X,7
	goto	SPACE_L13_R
; end next test
	movlw	H'00'		; peak
	bcf		PCLATH,3	; page 0
	call	DRV_LCD
	bsf		PCLATH,3	; page 1
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU14_R
	movlw	EEPROM13		; block location value
	call	EREAD
	movwf	DIGITAL_R	; update digital value

VU14_R
	bcf		PCLATH,3	; page 0
	goto	VU14_R_CONTINUE	

; EEREAD routine in page 1
EREAD
	bcf		STATUS,RP1	; select bank 0
	bsf 	STATUS,RP1	; select memory bank 2
	movwf 	EEADR		; indirect special function register
	bsf 	STATUS,RP0	; select memory bank 3
	bcf		EECON1,EEPGD; data memory
	bsf		EECON1,RD	; read EEPROM
	bcf 	STATUS,RP0	; select memory bank 2
	movf	EEDATA,w	; EEPROM value in w
	bcf		STATUS,RP1	; select bank 0
	return

	org H'0500'
VU14_R_CONTINUE	

	movf	VU_RIGHT_MS,w	; VU input right channel ms byte
	subwf	VALUE_A_D_14_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	VU_RIGHT_LS,w	; VU input right channel ls byte	
	subwf	VALUE_A_D_14_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV14_R		; drive block
	btfsc	TEMP_X,7
	goto	DRV14_R		; drive block
; check peak value	
	goto	PEAK_14_R		; not at VU level
DRV14_R
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_14_R	
	movlw	H'FF'		; block
	call	DRV_LCD
	movlw	EEPROM14		; block location value
	call	EEREAD
	movwf	DIGITAL_R	; update digital value
	goto	VU15_R

PEAK_14_R
; Peak right channel (if digital reserve space and drive at end) 
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_14_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_14_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK14_R	; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK14_R	; drive peak 
; check peak value
SPACE_L14_R
	call	SPACE1
	goto	VU15_R 
DRV_PK14_R	
	btfsc	OPTIONS,1		; if not peak then next block
	goto	SPACE_L14_R
; only drive peak if next peak location is off
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_15_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_15_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	SPACE_L14_R
	btfsc	TEMP_X,7
	goto	SPACE_L14_R
; end next test
	movlw	H'00'		; peak
	call	DRV_LCD
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU15_R
	movlw	EEPROM14		; block location value
	call	EEREAD
	movwf	DIGITAL_R	; update digital value

VU15_R
	movf	VU_RIGHT_MS,w	; VU input right channel ms byte
	subwf	VALUE_A_D_15_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	VU_RIGHT_LS,w	; VU input right channel ls byte	
	subwf	VALUE_A_D_15_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV15_R		; drive block
	btfsc	TEMP_X,7
	goto	DRV15_R		; drive block
; check peak value	
	goto	PEAK_15_R		; not at VU level
DRV15_R
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_15_R	
	movlw	H'FF'		; block
	call	DRV_LCD
	movlw	EEPROM15		; block location value
	call	EEREAD
	movwf	DIGITAL_R	; update digital value
	goto	VU16_R

PEAK_15_R
; Peak right channel (if digital reserve space and drive at end) 
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_15_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_15_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK15_R	; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK15_R	; drive peak 
; check peak value
SPACE_L15_R
	call	SPACE1
	goto	VU16_R 
DRV_PK15_R	
	btfsc	OPTIONS,1		; if not peak then next block
	goto	SPACE_L15_R
; only drive peak if next peak location is off
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_16_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_16_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	SPACE_L15_R
	btfsc	TEMP_X,7
	goto	SPACE_L15_R
; end next test
	movlw	H'00'		; peak
	call	DRV_LCD
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU16_R
	movlw	EEPROM15		; block location value
	call	EEREAD
	movwf	DIGITAL_R	; update digital value

VU16_R
	movf	VU_RIGHT_MS,w	; VU input right channel ms byte
	subwf	VALUE_A_D_16_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	VU_RIGHT_LS,w	; VU input right channel ls byte	
	subwf	VALUE_A_D_16_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV16_R		; drive block
	btfsc	TEMP_X,7
	goto	DRV16_R		; drive block
; check peak value	
	goto	PEAK_16_R		; not at VU level
DRV16_R
	btfsc	OPTIONS,0	; if VU off then use peak value for reading
	goto	PEAK_16_R	
	movlw	H'FF'		; block
	call	DRV_LCD
	movlw	EEPROM16		; block location value
	call	EEREAD
	movwf	DIGITAL_R	; update digital value
	goto	VU_LEFT_DIGITAL

PEAK_16_R
; Peak right channel (if digital reserve space and drive at end) 
	movf	PEAK_RIGHT_MS,w	; peak input right channel ms byte
	subwf	VALUE_A_D_16_M,w	; high byte of right hand bar value
	movwf	TEMP_X
	movf	PEAK_RIGHT_LS,w	; peak input right channel ls byte	
	subwf	VALUE_A_D_16_L,w	; low byte of right hand bar value
	btfss	STATUS,C
	decf	TEMP_X,f
	iorwf	TEMP_X,w	; equal to zero
	btfsc	STATUS,Z
	goto	DRV_PK16_R		; drive block
	btfsc	TEMP_X,7
	goto	DRV_PK16_R		; drive peak 
; check peak value
SPACE_R16_R
	call	SPACE1	
	goto	VU_LEFT_DIGITAL
DRV_PK16_R	
	btfsc	OPTIONS,1		; if not peak then next block
	goto	SPACE_R16_R
	movlw	H'00'		; peak
	call	DRV_LCD
	btfss	OPTIONS,0 	; if VU off then use peak value for reading
	goto	VU_LEFT_DIGITAL
	movlw	EEPROM16		; block location value
	call	EEREAD
	movwf	DIGITAL_R	; update digital value
; End of right bargraph driving

; Display digital value if set
	
VU_LEFT_DIGITAL

; display rate
	clrf	DISP_FLG		; display flag
	movf	DIGITAL_RATE,w
	btfsc	STATUS,Z		; when zero update
	goto	DIG_UPDATE	
	decf	DIGITAL_RATE,f	; decrease
	goto	RECLAIM
DIG_UPDATE	
	movlw	D'01'
	movwf	DIGITAL_RATE	; digital rate

	btfss	OPTIONS,2	; when set digital value
	goto	RECLAIM		; 
	movlw	H'81'		; line 1 position 2
	call	LOAD
	movf	DIGITAL_L,w	; left digital value
	xorlw	H'7F'		; if no preloaded value
	btfsc	STATUS,Z	; 
	goto	TWO_SPACE_L	; blank instead of value
	movf	DIGITAL_L,w	; if zero no sign
	btfsc	STATUS,Z
	goto	NO_SIGN_L
	btfsc	DIGITAL_L,7	; when clear - sign
	goto	PLUS_DIGITAL_SIGN_L
	movlw	A'-'
	call	DRV_LCD
	goto	DRV_DIGITAL_L
PLUS_DIGITAL_SIGN_L
	movlw	A'+'	
	call	DRV_LCD
	goto	DRV_DIGITAL_L
NO_SIGN_L
	call	SPACE1		; 0 so no sign
DRV_DIGITAL_L
	movf	DIGITAL_L,w
	movwf	BIN_0
	bcf		BIN_0,7		; sign bit out
	call	BCD_ASCII	; get ASCII values
	movf	OUT2,w		; middle digit
	xorlw	H'30'		; is it 0
	btfss	STATUS,Z
	goto	LOADL7
	call	SPACE1 
	goto	LOADL8
LOADL7	
	movf	OUT2,w		; not zero so load value
	call 	DRV_LCD
LOADL8
	movf	OUT3,w
	call	DRV_LCD
dB_L	
	movlw	A'd'		; dB
	call	DRV_LCD
	movlw	A'B'	
	call	DRV_LCD
	movlw	H'90'		; line 1 position 17
	call	LOAD
	goto	VU_RIGHT_DIGITAL
TWO_SPACE_L
	movlw	A'-'
	call	DRV_LCD
	call	SPACE2
	goto	dB_L

VU_RIGHT_DIGITAL

	movlw	H'C1'		; line 2 position 2
	call	LOAD
	movf	DIGITAL_R,w	; left digital value
	xorlw	H'7F'		; if no preloaded value
	btfsc	STATUS,Z	; 
	goto	TWO_SPACE_R	; blank instead of value
	movf	DIGITAL_R,w	; if zero no sign
	btfsc	STATUS,Z
	goto	NO_SIGN_R
	btfsc	DIGITAL_R,7	; when clear - sign
	goto	PLUS_DIGITAL_SIGN_R
	movlw	A'-'
	call	DRV_LCD
	goto	DRV_DIGITAL_R
PLUS_DIGITAL_SIGN_R
	movlw	A'+'	
	call	DRV_LCD
	goto	DRV_DIGITAL_R
NO_SIGN_R
	call	SPACE1		; 0 so no sign
DRV_DIGITAL_R
	movf	DIGITAL_R,w
	movwf	BIN_0
	bcf		BIN_0,7		; sign bit out
	call	BCD_ASCII	; get ASCII values
	movf	OUT2,w		; middle digit
	xorlw	H'30'		; is it 0
	btfss	STATUS,Z
	goto	LOADR7
	call	SPACE1 
	goto	LOADR8
LOADR7	
	movf	OUT2,w		; not zero so load value
	call 	DRV_LCD
LOADR8
	movf	OUT3,w
	call	DRV_LCD
dB_R	
	movlw	A'd'		; dB
	call	DRV_LCD
	movlw	A'B'	
	call	DRV_LCD
	movlw	H'D0'		; line 2 position 17
	call	LOAD
	goto	RECLAIM
TWO_SPACE_R
	movlw	A'-'
	call	DRV_LCD
	call	SPACE2
	goto	dB_R

RECLAIM
	movf	PCLATH_STO,w
	movwf	PCLATH		; return PCLATH	
	
	swapf	STATUS_TMP,w; status temp storage to w
	movwf	STATUS		; w to status register
	swapf	W_TMP,f		; swap upper and lower 4-bits in w_tmp
	swapf   W_TMP,w		; swap bits and into w register
	retfie				; return from interrupt

 end
