; PIN ASSIGNMENT CONTROLLER PIC16F873A
;************************************************* **************************************
;* FOOT * * FUNCTION NAME
;************************************************* **************************************

;2 * RA0/AN0 * output control (gain = 330)
;3 * RA1/AN1 * output control (gain = 33)
;4 * RA2/AN2/Vref- * KH. Set coeff. / Set "0"
; 5 * RA3/AN3/Vref + *
; 6 * RA4/T0CKI * KH. + / Test
; 7 * RA5/AN4/SS * KH .-
; 8 * Vss * GND
; 9 * OSC1/CLKIN * Quartz 20 MHz
; 10 * OSC2/CLKOUT * Quartz 20 MHz
; 11 * RC0/T1OSO/T1CKI * Yield Cl, I = 10mA
; 12 * RC1/T1OSI/CCP2 * Rank Cx
; 13 * RC2/CCP1 * Comparator top-level charging Cx
; 14 * RC3/SCK/SCL * Rin. "-" On the ground
; 15 * RC4/SDI/SDA * Rin. "+" On Cx
; 16 * RC5/SDO * Rin. "-" On Cx
; 17 * RC6/TX/CK * Comparator lower charge level Cx
; 18 * RC7/RX/DT *
; 19 * Vss * +5 V
; 20 * Vdd * GND
; 21 * RB0/INT * LCD_D4
; 22 * RB1 * LCD_D5
; 23 * RB2 * LCD_D6
; 24 * RB3/PGM * LCD_D7
; 25 * RB4 * LCD_R / S
; 26 * RB5 * LCD_E
; 27 * RB6/PGC *
; 28 * RB7/PGD *

;************************************************* ***************************************

;	НАЗНАЧЕНИЕ ВЫВОДОВ КОНТРОЛЛЕРА  PIC16F873A
;***************************************************************************************
;*НОГА *        ИМЯ     *   НАЗНАЧЕНИЕ
;***************************************************************************************

; 1    *  MCLR/Vpp         *  Сброс
; 2    *  RA0/AN0          *  выход ДУ (Ку=330)
; 3    *  RA1/AN1          *  выход ДУ (Ку=33)
; 4    *  RA2/AN2/Vref-    *  Кн. Set coeff./Set "0"
; 5    *  RA3/AN3/Vref+    *
; 6    *  RA4/T0CKI        *  Кн.+/Test
; 7    *  RA5/AN4/SS       *  Кн.-
; 8    *  Vss              * GND
; 9    *  OSC1/CLKIN       * Кварц 20 МГц
; 10   *  OSC2/CLKOUT      * Кварц 20 МГц
; 11   *  RC0/T1OSO/T1CKI  * Заряд Сх, I=10mA
; 12   *  RC1/T1OSI/CCP2   * Разряд Сх
; 13   *  RC2/CCP1         * Компаратор верхнего уровня зарядки Сх
; 14   *  RC3/SCK/SCL      * вх."-" на землю

; 15   *  RC4/SDI/SDA      * вх."+" на Сх
; 16   *  RC5/SDO          * вх."-" на Сх
; 17   *  RC6/TX/CK        * Компаратор нижнего уровня зарядки Сх
; 18   *  RC7/RX/DT        *
; 19   *  Vss              * +5V
; 20   *  Vdd              * GND
; 21   *  RB0/INT          * LCD_D4
; 22   *  RB1              * LCD_D5
; 23   *  RB2              * LCD_D6
; 24   *  RB3/PGM          * LCD_D7
; 25   *  RB4              * LCD_R/S
; 26   *  RB5              * LCD_E
; 27   *  RB6/PGC          *
; 28   *  RB7/PGD          *

;****************************************************************************************

Port_A_Config	equ 0xFF
; Port A bit equates
Kn_Set  		equ	2
Kn_Plus  		equ 4
Kn_Minus  		equ 5

Port_B_Config	equ b'11000000'

Port_C_Config	equ b'11000100'
; Port C bit equates
Cap_Charge  	equ 0
Cap_Discharge	equ 1
Comp_Up			equ 2
In_N_Gnd		equ 3
In_P_Cx			equ 4
In_N_Cx			equ 5
Comp_Low		equ 6

ESR_ready		equ	b'00110011' ;вкл. разряд, "+" и "-" ДУ на Сх
ESR_start		equ b'00110000'	;вкл. заряд, "+" и "-" ДУ на Сх
Cap_ready		equ b'00011011'	;вкл. раздяд, "-" ДУ на землю, "+" на Сх
Cap_start		equ	b'00011000'	;вкл. заряд, "-" ДУ на землю, "+" на Сх
Cap_start2		equ	b'00110000'	;вкл. заряд, "-" ДУ на Cx, "+" на Сх

Max_Count		equ	.70	;максимальное число (1 байт, не более 256) переполнений TMR0 при счете
						;шаг счета - 0.2 мкс, 65536*0.2=13107.2 мкс - одно переполнение
						;или при I=10mA 15 отсчетов/мкФ 65536/15=4369 мкф - одно переполнение
						;Пусть Сх мах=150000мкФ, 150000/4369=34
						;Учитывая время заряда до нижней границы константу надо удвоить
