;=============================================
;Синтезатор 145 мгц
;А.Ю. Денисов <alldn@yahoo.com> Тамбов 1999 г.
;ПЧ=10700.    WDT OFF.	 F_RC_osc=1.2 мГц.
;
;=============================================
;порты
;
indf	equ	00  ;указатель косвенной адресации
tmr0	equ	01  ;таймер
pcl	equ	02  ;счетчик команд
stat	equ	03  ;регистр состояния status
fsr	equ	04  ;регистр косвенной адресации
;
port_a	equ	05  ;порт А
port_b	equ	06  ;порт В
;
;=============================================
;регистры
;
step	equ	0E  ;шаг перестройки
count	equ	0F  ;счетчик
count1	equ	10  ;счетчик
rotate	equ	11  ;ротация DATA
cross	equ	12  ;признак ретранслятора
;
H_mulplr  equ	13  ;Старший байт 16-битного множимого
L_mulplr  equ	14  ;Младший байт 16-битного множимого
mulcnd	 equ	15  ;8-битный множитель
;
R0	equ	16  ;
R1	equ	17  ;на
R2	equ	18  ;индикаторе
;
H_byte	equ	19  ; буфер
M_byte	equ	1A  ; преобразования
L_byte	equ	1B  ;
;
rxhi	equ	1C  ;делитель
rxlo	equ	1D  ;приема
;
txhi	equ	1E  ;делитель
txlo	equ	1F  ;передачи
;
;=============================================
;Макросы
;
jnz	macro	metka
	btfss	stat,2
	goto	metka
	endm
;
jz	macro	metka
	btfsc	stat,2
	goto	metka
	endm
;
jnc	macro	metka
	btfss	stat,0
	goto	metka
	endm
;
jc	macro	metka
	btfsc	stat,0
	goto	metka
	endm
;
;=============================================
	list p=16F84
       __CONFIG 03FF3H
;=============================================
;************ SUBROUTINES ********************
;=============================================
;
	org	0
	goto	start
;
;Начальная инициализация
init
	movlw	10	 ;задержка
	movwf	count1	 ;для
init2			 ;инициализации
	movlw	0xFF	 ;индикатора
	movwf	count	 ;HT1610
init1			 ;
	decfsz	count,f  ;
	goto	init1	 ;
			 ;
	decfsz	count1,f ;
	goto	init2	 ;
init3
	movlw	0fh	 ;
	movwf	fsr	 ;
clear			 ;начальное
	clrf	indf	 ;обнуление
	incf	fsr,f	 ;служебных
	btfss	fsr,5	 ;ячеек
	goto	clear	 ;
;
	clrf	fsr	 ;выбор 0 банка
;
	movlw	0x71	 ;
	movwf	txhi	 ;передача
	movlw	0x84	 ;145.300/5
	movwf	txlo	 ;
;
	movlw	0x69	 ;
	movwf	rxhi	 ;прием
	movlw	0x28	 ;(145.300-10.7)/5
	movwf	rxlo	 ;
;
	retlw	0	 ;выход из п\программы.
;
;=============================================
;Выдать байт на индикатор
displ
	movwf	rotate	  ;байт из W в файл rotate
	clrf	count	  ;загрузить 8
	bsf	count,3   ;	в счетчик бит.
	bcf	stat,0	  ;сброс cary
displ1
	clrf	stat
	rlf	rotate,f  ;сдвиг rotate влево через C
	btfsc	stat,0	     ;если Cary=0 skip
	bsf	port_b,5  ;установить DATA=1
	btfss	stat,0	     ;если Сary=1 skip
	bcf	port_b,5  ;уст. DATA=0
	nop
	bsf	port_b,4  ;CLK=1 _-
	nop
	bcf	port_b,4  ;   =0   -_ тактовый импульс
	decfsz	count,f   ;проверить счетчик бит.
	goto	displ1	  ;не равен 0. Следующий бит.
