LIST    P=16f84		;индикация для U питания = 3 в (ассемблер для 16F84 можно использовать для 16F819)
	include p16f819.inc
	__CONFIG  2F30H	;2F30H
#define bank0	bcf STATUS,RP0      ;выбрать Bank 0
#define bank1	bsf STATUS,RP0      ;выбрать bank 1

	ORG     0
		goto	st
	org	4
st		clrf	fl		;регистр флагов, биты	0=1 -была нажата кнопка
									1=1 -кнопка была нажата > 4 сек,значит показываем значение без линейно-логарифмического преобразования
									2=1 -кнопка отжата
									3=1 -показываем значение без линейно-логарифмического преобразования
				;при нажатии на кнопку устройство отключается, еще раз нажимаем - включается
				;если нажать и удерживать > 4сек, то показывает значение без логарифмического преобразования
		movlw	0ff
		movwf	n_kn		;счетчик времени нажатия кнопки
		movlw	1
		movwf	n_kn1		;старший байт счетчика времени нажатия кнопки
st0		call	init
st1		btfsc   ADCON0,ADGO
		goto	st1		;ожидание готовности АЦП
		movlw	19
		subwf	ADRESH,w	;учитывам смещение напряжения на диодах детектора
		bc	st2		;если результат отрицательный, то не учитываем
		movf	ADRESH,w	;вообще-то здесь будет ошибка измерения если напряжение смещения окажется меньше ожидаемого
st2		movwf	k		;результат измерения
		movwf	kz
		btfss	fl,0
		goto	st6		;кнопка не нажималась
		btfss	fl,1
		goto	wikl		;кнопка была нажата недостаточно долго - перейти в спящий режим
		bsf	fl,3		;кнопка была нажата > 4 сек,значит