;****************************************************************************************


	 list      p=PIC16F873a
     #include  P16F873a.inc ;	; 20.000 MHz
	__CONFIG _CP_OFF & _BODEN_OFF & _HS_OSC & _WRT_OFF & _WDT_OFF & _PWRTE_ON & _DEBUG_OFF & _CPD_OFF & _LVP_OFF

;	#define	_BAT	PORTA,1		; 0- low bat

	#define	_RS	    PORTB,4
	#define	_E	    PORTB,5


	CBLOCK 0x35 ;0x20-0x34 for FLOATING POINT LIBRARY
	;	Блоки данных
	W_TEMP		;сохранение контекста при прерываниях
	STATUS_TEMP
	PCLATH_TEMP
	

	Dly0  ;Stores 3 bytes of data for the delay count
	Dly1  ;Dly0 is the least significant byte
	Dly2  ;while Dly3 is the most significant byte

;	Temp
	Temp1
	Temp2
	Temp3
	Temp4

	Count1
	Count2

	T0
	T1

	;	Блоки данных
	T2	; Старший байт
	T3
	T4
	T5	; Младший байт

	AX	; Старший байт
	A0
	A1
	A2	; Младший байт

	A3
	A4
	A5

	BCD0	; Младший байт
	BCD1
	BCD2
	BCD3
	BCD4	; Старший байт
	
	U330_L	;Напряжение с выхода ДУ, Ку=330, младший байт
	U330_H	;Напряжение с выхода ДУ, Ку=330, старший байт
	U33_L	;Напряжение с выхода ДУ, Ку=33, младший байт
	U33_H	;Напряжение с выхода ДУ, Ку=33, старший байт
	
	TMR1_Count	;Счетчик переполнений TMR1
	TMR0_Count	;Счетчик переполнений TMR0
	Flags
	EE_ADR ;вспомогательная ячейка для работы с EEPROM
	EE_DATA
	NZ	;число значащих разрядов при выводе на индикатор
	NC	;номер константы
	Const_ADR ;адрес константы в EEPROM
	ENDC
	
	CBLOCK 0xB5
	W_TEMP1		;сохранение контекста при прерываниях
	ENDC
	
;=========================
;       МАКРОСЫ
;=========================
bank0	macro 
	    bcf STATUS, RP0
    	endm
	
bank1	macro 
	    bsf STATUS, RP0
    	endm	

Dly24 MACRO DLY
;Take the delay value argument from the macro, precalculate
;the required 3 RAM values and load the The RAM values Dly2,Dly1 
;and Dly0.
	banksel Dly0
	movlw   DLY & H'FF'
	movwf   Dly0
	movlw   DLY >>D'08' & H'FF'
	movwf   Dly1
	movlw   DLY >>D'16' & H'FF'
	movwf   Dly2
;Bytes are shifted and anded by the assembler to make user 
;calculations easier.
	endm
	
;==========================
	
	ORG		0x2100   	; Область EEPROM
;		Данные			; Адрес	в EEPROM

; корректирующие коэффициенты для:
USR_1		DE	0x00, 0x00, 0x03, 0xE8	; 1 - предела 1 Ом
USR_10		DE	0x00, 0x00, 0x03, 0xE8	; 1 - предела 10 Ом
USR_Cx		DE	0x00, 0x00, 0x03, 0xE8	; 1 - измерения емкости

;K_ESR_1		DE	0x7F, 0x00, 0x00, 0x00 ; 1 - предела 1 Ом
;K_ESR_10	DE	0x7F, 0x00, 0x00, 0x00 ; 1 - предела 10 Ом
;K_Cx		DE	0x7F, 0x00, 0x00, 0x00 ; 1 - измерения емкости

;numbers in FLOATING POINT LIBRARY format
U0_ESR_1	DE	0x85, 0x16, 0x00, 0x00 ; 75=85160000 - "0" на пределе 1 Ом
U0_ESR_10	DE	0x81, 0x60, 0x00, 0x00 ;  7=81600000 - "0" на пределе 10 Ом

; множители для расчетов:
M_ESR_1		DE	0x75, 0x40, 0x30, 0x0C ; 1/682=7540300C
M_ESR_10	DE	0x78, 0x74, 0x89, 0x8D ; 1/67=7874898D
M_Cx		DE	0x74, 0x2E, 0xC3, 0x3E ; 1/(15*100)=742EC33E
sub_Cx		DE	0x80, 0x40, 0x00, 0x00 ; 3=80400000 - вычитается из показаний TMR1

;==========================
		org 	0x700 ; посделние 256 байт 1-й страницы памяти программ
Table	addwf	PCL,F
omega	dt	b'00000000'	;знак омега
		dt	b'00001110'
		dt	b'00010001'
		dt	b'00010001'
		dt	b'00010001'
		dt	b'00001010'
		dt	b'00011011'
		dt	b'00000000'
		
mu		dt	b'00000000'
		dt	b'00000000'
		dt	b'00010010'
		dt	b'00010010'
		dt	b'00010010'
		dt	b'00011110'
		dt	b'00010001'
		dt	b'00010000'