;
	retlw	0	  ;выход из п\программы.
;
;=============================================
;Вкл/откл режима ретранслятора
retrans
	movf	cross,f ;ретранслятор включен?
	jnz	init3	;да, нужно выключить
	movlw	0xE0	;иначе нужно
	movwf	cross	;включить
;
	movlw	0x71  ;
	movwf	txhi  ;передача
	movlw	0x6B  ;145.175/5
	movwf	txlo  ;
;
	movlw	0x69  ;
	movwf	rxhi  ;прием
	movlw	0x87  ;(145.775-10.7)/5
	movwf	rxlo  ;
;
	retlw	0	  ;выход из п\программы.
;
;=============================================
;Плюс 25 килогерц
plus25
	movf	step,w
	addwf	rxlo,f
	jnc	pl1
	incf	rxhi,f
pl1
	movf	step,w
	addwf	txlo,f
	jnc	pl2
	incf	txhi,f
pl2
	retlw	0	  ;выход из п\программы.
;
;=============================================
;Минус 25 килогерц
minus25
	movf	step,w
	subwf	rxlo,f
	jc	min1
	decf	rxhi,f
min1
	movf	step,w
	subwf	txlo,f
	jc	min2
	decf	txhi,f
min2
	retlw	0	  ;выход из п\программы.
;
;=============================================
;Плюс 100 килогерц
plus100
	movf	step,w
	movwf	count
	bcf	stat,0
	rlf	count,f
	rlf	count,w
	addwf	rxlo,f
	jnc	pl21
	incf	rxhi,f
pl21
	movf	step,w
	movwf	count
	bcf	stat,0
	rlf	count,f
	rlf	count,w
	addwf	txlo,f
	jnc	pl22
	incf	txhi,f
pl22
	retlw	0	  ;выход из п\программы.
;
;=============================================
;Минус 100 килогерц
minus100
	movf	step,w
	movwf	count
	bcf	stat,0
	rlf	count,f
	rlf	count,w
	subwf	rxlo,f
	jc	min21
	decf	rxhi,f
min21
	movf	step,w
	movwf	count
	bcf	stat,0
	rlf	count,f
	rlf	count,w
	subwf	txlo,f
	jc	min22
	decf	txhi,f
min22
	retlw	0	  ;выход из п\программы.
;
;=============================================
;Подтверждение нажатия клавиши
sound
	movlw	.50
	movwf	count
sound2
	bsf	port_b,6  ;_i-
;
;задержка --------------------------------
	movlw	.10
	movwf	count1
sound1
	decfsz	count1,1    ;задержка ~2ms
	goto	sound1
;
	bcf	port_b,6  ; -i_
;
;задержка --------------------------------
	movlw	.10
	movwf	count1
sound11
	decfsz	count1,1    ;задержка ~2ms
	goto	sound11
;
	decfsz	count,1
	goto	sound2
;
	retlw	0	  ;выход из п\программы.
;=============================================
;Установить частоту в 1508PL1
setfreq
	movlw	4	   ;выдать в 1508ПЛ1
	call	send	   ;1й байт=4 (делитель на 2000)
	movfw	count1
	movwf	fsr
	movfw	0
	call	send	   ;
	incf	count1,f
	movfw	count1
	movwf	fsr
	movfw	0
	call	send	   ;
strob
	bsf	port_a,2   ;1 _-
	nop
	bcf	port_a,2   ;0	-_
;
	retlw	0	  ;выход из п\программы.
;
;=============================================
;Выдать байт из rotate последовательно в 1508PL1
send
	movwf	rotate	  ;байт из W в файл rotate
	clrf	count	  ;загрузить 8
	bsf	count,3   ;	в счетчик бит.
	bcf	3,0	  ;сброс cary