st6		btfss	fl,3		;показываем значение без линейно-логарифмического преобразования
		call	preobr
		bsf	ADCON0,ADGO	;запускаем АЦП (он работает сам, к следующему опросу (метка st1)результат будет готов
		call	init_k	;пребразуем число в регистре kz в константы для подачи на индикатор
		movlw	10		;количество циклов индикации (время показа результата измерения около 0,3сек)
		movwf	t1
st3		btfss	PORTB,6	;опрос порта,
		goto	st5		;если нажата кнопка - переход
		call	out		;вывод на индикатор-формирование временной диаграммы индикатора
st4		decfsz	t1,f
		goto	st3		;цикл индикации
		bsf	fl,2		;установить признак что кнопка не нажата
		goto	st0	;?

st5		btfss	fl,2		;ожидание отпускания кнопки
		goto	st3		;для пpедотвpащения выключения после включения

		bank1
		bsf	PORTB,3	;погасить часть сегментов на индикаторе
		bank0
		btfsc	fl,3	;для выкл из pеж доп инд
		bcf	fl,1	;
		bsf	fl,0
		decfsz	n_kn,f	;счетчик времени нажатия кнопки
		goto	st3
		decfsz	n_kn1,f	;старший байт счетчика времени нажатия кнопки
		goto	st3
		bsf	fl,1			;кнопка была нажата > 4 сек,значит показываем значение без линейно-логарифмического преобразования
		goto	st3
				;вывод на индикатор-формирование временной диаграммы индикатора
out		bank1
		bsf	PORTB,3	;первый цикл диаграммы
		bank0
		movf	k3,w
	iorlw	2				;погасить левую цифру ("1")
		movwf	PORTA
		andlw	20
		iorwf	k1,w
		movwf	PORTB
		bank1
		bcf	PORTB,6		;включить верхние сегменты (-)
		bank0
		call	zdr

		bank1
		bsf	PORTB,6	;второй цикл диаграммы
		bank0
		movf	k4,w
	iorlw	2				;погасить левую цифру ("1")
		movwf	PORTA
		andlw	20
		iorwf	k2,w
		movwf	PORTB
		bank1
		bcf	PORTB,3		;включить нижние сегменты (+)
		bank0
		call	zdr

		bank1
		bsf	PORTB,3	;третий цикл диаграммы
		bank0
		movf	k3,w
	iorlw	2				;погасить левую цифру ("1")
		xorlw	0ff
		movwf	PORTA
		movf	k3,w
		andlw	20
		iorwf	k1,w
		xorlw	0ff
		movwf	PORTB
		bank1
		bcf	PORTB,6		;включить верхние сегменты (-)
		bank0
		call	zdr

		bank1
		bsf	PORTB,6	;четвертый цикл диаграммы
		bank0
		movf	k4,w
	iorlw	2				;погасить левую цифру ("1")
		xorlw	0ff
		movwf	PORTA
		movf	k4,w
		andlw	20
		iorwf	k2,w
		xorlw	0ff
		movwf	PORTB
		bank1
		bcf	PORTB,3		;включить нижние сегменты (+)
		bank0
		call	zdr
		return

init_k	movf	kz,w
		movwf	k01			;формирование адреса перехода для выбора константы
		movwf	k02
		swapf	k01,f
		movlw	0f
		andwf	k01,f
		andwf	k02,f
		call	tab1
		movwf	k1
		call	tab2
		movwf	k2
		call	tab3
		movwf	k3
		call	tab4
		movwf	k4
		return

init		movlw	0
		movwf	INTCON	;без прерываний
		bank1
		movlw	80
		movwf	OPTI		;отключить встроенные резисторы на ножках порта
		movlw	0
		movwf	OSCCON	;частота встроенного генератора 32кгц
		movlw	0
		movwf	OSCTUNE	;то же
		clrf	ADCON1	;все 5 ножек могут использоваться как входы АЦП
	movlw	048
	movwf	PORTB			;конфигурируем ножки на вход или выход
	movlw	38
	movwf	PORTA
		bank0
		movlw	23		;AN4 - вход АЦП, включить питание АЦП, запуск цикла измерения
		movwf	ADCON0
		return

wikl		movlw	10		;выключить питание АЦП
		movwf	ADCON0
	movlw	0ff			; на выходы подать "1"
	movwf	PORTA
	movwf	PORTB
		bank1
	movlw	0
	movwf	PORTA
	movlw	048			;RB3 - на вход
	movwf	PORTB
	call	zdr
		bank0
		movf	PORTB,w	;для правильной работы прерывания
		movlw	88		;разрешить прерывание от изменения на входе порта B
		movwf	INTCON
		sleep			;спать
		goto	st

zdr		clrf	t		;просто временная задержка
		bsf	t,4
zdr2		decfsz	t,f
		goto	zdr2
		return

tab1		movf	k01,w			;переход на кол-во шагов соответствующих индицируемой цифре
		addwf	PCL,f			;для выбора константы подаваемой на порт
		retlw	0c2	;0
		retlw	0d6	;1
		retlw	0c4	;2
		retlw	0c4	;3
		retlw	0d0	;4
		retlw	0c1	;5
		retlw	0c1	;6
		retlw	0c6	;7
		retlw	0c0	;8
		retlw	0c0	;9
		retlw	0d5	
		retlw	0d1	
		retlw	0d5	
		retlw	0d4	
		retlw	0c1	
		retlw	0d5	;-
		retlw	0c1	;f
tab2		movf	k01,w		;переход на кол-во шагов соответствующих индицируемой цифре
		addwf	PCL,f		;для выбора константы подаваемой на порт
		retlw	18	;0
		retlw	1e	;1
		retlw	19	;2
		retlw	1c	;3
		retlw	1e	;4
		retlw	1c	;5
		retlw	18	;6
		retlw	1e	;7
		retlw	18	;8
		retlw	1c	;9
		retlw	18	
		retlw	18	
		retlw	19	
		retlw	18	
		retlw	19	
		retlw	1f	;-
		retlw	1b	;f
tab3		movf	k02,w		;переход на кол-во шагов соответствующих индицируемой цифре
		addwf	PCL,f		;для выбора константы подаваемой на порт
		retlw	80	;0
		retlw	0a1	;1
		retlw	01	;2
		retlw	01	;3
		retlw	20	;4
		retlw	40	;5
		retlw	40	;6
		retlw	81	;7
		retlw	00	;8
		retlw	00	;9
		retlw	61	
		retlw	60	
		retlw	61	
		retlw	21	
		retlw	40	
		retlw	61	;-
		retlw	40	;f
tab4		movf	k02,w		;переход на кол-во шагов соответствующих индицируемой цифре
		addwf	PCL,f		;для выбора константы подаваемой на порт
		retlw	20	;0
		retlw	0a1	;1
		retlw	60	;2
		retlw	21	;3
		retlw	0a1	;4
		retlw	21	;5
		retlw	20	;6
		retlw	0a1	;7
		retlw	20	;8
		retlw	21	;9
		retlw	20
		retlw	20
		retlw	60
		retlw	20
		retlw	60
		retlw	0e1	;-
		retlw	0e0	;f

preobr	movlw	60		;при нулевом входном сигнале показывать 60 db
		movwf	kz
		clrf	kx
		goto	l2
l1		movlw	3		;каждый сдвиг +3db
		addwf	kz,f
		movf	kz,w		;десятичная коррекция (чтобы были значения от 0 до 9)
		andlw	0f		;
		sublw	9		;
		bc	l2		;
		movlw	6		;
		addwf	kz,f		;
l2		bcf	STATUS,C	;обнулить бит переноса
		rrf	k,f		;сдвигаем вправо
		rrf	kx,f
		movf	k,w
		bnz	l1		;пока не обнулится k
		btfss	kx,6
		goto	l3
		incf	kz,f		;+2db
		incf	kz,f
l3		btfsc	kx,5
		incf	kz,f		;+1db
		movf	kz,w		;десятичная коррекция (чтобы были значения от 0 до 9)
		andlw	0f
		sublw	9
		bc	l4
		movlw	6
		addwf	kz,f
l4		return

	cblock	20	:начальный адрес банка регистров (меньше 20 для 16F819 занимают спецрегистры)
	t		;счетчик для временной задержки
	t1		;счетчик количества показов одного измерения
	k		;хранение результата АЦП - аналого-цифр.преобр.
	kx		;вспомогательный регистр для преобр.из линейной в логарифмическую зависимость
	kz		;результат линейно - логарифмической зависимости (шкала в децибелах db)
	k01		;адрес перехода
	k02		;адрес перехода
	k1		;констаты для выдачи на порт (изображения символов)
	k2		;констаты для выдачи на порт (изображения символов)
	k3		;констаты для выдачи на порт (изображения символов)
	k4		;констаты для выдачи на порт (изображения символов)
	n_kn		;младший байт счетчика времени нажатия кнопки
	n_kn1		;старший байт счетчика времени нажатия кнопки
	fl		;регистр флагов для выбора режима работы
	endc
	end