_Const	dt	"Coeff. for",0
_ESR	dt	"ESR",0
_Cx		dt	" Cx ",0
_Time_out	dt	"Cx ---",0
_1_ohm	dt	" 1 ",1,0
_10_ohm	dt	" 10 ",1,0
_tst_1	dt	"1",1,"=",0
_tst_10	dt	" 10",1,"=",0
_write_U0	dt	"U0 ---> EEPROM  ",0
_ready	dt	"It is ready!",0
		org 	0x00 
;*******************************************************************************
;                            НАЧАЛО  ПРОГРАММЫ
;******************************************************************************* 	
		nop			;for MPLAB-ICD2
		goto		init
;------------------ Interrupt ------------------
		org		0x004

		movwf   W_TEMP		;save W
		swapf   STATUS,W	;swap STATUS, W
		clrf	STATUS
		movwf   STATUS_TEMP	;save status
		movf	PCLATH,W
		movwf	PCLATH_TEMP	;save PCLFTH
		
		decfsz	TMR0_Count
		goto	restore_context
		bsf		Flags,0		;Time Out!
		goto	stop_TMR1
		
restore_context
		bcf     INTCON,T0IF	;clear interrupt flag
		
		movf	PCLATH_TEMP,W
		movwf	PCLATH
		swapf	STATUS_TEMP,W	;fetch status, reswap nibbles
		movwf   STATUS			;restore status
		swapf   W_TEMP,F    ;swap nibbles in preparation
		swapf   W_TEMP,W    ;for the swap restoration of w
		retfie				;return from interrupt
;-----------------------------------------------

init
		banksel		INTCON
		clrf		Flags
		clrf		INTCON
		clrf		PCLATH
		clrf		PORTA
		clrf		PORTB
		movlw		ESR_ready ;вкл. разряд, "+" и "-" ДУ на Сх
		movwf		PORTC

		banksel		TRISA
		movlw		Port_A_Config
		movwf		TRISA
		;инициализация АЦП
		movlw		b'10000100';правое выравнивание, Vdd, Vss, AN0, AN1, AN3
		movwf		ADCON1

		movlw		Port_B_Config
		movwf		TRISB
		movlw		Port_C_Config
		movwf		TRISC

;	Инициализация LCD в 4-х битный режим		
InitLCD
        call		Delay_5_ms
        call		Delay_5_ms
        call		Delay_5_ms ;пауза 15 мс после вкл питания
		banksel		PORTB
		movlw		3
		movwf		Count1
		movwf		PORTB
SetLoop
        bsf		_E		;для инициализации LCD 3 раза посылается команда 0x30
		nop
		nop
		nop
		bcf		_E
		call		Delay_5_ms
		decfsz		Count1,f
		goto		SetLoop
		
		movlw		2		; 4-x битный
		movwf		PORTB
		call		Send
		movlw		28		; 4-х битный, 2 строки, 5х7
		call		CmdLCD
		movlw		0C		; Включить дисплей
		call		CmdLCD
		movlw		6
		call		CmdLCD
		call		Load_ZG ; Загрузить символы мю и омега
        call		ClrDSP		; Очистить дисплей
;--------------------------------------------------
		btfsc		PORTA, Kn_Set ;
		goto		Main
;------------ режим установки констант ------------
		goto		c_1		
Const_Loop
		btfss		PORTA, Kn_Plus
		call		IncB
		btfss		PORTA, Kn_Minus
		call		DecB
		btfsc		PORTA, Kn_Set
		goto		Const_Loop

		btfss		Flags,5	;флаг изменения константы
		goto		c_3
		call		Save_Const	;константа изменилась, надо сохранить		
c_3
		incf		NC,F
		movf		NC,W
		sublw		3	;число констант
		btfss		STATUS,Z
		goto		$+2
c_1		clrf		NC
		bcf			Flags,5	;Очищаем флаг изменения константы
        call		ClrDSP		; Очистить дисплей
   		movlw		LOW _Const
		call		Read_String
		movlw 		HIGH $
		movwf 		PCLATH
        movf		NC,W
        addwf		PCL,F ;табличный переход
        goto		const_1_ohm		;+0
        goto		const_10_ohm	;+1
        goto		const_Cx		;+2
c_2		call		ShowX
        goto		Const_Loop

const_1_ohm
		movlw		LOW USR_1
		movwf		Const_ADR
		call		EEPROM_To_B
		movlw		LOW _1_ohm
		call		Read_String
		goto		c_2
const_10_ohm
		movlw		LOW USR_10
		movwf		Const_ADR
		call		EEPROM_To_B
		movlw		LOW _10_ohm
		call		Read_String
		goto		c_2
const_Cx		
		movlw		LOW USR_Cx
		movwf		Const_ADR
		call		EEPROM_To_B
		movlw		LOW _Cx
		call		Read_String
		goto		c_2
;------- Инициализация модуля АЦП ------
Main
;		banksel		ADCON1
;		movlw		b'10000100';правое выравнивание, Vdd, Vss, AN0, AN1, AN3
;		movwf		ADCON1