next
	rlf	rotate,f  ;сдвиг rotate влево через C
	btfsc	3,0	  ;если Cary=0 skip
	bsf	port_a,0  ;установить DATA=1
	btfss	3,0	  ;если Сary=1 skip
	bcf	port_a,0  ;уст. DATA=0
	nop
	bsf	port_a,1  ;CLK=1 _-
	nop
	bcf	port_a,1  ;   =0   -_ тактовый импульс
	decfsz	count,1   ;проверить счетчик бит.
	goto	next	  ;не равен 0. Следующий бит.
	retlw	0	  ;выход из п\программы.
;
;=============================================
;Преобразование bin to BCD
;
b2_bcd
	bcf	stat,0	  ; clear the carry bit
	movlw	.24
	movwf	count
	clrf	R0
	clrf	R1
	clrf	R2
loop16	rlf	L_byte,f
	rlf	M_byte,f
	rlf	H_byte,f
	rlf	R2,f
	rlf	R1,f
	rlf	R0,f
;
	decfsz	count,f
	goto	adjDEC
;
; заменяем нули на 0xA для LCD индикатора
	movlw	0x0F
	andwf	R2,0
	jnz	next1
	movlw	0x0A
	iorwf	R2,f
next1
	movlw	0xF0
	andwf	R2,0
	jnz	next2
	movlw	0xA0
	iorwf	R2,f
next2
	movlw	0x0F
	andwf	R1,0
	jnz	next3
	movlw	0x0A
	iorwf	R1,f
next3
	retlw	0
;
adjDEC
	movlw	R2
	movwf	fsr
	call	adjBCD
;
	movlw	R1
	movwf	fsr
	call	adjBCD
;
	movlw	R0
	movwf	fsr
	call	adjBCD
;
	goto	loop16
;
adjBCD	movlw	3
	addwf	0,W
	movwf	count1
	btfsc	count1,3  ; test if result > 7
	movwf	0
	movlw	30
	addwf	0,W
	movwf	count1
	btfsc	count1,7  ; test if result > 7
	movwf	0	  ; save as MSD
;
	retlw	0
;
;=============================================
; Умножение 16-битного числа на 8-битное
;
m16x8
	clrf	H_byte
	clrf	M_byte
	clrf	L_byte
	movlw	.16
	movwf	count
	movf	mulcnd,w
	bcf	stat,0	  ; Clear the carry bit in the
loop			  ; status Reg.
	rrf	H_mulplr,f
	rrf	L_mulplr,f
	btfsc	stat,0
	addwf	H_byte,f
	rrf	H_byte,f
	rrf	M_byte,f
	rrf	L_byte,f
	decfsz	count,f
	goto	loop
;
	retlw	0
;
;=============================================
; Изменение шага перестройки 5 <-> 25 килогерц
;
newstep
	movlw	4
	xorwf	step,f
	goto	hotstart
;
;=============================================
;************ MAIN PROGRAM *******************
;=============================================
start
	bsf	stat,5	 ;для 16F84
	movlw	0
	movwf	01h
	movlw	8
	movwf	port_a
	movlw	08Fh
	movwf	port_b
	bcf	stat,5

	call	init	   ;инициализация
	movlw	5
	movwf	step
;
	goto	hotstart
;
;опрос клавиш
begin
	movf	port_b,w   ;из port_b в W
	andlw	8f	   ;маскируем выходные порты
	xorlw	0f	   ;есть нажатая клавиша?
	btfsc	stat,2	   ;
	goto	begin

	movlw	10	   ;
	movwf	count1	   ;
loop2			   ;
	movlw	0xFF	   ;
	movwf	count	   ;
loop1			   ;
	decfsz	count,f    ;задержка (антидребезг)
	goto	loop1	   ;
			   ;
	decfsz	count1,f   ;
	goto	loop2	   ;
;
;	     еще раз смотрим нажатие клавиши
	movf	port_b,w   ;из port_b в W
	andlw	8f	   ;маскируем выходные порты
	xorlw	0f	   ;есть нажатая клавиша?
	btfsc	stat,2	   ;
	goto	begin