ESR_measure
		banksel		PORTC
		movlw		ESR_start ; вкл. заряд, "+" и "-" ДУ на Сх
		movwf		PORTC
		
		movlw		0x4		;Задержка 3.6мкс (18 циклов) для окончания перех.процессов - ПОДОБРАТЬ!!!
		call		Delay_go

		bcf			PORTC, In_P_Cx ;отключаем Сзап от Сх
		nop			;???
		bsf			PORTC, Cap_Charge ;выкл. Iзар.

		;Измеряем напряжение с выхода диф.усилителя с Ку=330
		banksel		ADCON0
		movlw		b'10000001' ;Fosc/32, канал 0, модуль АЦП вкл.
		movwf		ADCON0
		call		Delay_20_us
		bsf			ADCON0,2	;начать аналого-цифровое преобразование
		btfsc		ADCON0,2
		goto		$-1		; ждем окончания преобразования
		movf		ADRESH,W
		movwf		U330_H
		banksel		ADRESL
		movf		ADRESL,W
		banksel		U330_L
		movwf		U330_L
		
		;Измеряем напряжение с выхода диф.усилителя с Ку=33
		banksel		ADCON0
		movlw		b'10001001' ;Fosc/32, канал 1, модуль АЦП вкл.
		movwf		ADCON0
		call		Delay_20_us
		bsf			ADCON0,2	;начать аналого-цифровое преобразование
		btfsc		ADCON0,2
		goto		$-1		; ждем окончания преобразования
		movf		ADRESH,W
		movwf		U33_H
		banksel		ADRESL
		movf		ADRESL,W
		banksel		U33_L
		movwf		U33_L

;------------ Если ESR>10 Ом, измерение емкости не выполняем ------------
		clrf		Flags
		movlw		0x03
		subwf		U33_H,W	;если показания АЦП>=0x300 (768)
		btfss		STATUS,Z
		goto		Cx_0	;переход на измерение емкости
		bsf			Flags,0		;взводим флаг Time Out
		goto		Cx_3
;------------ Измерение емкости конденсатора ------------
Cx_0
		movlw		Cap_ready ;вкл. раздяд, "-" ДУ на землю, "+" на Сх
		movwf		PORTC
		call		TMR0_init	;Запускаем TMR0 для предотвращения зависаний при измерении емкости
		
		call		Delay_200_us
		btfss		PORTC, Comp_Low	; 1 - Cx разрядился
		goto		$-2				;ждем снова 200 мкс
		call		Delay_200_us	;для надежности еще задержка
		call		TMR1_init

		movlw		0x03
		subwf		U330_H,W	;если показания АЦП>=0x300 (768)
		btfss		STATUS,Z	;т.е. ESR>1 Ом, емкость измеряем с компенсацией ESR
		goto		Cx_1
		movlw		Cap_start2	;вкл. заряд, "-" ДУ на Cx, "+" на Сх
		movwf		PORTC
		movlw		0x4		;Задержка 3.6мкс (18 циклов) для заряда С на "-" входе ДУ
		call		Delay_go
		bcf			PORTC,In_N_Cx	;отключаем "-" вход ДУ от Сх
		goto		Cx_2
Cx_1
		movlw		Cap_start ;вкл. заряд, "-" ДУ на землю, "+" на Сх
		movwf		PORTC
Cx_2		
		btfsc		PORTC, Comp_Low ; 0 - Cx зарядился до нижней границы
		goto		$-1
		bsf			T1CON, TMR1ON	; запускаем таймер

tst_charge
		btfss		PORTC,Comp_Up; 0 - Cx зарядился до верхней границы
		goto		stop_TMR1
		btfsc		PIR1, TMR1IF	; TMR1 переполнен?
		call		Inc_count
		goto		tst_charge

stop_TMR1
		clrf		T1CON	;остановить TMR1
		clrf		INTCON	;запрещаем прерывания
		btfsc		PIR1, TMR1IF	;проверим последний раз на переполнение таймера
		call		Inc_count		;было переполнение
Cx_3	movlw		Cap_ready ;вкл. раздяд, "-" ДУ на землю, "+" на Сх
		movwf		PORTC

;--------------------------------------------------------
;Выводим результат на индикатор
;		call		CursorHome
		call		ClrDSP
;Timeout		
		btfss		Flags,0
		goto		Disp_Cx
		movlw		LOW _Time_out
		call		Read_String
		goto		Disp_ESR

;--------------------------------------------------------
		clrf		FPFLAGS
		bsf			FPFLAGS, RND ; флаг округления при расчетах
Disp_Cx
		movlw		LOW _Cx
		call		Read_String

		clrf		AEXP
		movf		TMR1_Count,W
		movwf		AARGB0
		movf		TMR1H,W
		movwf		AARGB1
		movf		TMR1L,W
		movwf		AARGB2
		
		btfsc		PORTA, Kn_Plus
		goto		Calc_Cx
		call		BCD 	;Если нажата кнопка плюс, то тестовый вывод
		movlw		BCD4	;таймера без обработки
		call		Disp_Full
		goto		Disp_ESR
Calc_Cx		
		call		FLO2424 ;Integer to float conversion
		movlw		low sub_Cx
		call		EEPROM_To_B
		call		FPS24	;A=A-3
		movlw		low M_Cx
		call		EEPROM_To_B
		call		FPM24	;A=A*M_Cx
		movlw		low USR_Cx
		call		X_To_B
		call		INT2424	;Output: 24 bit 2's complement integer right
							;justified in AARGB0, AARGB1, AARGB2
		clrf		AEXP
		call		BCD
		bsf			Flags,1 ;не выводить лидирующие нули
		movlw		3
		movwf		NZ		;число значащих разрядов, остальные будут 0
		bsf			Flags,3	;включить проверку знач. разрядов при выводе
				
		movlw		BCD3
		call		DispBCD
		movlw		BCD3	;показания увеличены в 10 раз,
		call		DispBCD	;здесь сотни тысяч мкФ 	
		
		movlw		BCD2	;десятки тысяч мкФ
		call		DispBCD
		movlw		BCD2	;тысячи мкФ
		call		DispBCD

		; если впереди были одни нули, разделитель не выводим
		btfsc		Flags,1
		goto		next_1
		movlw		","		;разделитель тысяч
		call		CharLCD
next_1
		movlw		BCD1	;сотни мкФ
		call		DispBCD
		btfsc		Flags,1 ;до сотен небыло значащих цифр,
		bsf			Flags,2	;будем выводить десятые доли мкФ
		movlw		BCD1	;десятки мкФ
		call		DispBCD

		bcf			Flags,1	;проверка на =0 не нужна, выводим все подряд
		movlw		BCD0	;единицы мкФ
		call		DispBCD
		
		btfss		Flags,2 ;нужен ли вывод десятичной точки
		goto		next_2  ;нет
		bcf			Flags,2	;да
		call		DispDot	;десятичная точка
		movlw		BCD0	;десятые мкФ
		call		DispBCD
next_2
		call		DispSP
		movlw		2		;код мю
		call		CharLCD
		movlw		"F"
		call		CharLCD
;----------------------------
Disp_ESR
		btfss		PORTA, Kn_Plus
		goto		tst_ESR
		
		bcf			Flags,4 ;сброс флага больше 10 Ом		
		movlw		0x03
		subwf		U330_H,W	;если показания АЦП>=0x300 (768)
		btfsc		STATUS,Z	;проверяем второй канал (10 Ом)
		goto		chk_10
		
; Канал 1 Ом
		call		ClrA
		movf		U330_H,W ;усилитель Ку=330, предел 1 Ом
		movwf		AARGB0
		movf		U330_L,W
		movwf		AARGB1
		call		FLO1624 ;to 24 bit floating point
		movlw		low U0_ESR_1
		call		EEPROM_To_B
		call		FPS24	;A=A-U0 - вычитаем смещение нуля
		movlw		low M_ESR_1
		call		EEPROM_To_B
		call		FPM24	;A=A*M_ESR_1
		movlw		low USR_1
		call		X_To_B
		goto		ESR_to_LCD

chk_10
		movlw		0x03
		subwf		U33_H,W	;если показания АЦП>=0x300 (768)
		btfsc		STATUS,Z
		bsf			Flags,4 ;больше 10 Ом		

;канал 10 Ом
		call		ClrA
		movf		U33_H,W ;усилитель Ку=33, предел 10 Ом
		movwf		AARGB0
		movf		U33_L,W
		movwf		AARGB1
		call		FLO1624 ;to 24 bit floating point
		movlw		low U0_ESR_10
		call		EEPROM_To_B
		call		FPS24	;A=A-U0 - вычитаем смещение нуля
		movlw		low M_ESR_10
		call		EEPROM_To_B
		call		FPM24	;A=A*M_ESR_10
		movlw		low USR_10
		call		X_To_B

ESR_to_LCD
		call		SecLine
		movlw		LOW _ESR
		call		Read_String
		
		btfss		Flags,4 ;>10 ohm?
		goto		next_3
		movlw		">"
		call		CharLCD
		goto		next_4
next_3	call		DispSP

next_4	movlw		0x80
		andwf		AARGB0,W ;выделяем знак "-"
		btfsc		STATUS,Z
		goto		next_5	;результат > 0
		call		ClrA	;результат < 0, выводим одни нули
		goto		next_6
next_5	call		INT2424

next_6	bcf			Flags,3	;выключить проверку знач. разрядов при выводе
		bsf			Flags,1 ;не выводить лидирующие нули
		clrf		AEXP
		call		BCD

		movlw		BCD2
		call		DispBCD
		movlw		BCD2
		call		DispBCD ;десятки Ом

		bcf			Flags,1	;проверка на =0 не нужна, выводим все подряд
		movlw		BCD1	;единицы Ом
		call		DispBCD
		call		DispDot
		movlw		BCD1
		call		DispBCD

		movlw		BCD0
		call		DispBCD
		movlw		BCD0
		call		DispBCD
		
		call		DispSP
		movlw		1				;знак ом
		call		CharLCD
end_disp
		banksel		PORTC
		bsf			PORTC, Cap_Discharge ;вкл. разряд Сх

		call		Delay_05_sec
		
		banksel		PORTC
		bcf			PORTC, Cap_Discharge ;выкл. разряд Сх
		
		goto	ESR_measure