;
; обработка нажатия клавиши ----------------------
	movf	port_b,w   ;читаем из port_b в W
	movwf	rotate	   ;запоминаем в rotate
	andlw	0x03
	jz	retrans1

	movf	rotate,w
	andlw	0x0C
	jz	newstep

	rlf	rotate,w
	jc	transmit

	rrf	rotate,f
	jnc	pl25

	rrf	rotate,f
	jnc	mn25

	rrf	rotate,f
	jnc	pl100

	call	minus100   ;минус 100 кгц
hotstart
	call	sound	   ;писк
	movlw	rxhi	   ;установка относительной
	movwf	count1	   ;адресации
	call	setfreq    ;установка частоты
; прибавим ПЧ для вывода на индикатор
;
	movlw	0x5C	   ;загружаем первое слагаемое
	movwf	L_mulplr   ;равное 10700/5
	movlw	0x08
	movwf	H_mulplr
;
	movf	rxlo,w	   ;второе слагаемое равное
	addwf	L_mulplr,f ;(частота - ПЧ)/5
	jnc	hot1
	incf	H_mulplr,f
hot1
	movf	rxhi,w
	addwf	H_mulplr,f
hot2
	movlw	.5	       ;умножаем на 25
	movwf	mulcnd
	call	m16x8
	call b2_bcd   ;переводим в дв.-десятичный вид
;	с исправлениями для индикатора HT1610
;
;			 и выводим на индикатор
	movf	cross,w ;признак ретранслятора
	call	displ	;
	movlw	0	; пробел
	call	displ	;
	movf	R0,w	; частота
	call	displ	;
	movf	R1,w	;
	call	displ	;
	movf	R2,w	;
	call	displ	;
;
keyoff			   ;ждем отжатие клавиши
	movf	port_b,w   ;из port_b в W
	andlw	8f	   ;маскируем выходные порты
	xorlw	0f	   ;есть нажатая клавиша?
	jnz	keyoff
;
	movlw	10
	movf	count1,f
koff2
	movlw	0xFF
	movf	count,f
koff1
	decfsz	count,f
	goto	koff1

	decfsz	count1,f
	goto	koff2

	goto	begin
;
retrans1		   ;ретранслятор on/off
	call	retrans
	goto	hotstart
;
pl25			   ;плюс 25 кгц
	call	plus25
	goto	hotstart
;
mn25			   ;минус 25 кгц
	call	minus25
	goto	hotstart
;
pl100			   ;плюс 100 кгц
	call	plus100
	goto	hotstart
;
transmit
	movlw	txhi	   ;установка относительной
	movwf	count1	   ;адресации
	call	setfreq    ;установка частоты
;
	movf	txlo,w	   ;переносим множимое
	movwf	L_mulplr
	movf	txhi,w
	movwf	H_mulplr
;
	movlw	.5	       ;умножаем на 25
	movwf	mulcnd
	call	m16x8
	call b2_bcd  ;переводим в дв.-десятичный вид
;	с исправлениями для индикатора HT1610
;	и выводим на индикатор
	movf	cross,w ;признак ретранслятора
	call	displ
;
	movlw	0	; пробел
	call	displ
;
	movf	R0,w	; частота
	call	displ
	movf	R1,w
	call	displ
	movf	R2,w
	call	displ
;
keyoff1     ;ждем отжатие клавиши
	movf	port_b,w   ;из port_b в W
	andlw	8f	   ;маскируем выходные порты
	xorlw	0f	   ;есть нажатая клавиша?
	btfss	stat,2	   ;
	goto	keyoff1

	movlw	10
	movf	count1,f
koff12
	movlw	0xFF
	movf	count,f
koff11
	decfsz	count,f
	goto	koff11

	decfsz	count1,f
	goto	koff12
;
	goto	hotstart
	end