;Для тестирования - вывод АЦП без обработки
;сразу 2-х каналов (1 и 10 Ом)
tst_ESR
		call		SecLine
		;канал 1 Ом
		movlw		LOW _tst_1
		call		Read_String
		call		ClrA
		movf		U330_H,W ;усилитель Ку=330, предел 1 Ом
		movwf		AARGB1
		movf		U330_L,W
		movwf		AARGB2
		call		BCD
		movlw		BCD1
		call		Disp_Full
		;канал 10 Ом
		movlw		LOW _tst_10
		call		Read_String
		call		ClrA
		movf		U33_H,W ;усилитель Ку=33, предел 10 Ом
		movwf		AARGB1
		movf		U33_L,W
		movwf		AARGB2
		call		BCD
		movlw		BCD1
		call		Disp_Full
		btfsc		PORTA, Kn_Set	;проверка кнопки установки нуля
		goto		end_disp
		;Сохранение U0 в EEPROM ------------------------
		call		CursorHome
		movlw		LOW _write_U0
		call		Read_String
		;U0 для l Ом
		call		ClrA
		movf		U330_H,W ;усилитель Ку=330, предел 1 Ом
		movwf		AARGB0
		movf		U330_L,W
		movwf		AARGB1
		call		FLO1624 ;to 24 bit floating point
		call		BEQUA
		movlw		LOW U0_ESR_1
		movwf		Const_ADR
		call		Save_Const
		;U0 для l0 Ом
		call		ClrA
		movf		U33_H,W ;усилитель Ку=33, предел 10 Ом
		movwf		AARGB0
		movf		U33_L,W
		movwf		AARGB1
		call		FLO1624 ;to 24 bit floating point
		call		BEQUA
		movlw		LOW U0_ESR_10
		movwf		Const_ADR
		call		Save_Const

		call		Delay_3_sec
		call		ClrDSP
		movlw		LOW _ready
		call		Read_String
		call		Delay_1_sec
		goto		end_disp
;------------------------- TMR1 -------------------------
;Инициализация таймера TMR1, шаг счета = 0.2 мкс
TMR1_init
		clrf		TMR1L
		clrf		TMR1H
		bcf			PIR1, TMR1IF
		movlw		b'00000000'; 1:1 Fosc/4
		movwf		T1CON
		clrf		TMR1_Count
		return
;------------------------- TMR1 -------------------------
;Увеличить счетчик переполнений TMR1
Inc_count
		bcf			PIR1, TMR1IF	;очищаем флаг переполнения таймера
		incfsz		TMR1_Count,F
		return
		bsf			Flags,0	;Time out
		goto 		stop_TMR1;за отведенное время измерения не дождались окончания заряда
;------------------------- TMR0 -------------------------
;Инициализация таймера TMR0, шаг счета = 0.2 мкс
TMR0_init
		movlw	Max_Count
		movwf	TMR0_Count	;начальное значение счетчика переполнений TMR0
		clrf	TMR0	 ;clear timer
		movlw	OPTION_REG ;Work around the OPTION
		movwf   FSR		;address OPTION_REG -> FSR
		movlw	b'00000111' ; set up timer. 1:256 presc 
		movwf	INDF
		
		bcf	INTCON,T0IF	;clear tmr0 int flag
		bsf	INTCON,T0IE ;enable TMR0 int
		bsf	INTCON,GIE	;enable global interrupts
		clrf	TMR0	;start timer
		return
;------------------------- Delay -------------------------
;	Подпрограммы пауз
Delay_3_sec		;Пауза 3 сек
		Dly24	D'937499'   ; 3/(4/20000000)/16=937500-1=937499
		goto	DoDly24

Delay_2_sec		;Пауза 2 сек
		Dly24	D'624999'   ; 2/(4/20000000)/16=625000-1=624999
		goto	DoDly24

Delay_1_sec		;Пауза 1 сек
		Dly24	D'312499'   ; 1/(4/20000000)/16=312500-1=312499
		goto	DoDly24

Delay_05_sec		;Пауза 0.5 сек
		Dly24	D'156249'   ; 0.5/(4/20000000)/16=156250-1=156249
		goto	DoDly24

Delay_5_ms	;Пауза 5 мс
		Dly24	D'1562'   ; 0.005/(4/20000000)/16=1562.5=1562
		goto	DoDly24
		
Delay_200_us	;Пауза 200 мкс
		Dly24	D'62'   ; 0.0002/(4/20000000)/16=62.5=62
		goto	DoDly24

DoDly24		;16 Tcy per loop
		movlw   H'FF'      ;Start with -1 in W
		addwf   Dly0,F     ;LSB decrement
		btfsc   STATUS,C   ;was the carry flag set?
		clrw               ;If so, 0 is put in W
		addwf   Dly1,F     ;Else, we continue.
		btfsc   STATUS,C
		clrw               ;0 in W
		addwf   Dly2,F
		btfsc   STATUS,C
		clrw               ;0 in W
		iorwf   Dly0,W     ;Inclusive-OR all variables
		iorwf   Dly1,W     ;together to see if we have reached
		iorwf   Dly2,W     ;0 on all of them.
		btfss   STATUS,Z   ;Test if result of Inclusive-OR's is 0
		goto    DoDly24
		return

Delay_20_us
		movlw		0x1F		;Задержка 20 мкс
Delay_go
		movwf		Dly0
		decfsz		Dly0,F
		goto		$-1
		nop
		nop
		return

;---------------------- LCD ---------------------
;	 Перевод указателя  на второй символ второй строки
SecLine		movlw		0xC0

;	Загрузка команды
CmdLCD	movwf	Temp4
;		bcf		_RS
		swapf	Temp4, W
		andlw	0x0F
		movwf	PORTB
		bsf		_E
		nop
		nop
		nop
		bcf		_E
		movf	Temp4, W
		andlw	0x0F
		movwf	PORTB
		bsf		_E
		nop
		nop
		nop
		bcf		_E
;		clrf		PORTB
		call	Delay_200_us
		return


;	Перекодировка в ASCII и вывод
NumLCD	andlw		0x0F		; маска
		iorlw		0x30		; ASCII
;	Вывод ASCII символа
CharLCD	movwf		Temp4
SendLCD	swapf		Temp4, W
		andlw		0x0F
		iorlw		b'00010000'	; RS=1
		movwf		PORTB
		bsf		_E
		nop
		nop
		nop
		bcf		_E
		movf		Temp4, W
		andlw		0x0F
		iorlw		b'00010000'	; RS=1
		movwf		PORTB
Send	bsf		_E
		nop
		nop
		nop
		bcf		_E
		clrf		PORTB
		call		Delay_200_us
		return



CursorHome	movlw		0x02		; Дисплей в исходное состояние
			goto		LongSend
ClrDSP		movlw		1		; Очистка дисплея
LongSend	call		CmdLCD
			goto		Delay_5_ms

DispDot		movlw		"."
			goto		CharLCD

Disp0		movlw		"0"
			goto		CharLCD

DispSP		movlw		" "
			goto		CharLCD

;-----------------------------------------------------------
;Чтение строки из таблицы и вывод на LCD
Read_String
			movwf		Count1
			decf		Count1,F ;коррекция начального смещения
			movlw 		HIGH Table
			movwf 		PCLATH
get_next_s
			movf		Count1,W
			call		Table
			andlw		0xFF	; проверка на конец строки
			btfsc		STATUS, Z
			return
			call		CharLCD
			incf		Count1,F
 			goto		get_next_s

;---------------------- Load CGRAM LCD ---------------------
;загрузить знакогенератор
Load_ZG
			movlw		b'01001000' ; AC in CGRAM=8
			call		CmdLCD
			movlw 		HIGH Table
			movwf 		PCLATH
			movlw		.16		;2 знака по 8 байт
			movwf		Count1
			movlw		LOW  omega-1
			movwf		Count2	;смещение в таблице

get_s		call		Table	;получить символ из таблицы
			call		CharLCD
			incf		Count2,F
			movf		Count2,W
			decfsz		Count1,F
			goto		get_s
			return
;----------------------------------------------------------
;вывод из переданного в W адреса блока BCD0...4
;на индикатор
Disp_Full
			movwf		FSR		;адрес ячейки для вывода на LCD
next_byte
			swapf		INDF,W
			call		NumLCD
			movf		INDF,W
			call		NumLCD
			;проверим, добрались ли мы до BCD0
			movlw		BCD0
			subwf		FSR,W
			btfsc		STATUS,Z
			return
			decf		FSR,F
			goto		next_byte
;---------------------- BCD to LCD ---------------------
;	Вывод разряда и подготовка к выводу следующего
DispBCD		movwf		FSR
NextNibble	swapf		INDF,F
		movf		INDF,W
		btfss		Flags,1 ;1 - не выводить лидирующие нули
		goto		chk_NZ
		andlw		0x0F
		btfsc		STATUS,Z
		return		;пропуск вывода
		bcf			Flags,1 ; эту и все посдедующие цифры выводим
chk_NZ
		btfss		Flags,3 ; 1- выводить только NZ разрядов, остальные - 0
		goto		NumLCD
		movf		NZ,F
		btfsc		STATUS,Z	;счетчик=0?
		goto		Disp0	;да, выводим 0
		decf		NZ,F	;нет, выводим то что есть
		call		NumLCD
		return
;---------------------- BCD ---------------------
;	Перекодировка значения из двоичного в десятичный формат
BCD		movlw		0x20
		movwf		T1
		clrf		BCD0
		clrf		BCD1
		clrf		BCD2
		clrf		BCD3
		clrf		BCD4

BcdLoop	rlf		AARGB2, F
		rlf		AARGB1, F
		rlf		AARGB0, F
		rlf		AEXP, F

		rlf		BCD0, F
		rlf		BCD1, F
		rlf		BCD2, F
		rlf		BCD3, F
		rlf		BCD4, F
		decfsz		T1, F
		goto		Adjust
		return

Adjust	movlw		.5
		movwf		Count2

		movlw		BCD0
		movwf		FSR
		goto		ADloop+1

ADloop	incf		FSR, F
		call		Adjbcd
		decfsz		Count2, F
		goto		ADloop
		goto		BcdLoop

Adjbcd	movlw		0x03
		addwf		INDF, W
		movwf		T0		
		btfsc		T0, 3		
		movwf		INDF
		movlw		0x30
		addwf		INDF, W
		movwf		T0
		btfsc		T0, 7
		movwf		INDF
		return

;-------------------------------------------------------
;	Копирование "по назначению" блока (4 байта) данных
; Temp1 = адрес получателя - указывается старший адрес блока
; Temp2 = адрес источника - указывается старший адрес блока

;CEQUA		movlw		CX		; C=A
Copy_From_A
		movwf		Temp1		; Xw=A
		movlw		AEXP
		movwf		Temp2
		goto		Copy

BEQUA		movlw		AEXP		; B=A
Copy_To_B	movwf		Temp2		; B=Xw
		movlw		BEXP
		goto		Copy_B

;AEQUF		movlw		FX		; A=F
Copy_To_A
		movwf		Temp2		; A=Xw
		movlw		AEXP

Copy_B	movwf		Temp1
Copy	movlw		4		; Объём блока
		movwf		Count1
Copy_Loop
		movf		Temp2, W
		movwf		FSR
		movf		INDF, W
		movwf		Temp3
		movf		Temp1, W
		movwf		FSR
		movf		Temp3, W
		movwf		INDF
		decf		Temp1, F ; двигаемся в сторону уменьшения
		decf		Temp2, F ; адресов
		decfsz		Count1, F
		goto		Copy_Loop
		return

;-------------------------------------------------------
X_To_B	call		EEPROM_To_B	; Загрузка коэффициента X
		call		ASwapB
		call		FLO2424
		call		FPM24
		return

ASwapB	movlw		T5
		call		Copy_From_A
		movlw		BEXP
		call		Copy_To_A
		movlw		T5
		call		Copy_To_B
		return		
;-------------------------------------------------------
;	Очистка блоков А и В
ClrB	movlw		BEXP	; Очистка блока В
		goto		ClrA+1

ClrA	movlw		AEXP	; Очистка блока А
		movwf		FSR
		movlw		4	;Объем блока
		movwf		Count1

ClrLoop
		clrf		INDF	; Цикл очистки
		decf		FSR, F	; уменьшаем адрес
		decfsz		Count1, F
		goto		ClrLoop
		return
;-------------------------------------------------------
;	Чтение данных из EEPROM в блок B
EEPROM_To_B
		movwf		EE_ADR	; Сохраняем адрес ячейки EEPROM
		movlw		BEXP
		movwf		FSR
		movlw		4	;Объем блока
		movwf		Count1
EE_read_loop
	    call		ReadEEPROM
		banksel		BEXP
		movwf		INDF
		incf		EE_ADR, F
		decf		FSR, F
		decfsz		Count1, F
		goto		EE_read_loop
		return

;	Чтение EEPROM
ReadEEPROM
		movf		EE_ADR,W ;
		banksel		EEADR 	; банк 2
		movwf		EEADR	; адрес ячейки EEPROM
		banksel		EECON1	; банк3
		bcf			EECON1,EEPGD ;выбрать EEPROM 
		bsf			EECON1,RD    ;инициализровать чтение
		banksel		EEDATA	; банк2
		movf		EEDATA,W	; W = EEDATA
		return

;-------------------------------------------------------
;	Запись блока BARG в EEPROM
; Адрес в EEPROM задается в Const_ADR
Save_Const
		movf		Const_ADR,W
		movwf		EE_ADR
		movlw		BEXP
		movwf		FSR
		movlw		4	;Объем блока
		movwf		Count1
EE_write_loop
		movf		INDF,W
		movwf		EE_DATA
		call		WriteEEPROM
		banksel		BEXP
		incf		EE_ADR, F
		decf		FSR, F
		decfsz		Count1, F
		goto		EE_write_loop
		return

;	Запись EEPROM
WriteEEPROM
		banksel		EECON1	;банк3
		btfsc		EECON1,WR
		goto		$-1
		banksel		EEADR	;банк2
		movf		EE_ADR,W
		movwf		EEADR
		movf		EE_DATA,W
		movwf		EEDATA
		banksel		EECON1
		bcf			EECON1,EEPGD
		bsf			EECON1,WREN
		movlw		0x55
		movwf		EECON2
		movlw		0xAA
		movwf		EECON2
		bsf			EECON1,WR
		bcf			EECON1,WREN
		return
;-------------------------------------------------------
;	Инкрементирование полублока B
IncB
		bsf			Flags,5	;устанавливаем флаг изменения константы
        incf		BARGB2, F
		btfsc		STATUS, Z
		incf		BARGB1, F
		goto		ShowX

;	Декрементирование полублока B
DecB
		bsf			Flags,5	;устанавливаем флаг изменения константы
        movf		BARGB2, F
		btfsc		STATUS, Z
		decf		BARGB1, F
		decf		BARGB2, F

ShowX		
        movlw		BEXP
        call		Copy_To_A
		
		call		BCD
		call		SecLine
		movlw		BCD1
		call		DispBCD
		call		DispDot
		movlw		BCD1
		call		DispBCD
		movlw		BCD0
		call		DispBCD
		movlw		BCD0
		call		DispBCD
		
		call		Delay_05_sec
		return

;=======================================================
;     PIC16 24 BIT FLOATING POINT LIBRARY

#define P16_MAP1 0
#define P16_MAP2 1
        include "math16.inc" 
        include "fp24.a16"   
        
        END

