;
;  Copyright (C) 2000 Jesper Hansen <jesperh@telia.com>.
;
;  This program is free software; you can redistribute it and/or
;  modify it under the terms of the GNU General Public License
;  as published by the Free Software Foundation; either version 2
;  of the License, or (at your option) any later version.
;
;  This program is distributed in the hope that it will be useful,
;  but WITHOUT ANY WARRANTY; without even the implied warranty of
;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;  GNU General Public License for more details.
;
;  You should have received a copy of the GNU General Public License
;  along with this program; if not, write to the Free Software Foundation, 
;  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
;
;
;*******************************************************************
;*******************************************************************
;
;Description
;
; Poor-mans DDS Synthesizer
; 
; Author = Jesper Hansen
; Modification = EW6GB, RN3AUS (PSK-mode added and auto-beacon)
; Target = ATTINY2313
; Date   = 2013-07-24
;
;
;
; PB0..7 = D/A Data out
;
; PD0		RXD
; PD1		TXD
; PD3		Beacon On-Off button
; PD4		Timer0 in
; PD5		Timer1 out
; PD6	    RX/TX control 
;

;*******************************************************************
;*******************************************************************
;
;
;
; Output frequency (using 24 bit accumulator) :
;
;	f = deltaPhase * fClock/2^24
;
;   fClock is in this case the CPU clock divided by the
;	number of cycles to output the data ( 11 cycles )
;
;	for 12,8 MHz oscillator fClock/11/2^24=0,069358132102272727272727272727273
; 		and 
; 		f = r24/r25/r26 * 0,069358132102272727272727272727273
;
;
;	fMax (theoretical) = 0.5 * fClock
;
; 		

;******************************************************************************
; start of code
;******************************************************************************


.include <tn2313def.inc>


    .cseg 

	.org 0
		rjmp	RESET
	.org INT1addr
		rjmp	EXT_INT1
	.org URXCaddr
		rjmp	RX_COMPLETE_INT
	.org OVF0addr
		rjmp	TIM0_OVF
	.org OVF1addr
		rjmp	TIM1_OVF
	.org OC1Aaddr
		rjmp	TIM1_COMPA
	.org OC0Baddr
		rjmp	TIM0_COMPB

;******************************************************************************
; code
;******************************************************************************


RESET:
		ldi		r16, RAMEND
		out		SPL, r16		; setup stack pointer

;---------- ВНИМАНИЕ! Константа, записываемая в UBRR, зависит от частоты примененного опорного генератора
;---------- здесь приведено значение для частоты 12800000 Гц - 0x52.
		ldi		r16,0x52		; set uart speed to 9,6 kbps 12M8
		;ldi		r16,0x6a		; set uart speed to 9,6 kbps 16M384
		;ldi		r16,0x65		; set uart speed to 9,6 kbps 15M6
		;ldi		r16,0x67		; set uart speed to 9,6 kbps 16M
		;ldi		r16,0x82		; set uart speed to 9,6 kbps 20M
		;ldi		r16,0x52		; set uart speed to 9,6 kbps 12M800175
		;ldi		r16,0x40		; set uart speed to 9,6 kbps 10M
		;ldi		r16,0x54		; set uart speed to 9,6 kbps 13M
		;ldi		r16,0x57		; set uart speed to 9,6 kbps 13M5
		;ldi		r16,0x4d		; set uart speed to 9,6 kbps 12M
;----------------------------------------------------------------------------
		out		UBRR,r16

		ldi		r16,0x98		; enable RXint and enable tx/rx
		out		UCR,r16

		clr 	r16
		sbr		r16,(1<<PD5)+(1<<PD6)+(1<<PD2)
		out		DDRD,r16		; PD5, PD6, PD2 bit as output
		clr		r16
		sbr  	r16,(1<<PD3)+(1<<PD4)
		out		PORTD,r16		; as input
	

		ser		r16				; 
		out		DDRB,r16		; set all PORTB bits as output

		; перед чтением кнопки задержка на 0,5 сек, чтобы после включения все емкости зарядились
		ldi r20,0x00
		ldi r21,0x88
		ldi r22,0x13
		rcall DELAY

		; set timers (for TX-timeout)
		rcall	setTimersNoBeacon

		; enable interrupt from INT1
		clr		r16
		ldi		r16,(1<<INT1)
		out 	GIMSK,r16
		;out		EIFR,r16
		ldi		r16,0b00000100 ;any change on int1
		out		MCUCR,r16


		; set sinewave output as default		
		;ldi		r31,high(sine*2)	; setup Z pointer hi
		;ldi		r30,low(sine*2)		; setup Z pointer lo
		ldi		r31,high(no_sine*2)	; setup Z pointer hi
		ldi		r30,low(no_sine*2)		; setup Z pointer lo


		; clear accumulator 
		ldi 	r29,0x00		; clear accumulator 
		ldi 	r28,0x00		; clear accumulator 

		; setup adder registers		
				;---- 12M8 ------
		ldi 	r24,0x00    ;  setup adder value	; младший байт
		ldi 	r25,0x40    ;  to 137500 kHz
		ldi 	r26,0x1e    ;  						; старший байт
		;---- 16M384 ----	
		;ldi 	r24,0x00    ;  
		;ldi 	r25,0xa2    ;  
		;ldi 	r26,0x17    ; 
		;---- 15M6 ----	
		;ldi 	r24,0x0d    ;  
		;ldi 	r25,0xd2    ;  
		;ldi 	r26,0x18    ;
		;---- 16M ----	
		;ldi 	r24,0x33    ;  
		;ldi 	r25,0x33    ;  
		;ldi 	r26,0x18    ; 
		;---- 20M ----	
		;ldi 	r24,0x79    ;  
		;ldi 	r25,0xa2    ;  
		;ldi 	r26,0x13    ; 
		;---- 12M800175 ----	
		;ldi 	r24,0xe5    ;  
		;ldi 	r25,0x3f    ;  
		;ldi 	r26,0x1e    ;
		;---- 10M ----	
		;ldi 	r24,0x52    ;  
		;ldi 	r25,0xb8    ;  
		;ldi 	r26,0x26    ; 
		;---- 13M ----	
		;ldi 	r24,0xdd    ;  
		;ldi 	r25,0xc8    ;  
		;ldi 	r26,0x1d    ; 
		;---- 13M5 ----	
		;ldi 	r24,0x76    ;  
		;ldi 	r25,0xae    ;  
		;ldi 	r26,0x1c    ;    						
		;---- 12M ----	
		;ldi 	r24,0x44    ;  
		;ldi 	r25,0x44    ;  
		;ldi 	r26,0x20    ; 
;----------------------------------------------

		ldi		r16, 0x00
		mov		r10,r16
		ldi		r20, 0x00	; phase shift - default=0
		ldi		r21, 0x00	;
		ldi		r22, 0x00	;

		ldi r19,0x00		; если r19=0 маяк выключен, иначе включен

		;регистр GPIOR0 - хранение состояния синтезатора
		;биты:  0 - PTT
		;		1 - TONE (в данной версии не используется)
		;		2 - BEACON on/off
		;		3 - режим программирования eeprom
		;		4 - 24/32 bit adder
		;		5,6,7 - версия прошивки (старая 0, текущая на данный момент 3)
		ldi r16,0b01100000
		out GPIOR0,r16

		;если при старте нажата кнопка - это режим маяка, установки немного другие
		sbic PIND,PD3
		rjmp START
BEACON:
		;прочитать из еепром константы для таймеров (длит. посылки) и частоту
		; r18 - текущий адрес чтения из eeprom
		; r13 - адрес начала следующего режима
		; r19 - вид модуляции: "O"-Opera, "D"-DFCW, "Q"-QRSS, "W"-WSPR, "B"-BPSK, "N"-пауза, "E"-запись в eeprom
		; r1,r2,r3 - 	f0 
		; r4,r5,r6 - 	f1 частоты посылок в DFCW 
		; r7,r8,r9 - 	f2				   и WSPR
		; r10,r11,r12 - f3
		; r14 - показывает бит внутри байта информации на передачу.
		; r15 - адрес начала данных для текущего режима
		; r17 - количество посылок
		clr r15
		ldi r18,0x00
		out EEAR,r18
		rcall LOAD_SET
		; если установки для маяка загрузились успешно, включаем PTT
		cpi r19,0
		breq START
		 sbi GPIOR0,2 ; beacon - on
		 sbi PORTD,PD6			; PD6=1
		 sbi GPIOR0,0 ; ptt-on
		 
		 ;рарешаем счетчикам формировать такты на передачу (режим сравнения вкл)
		 rcall	setBeaconTimers
		 rcall	TIM0_COMPB
		;ldi r16,(1<<OCF0B)
	  	;out TIFR,r16 ; искусственно вызываем прерывание, чтобы маяк начался немедленно


START:
		sei						; global enable interrupts

; main loop
;
;	r28,r29,r30 is the phase accumulator
;  	r24,r25,r26 is the adder value determining frequency
;   r20,r21,r22 is the adder value determining phase shift (for PSK)
;
; 	add value to accumulator
;	load byte from current table in ROM
;	output byte to port
;	repeat 
;


LOOP1:
	cli							; 1 ; interrupt disable
		add		r28,r24			; 1
		adc		r29,r25			; 1
		adc		r30,r26			; 1
		lpm		    			; 3
		out		PORTB,r0		; 1
	sei							; 1    interrupt enable							; 
		rjmp	LOOP1			; 2 => 11 cycles


;	32 bit adder mode for precision freq; no autobeacon mode
;	r12,r28,r29,r30 is the phase accumulator
;  	r11,r24,r25,r26 is the adder value determining frequency
;   r10,r20,r21,r22 is the adder value determining phase shift (for PSK)
LOOP32:
	cli							; 1 ; interrupt disable
		add		r12,r11			; 1
		adc		r28,r24			; 1
		adc		r29,r25			; 1
		adc		r30,r26			; 1
		lpm		    			; 3
		out		PORTB,r0		; 1
	sei							; 1    interrupt enable							; 
		rjmp	LOOP32			; 2 => 12 cycles


; подпрограмма задержки
; r22,r21,r20 - делитель счетчика, N=12800000/5 * T сек
DELAY:	subi r20,1
		sbci r21,0
		sbci r22,0
		brcc DELAY
		ret
;**********************************************************************
; communication functionality
;**********************************************************************

;
; get char in r16
;
get_char:
		in 		r16,USR			; wait for a byte to be ready	; 1
		sbrs	r16,7			; ready ?						; 3
		rjmp	get_char		; no, wait some more
		in		r16,UDR			; get the byte					; 1
		ret						; and return					; 4 = 9
		
;
; send char in r16
;
send_char:
		push	r16				; save r16								; 2
send_c2:
		in 		r16,USR			; wait for the transmitter to be ready	; 1
		sbrs	r16,5			; ready ? 								; 3
		rjmp	send_c2			; no, wait some more
		pop		r16				; restore r16							; 2
		out		UDR,r16			; send char								; 1
		ret						; ans return							; 4 = 13

;
; send the current frequency to the PC
; as a 5 byte sequence :
; 'F' folowed by a 32 bit phase accumulator value
;
;
send_data:
		push	r16				; save r16								; 2
		ldi		r16,'F'			; flag									; 1
		rcall	send_char												; 3 + 13 = 16

		in		r16, GPIOR0		; zero byte for 32-bit compatibility	; 1 ; номер версии и состояние PTT, tone
		rcall	send_char		; MSB									; 3 + 13 = 16 

		mov		r16,r26													; 1
		rcall	send_char		; high add								; 3 + 13 = 16

		mov		r16,r25													; 1
		rcall	send_char		; mid add								; 3 + 13 = 16

		mov		r16,r24													; 1
		rcall	send_char		; low add								; 3 + 13 = 16

		ldi		r16,0x0a												; 1
		rcall	send_char		; terminator							; 3 + 13 = 16
		pop		r16														; 2
		ret																; 4 
;																		; All = 105 cycles

send_data_beacon:
		push r16
		ldi r16, 'B'
		rcall send_char
		mov r16, r19
		rcall send_char
		mov r16, r26
		rcall send_char
		mov r16, r25
		rcall send_char
		mov r16, r24
		rcall send_char
		in r16,OCR1AH 
		rcall send_char
		in r16,OCR1AL 
		rcall send_char
		in r16,OCR0B 
		rcall send_char
		mov r16,r17
		rcall send_char
		in		r16, GPIOR0
		rcall	send_char
		pop r16
		ret


; add 1 to the phase accumulator		
;up_one:
	;	adiw	r24,1	
	;	clr		r23
	;	adc		r26,r23
	;	ret

; subtract 1 from the phase accumulator		
;down_one:
	;	sbiw	r24,1		
	;	clr		r23
	;	sbc		r26,r23
	;	ret

; 
; read in 4 characters from the serial link
;
read_4:
		rcall	get_char		; read and ignore bits 32..24
		mov		r11,r16
		rcall	get_char		; read bits 23..16
		mov		r26,r16
		rcall	get_char		; read bits 15..8
		mov		r25,r16
		rcall	get_char		; read bits 7..0
		mov		r24,r16
	 ; если частота больше 200 кГц - поднимаем PD2=1 иначе PD2=0
	 sbi PORTD,PD2					; PD2=1
     in r16, GPIOR0
	 andi r16, (1<<4) ; режим 32 бита или 24 бита? (32 бита GPIOR0,4 =1)
	 cpi r16, 0x00 
	 breq MR24
	 cpi r26, 0x30  ; 32 бита
	 brsh MR41
	 cbi PORTD,PD2					; PD2=0
	 ret
MR24: cpi r26, 0x2c  ; 24 бита
	 brsh MR41
	 cbi PORTD,PD2					; PD2=0
MR41:
		ret

; принять коды для 4-х частот и сохранить в регистрах
read_12:
		rcall	get_char
		mov		r1,r16
		rcall	get_char
		mov		r2,r16
		rcall	get_char
		mov		r3,r16
		
		rcall	get_char
		mov		r4,r16
		rcall	get_char
		mov		r5,r16
		rcall	get_char
		mov		r6,r16
		
		rcall	get_char
		mov		r7,r16
		rcall	get_char
		mov		r8,r16
		rcall	get_char
		mov		r9,r16
		
		rcall	get_char
		mov		r10,r16
		rcall	get_char
		mov		r11,r16
		rcall	get_char
		mov		r12,r16
		ret	

; read 4 character from the serial link and add to phase accumulator
; ---- Первый байт игнорируется, второй - младший байт, третий - средний, четвертый - старший байт.
read_ph_4:
		rcall	get_char		; read and ignore bits 32..24 
		mov		r10,r16
		rcall	get_char		; read bits 7 ..0	
		mov		r20,r16										
		rcall	get_char		; read bits 15..8
		mov		r21,r16							
		rcall	get_char		; read bits 23..16
		mov		r22,r16									
		ret										

			
;																
;
; Interrupt routine for incoming bytes on the RS232 link
;
	
RX_COMPLETE_INT:
		push	r16	
		clr		r16				; restart TIM1
		out		TCNT0,r16

		in 		r16,UDR	
		
tx_0:	
		cpi		r16,'P'				; phase shift, no report
		brne	tx_1
		add		r12,r10
		adc		r28,r20				; phase shift: accumulator (r28,r29,r30) + delta_ph (r20,r21,r22)
		adc		r29,r21
		adc		r30,r22
		pop		r16
		reti
tx_1:		
		cpi		r16,'1'				; request sinewave output, no report
		brne	tx_2										
		ldi		r31,high(sine*2)	; setup Z pointer hi
		nop;ldi		r30,low(sine*2)		; setup Z pointer lo
		pop		r16
		reti
tx_2:
		cpi		r16,'0'				; request no sinewave output; no report
		brne	tx_3											
		ldi		r31,high(no_sine*2)		; setup Z pointer hi
		nop;ldi		r30,low(no_sine*2)		; setup Z pointer lo
		pop 	r16
		reti
tx_3:
		cpi		r16,'S'				; frequency setting	- no verbose	
		brne	tx_4										
		rcall	read_4		
		pop 	r16
		reti				
		
tx_4:	
		cpi		r16,'s'				; frequency setting		
		brne	tx_5										
		rcall	read_4		
		rjmp	tx_exit	
									     
tx_5:
;		cpi		r16,'+'				; up one
;		brne	tx_6
	;	rcall	up_one
 ;   sbi PORTD,PD2					; PD2=1
;		rjmp	tx_exit		
tx_6:
		cpi		r16, 0xf0		; частота F0
		brne	tx_7
		mov	r26,r1
		mov	r25,r2
		mov	r24,r3
		pop 	r16
		reti	
tx_7:
		cpi		r16, 0xf1		; F1
		brne	tx_8
		mov	r26,r4
		mov	r25,r5
		mov	r24,r6	
		pop 	r16
		reti
tx_8:
;		cpi		r16,'-'				; down one
;		brne	tx_9
	;	rcall	down_one
;    sbi PORTD,PD2					; PD2=0
;		rjmp	tx_exit					
tx_9:
		cpi		r16,0xf2		; F2
		brne	tx_10
		mov	r26,r7
		mov	r25,r8
		mov	r24,r9			
		pop 	r16
		reti
tx_10:
		cpi		r16, 0xf3		; F3
		brne	tx_11
		mov	r26,r10
		mov	r25,r11
		mov	r24,r12		
		pop 	r16
		reti
tx_11:
		cpi		r16,'?'				; just force a reply
		brne	tx_12
		rjmp	tx_exit								
tx_12:	
		cpi		r16,'R'			; 
		brne	tx_13
		cbi PORTD,PD6			; PD6=0
		cbi GPIOR0,0 ; ptt-off
		rjmp	tx_exit
tx_13:	
		cpi		r16,'T'			; 
		brne	tx_14		
		sbi PORTD,PD6			; PD6=1
		sbi GPIOR0,0 ; ptt-on
		rjmp	tx_exit
tx_14:
		cpi		r16,'&'			; начало записи в eeprom			; 
		brne	tx_15
		sbic 	PIND, PD3		; разрешаем запись только если кнопка нажата
		 rjmp tx_15 ;не нажата - игнорируем
		
		clr		r16			;запрещаем работу таймеров, чтобы не началась передача маяка
		out		TIMSK, r16
	
		ldi		r18,0x00
		ldi		r19,'E'			; режим маяка - запись в eeprom
		sbi GPIOR0,3
		ldi		r16,'&'
		rcall	send_char
		pop		r16
		reti
tx_15:
		cpi		r16,'/'			; запись в eeprom последующего байта			; 
		brne	tx_16
		cpi		r19,'E'			; если не было предварительно команды на запись - не записываем			; 
		brne	tx_16
		rcall	get_char		; читаем байт
		rcall	WRITE_EEP		; и записываем его
		ldi		r16,'W'
		cpi		r18, 0x81		; свободное место еще есть?
		brsh	tx_15_1
		rcall	send_char		; в ответ выдаем W
		pop		r16
		reti
tx_15_1:ldi		r16,'!'
		rcall	send_char		; место в eeprom кончилось, выдаем "!"
		pop		r16
		reti
tx_16:	
		cpi		r16,'#'			; конец записи в eeprom			; 
		brne	tx_17
		cpi		r19,'E'			; если не было предварительно команды на запись - игнорируем и команду окончания записи			; 
		brne	tx_17
		ldi		r18,0x00
		ldi		r19, 0			; режим маяка - сбросить режим записи
		cbi GPIOR0,3
		
		rcall setTimersNoBeacon ;разрешить работу таймеров

		ldi		r16,'#'
		rcall	send_char
		pop		r16
		reti
tx_17:  
		cpi		r16, 'G'		; запуск маяка ("GO")
		brne tx_18
		clr r15
		ldi r18,0x00
		rcall LOAD_SET
		; если установки для маяка загрузились успешно, включаем PTT
		cpi r19,0
		breq tx_18_1
		 sbi GPIOR0,2
		 sbi PORTD,PD6			; PD6=1
		 sbi GPIOR0,0
		 rcall setBeaconTimers
		rcall send_data_beacon
		cbi GPIOR0,4
		rcall	TIM0_COMPB	; искусственно вызываем прерывание, чтобы маяк начался немедленно
		pop		r16
		pop r0
		pop r0
		rjmp LOOP1
tx_18:
		cpi r16, 'H'			; остановить маяк ("HALT")
		brne tx_19
tx_18_1:clr r15
		ldi r18,0x00
		ldi r19,0x00
		cbi GPIOR0,2
		out EEAR,r18
		rcall setTimersNoBeacon
		ldi		r31,high(no_sine*2)		; setup Z pointer hi
		ldi		r30,low(no_sine*2)		; setup Z pointer lo
		cbi GPIOR0,1
		cbi PORTD,PD6			; PD6=0
		cbi GPIOR0,0
		rjmp tx_exit
; unknown command, just ignore it
tx_19:
		cpi r16, 'L'		; загрузить 4 частоты для WSPR ("LOAD")
		brne tx_20
		rcall read_12
		rjmp tx_exit
tx_20:
		cpi		r16,'p'				; phase shift - for PSK	
		brne	tx_21				; 						
		rcall	read_ph_4									
		rjmp	tx_exit	

tx_21:	
		cpi		r16,'4'				; enable 32 bit adder (4 bytes)
		brne	tx_22
		sbi GPIOR0,4
		rcall	send_data
		pop		r16
		pop r0
		pop r0
		rjmp	LOOP32

tx_22: 
		cpi		r16,'3'				; enable 24 bit adder (3 bytes)
		brne	tx_23
		cbi GPIOR0,4
		rcall	send_data
		pop		r16
		pop r0
		pop r0
		rjmp	LOOP1
tx_23:
; always reply with the current frequency
tx_exit:
		rcall	send_data		; 3 + 105
		pop		r16				; 2
		reti					; 4
;								; All = 9 + 105 = 114 cycles
;--------------------------------------------------------------------------------------------



setTimersNoBeacon:
		push	r16

		clr		r16				; restart TIM1
		out		TCCR1B,r16
		out		TCNT1H,r16		; 
		out		TCNT1L,r16		; 
		out		TCNT0,r16
        ldi		r16,(1<<TOIE0)+(1<<TOIE1) ;разрешены прерывания таймеров по переполнению
		out		TIMSK,r16
		ldi 	r16,0b00000111
		out 	TCCR0B,r16;TIM0 - от входа Т0
		ldi		r16,0b00000101
		out		TCCR1B,r16;TIM1 - от прескалера на 1024
		
		pop		r16
		ret
;---------------------------------------------------------------------------------------------
setBeaconTimers:
		push r16
		clr		r16
		out		TCCR1B,r16
		out		TCNT1H,r16		; 
		out		TCNT1L,r16		; 
		out		TCNT0,r16
		ldi		r16,(1<<TOIE0)+(1<<TOIE1)+ (1<<OCIE1A) +(1<<OCIE0B);разрешены прерывания таймеров по переполнению
		out		TIMSK,r16
		ldi		r16,0b00001100
		out		TCCR1B,r16;TIM1 - от прескалера на 256
		pop r16
		ret
;---------------------------------------------------------------------------------------------
;************** interrupts ***************
TIM0_COMPB:					; длительность посылки истекла, извлечь из памяти след. посылку
							;2 - вход в прерывани
		push r16			;2
		clr r16				;1
		out TCNT0,r16		;1
		cpi r17,1 		  	; 1 еще есть что передавать?
		brsh TC0	; 1 
		 mov r18,r13	; устанавливаем адрес следующего режима
		 rcall LOAD_SET	; нет, нужно загрузить следующий режим
		 rcall send_data_beacon
		 
TC0:	
		dec r17				;1 счетчик посылок
		rcall READ_EEP		;9 + 22 =31
							;31
		cpi		r19,'O'		;1  OPERA
		breq	TC0_1		;1
		cpi		r19,'Q'		;   QRSS
		breq	TC0_1		;35
		rjmp	TC0_2		;
TC0_1:						; 34 сюда попадаем, если режим QRSS или OPERA (работа на одной частоте ООК)
		and r16,r14 		;1 выбрать очередной бит и дать команду
		tst r16				;1 36 бит равен 0?
		breq TC0_bit_zero	;1 -нет  2-да
		 ldi r31,high(sine*2)	;1 setup Z pointer hi
		 nop;ldi r30,low(sine*2)	;1 39setup Z pointer lo; сюда попадаем если бит=1
		 rjmp TC0_set_r14_1		;2 41
TC0_bit_zero:					;38 сюда переходим если бит=0
		ldi	r31,high(no_sine*2)		; 1 setup Z pointer hi
		nop;ldi	r30,low(no_sine*2)		; 1 40 setup Z pointer lo
		nop						;1 41
TC0_set_r14_1:
		dec r18 ; 1 42 если байт не кончился возвращаем счетчик адреса обратно
		lsl r14;rol r14 ;43 1 сдвиг влево. Если байт кончился, то перенос будет равен 1
		brcc TC0_OP_correction ;44 
		 inc r18 ;1 45 кончился - увеличиваем адрес
		 clr r14 ;1 устанавливаем указатель бита в единицу
		 inc r14 ;1
		 rjmp TC0_OP_exit ;2 49
TC0_OP_correction: ;45
		nop
		nop
		rjmp TC0_OP_exit	;2 49


TC0_OP_exit: ;коррекция фазы для ОР и выход
		add		r28, r20
		adc		r29, r21
		adc		r30, r22
		 nop
		 nop
		 nop
		 nop
		 nop
		 nop
		 nop
		pop r16				;2 
		reti				;4 66 - проверено 

TC0_2: 
		; 37
		cpi		r19,'B'		;1  BPSK
		breq	TC0_3		;40 - переход на BPSK

		cpi		r19,'N'		;1  нет излучения, пауза
		breq	TC0_4

		cpi		r19,'D'
		breq	TC0_DF
		cpi		r19,'W'
		breq	TC0_DF

		rjmp TC0_exit	;неизвестно что, выходим отсюда
TC0_DF:
		; здесь нужно загружать частоты (WSPR,DFCW)
		push r17
		clr r17
		push r16
		and r16,r14 		;1 выбрать очередной бит и дать команду
		tst r16				;1 бит равен 0? (z=1)
		pop r16
		breq TC0_DF_z00
		 inc r17			;нет, бит =1
TC0_DF_z00:
		lsl r14				; след разряд
		and r16,r14 		;1 выбрать очередной бит и дать команду
		tst r16				;1 бит равен 0? (z=1)
		breq TC0_DF_z01
		ori r17,0x02
TC0_DF_z01:
		; теперь в r15 - номер частоты.
		dec r18
		lsl r14
		brcc TC0_DF_set
		;если байт кончился, переходим к следующему
		 inc r18
		 clr r14
		 inc r14	
TC0_DF_set:
		mov r16,r17
		pop r17
		 ldi r31,high(sine*2)	;разрешить выход
		 nop;ldi r30,low(sine*2)
		cpi r16,0
		breq TC0_DF_setF0
		cpi r16,1
		breq TC0_DF_setF1
		cpi r16,2
		breq TC0_DF_setF2
		cpi r16,3
		breq TC0_DF_setF3
TC0_DF_setF0:
		mov r26,r1
		mov r25,r2
		mov r24,r3
		rjmp TC0_exit
TC0_DF_setF1:
		mov r26,r4
		mov r25,r5
		mov r24,r6
		rjmp TC0_exit
TC0_DF_setF2:
		mov r26,r7
		mov r25,r8
		mov r24,r9
		rjmp TC0_exit
TC0_DF_setF3:
		mov r26,r10
		mov r25,r11
		mov r24,r12
		rjmp TC0_exit

TC0_4:	; режим паузы, ничего не передается
		ldi	r31,high(no_sine*2)		; 1 setup Z pointer hi
		nop;ldi	r30,low(no_sine*2)
		cbi PORTD,PD6
		clr r16
		bst r16,6
		pop r16
		reti

TC0_3:		; 40 сюда попадаем, если режим BPSK
		and r16,r14 		;1 выбрать очередной бит и дать команду
		tst r16				;1 42 бит равен 0?
		breq TC0_B_zero	;43 1 -нет  44 2-да
		 add		r28,r4	;45
		 adc		r29,r5 ;46
		 adc		r30,r6	;47 фазовый сдвиг без инверсии
		 rjmp TC0_B_set_r14_1	;2 49
TC0_B_zero:					;44 сюда переходим если бит=0
		 add		r28,r20	;45
		 adc		r29,r21 ;46
		 adc		r30,r22	;47 фазовый сдвиг с инверсией
		 nop
		 nop						;1 49
TC0_B_set_r14_1:
		dec r18 ; 1 50 если байт не кончился возвращаем счетчик адреса обратно
		lsl r14;rol r14 ; 51 сдвиг влево. Если байт кончился, то перенос будет равен 1
		brcc TC0_B_correction  
		 inc r18 ;1 53 кончился - увеличиваем адрес
		 clr r14 ;1 устанавливаем указатель бита в единицу
		 inc r14 ;1 55
		 rjmp TC0_B_exit ;2 57
TC0_B_correction: ;53
		ldi r31,high(sine*2);1 разрешить выход
		nop;ldi r30,low(sine*2);1
		rjmp TC0_B_exit	;2 57
TC0_B_exit: ;коррекция фазовой задержки
		nop
		nop
		nop
		pop r16				;2 
		reti				;4 66 - проверено (66)

			
TC0_exit:
		pop r16
		sei
		reti

;--------------------------------------------------------------------------------------------

EXT_INT1:					; нажата/отпущена кнопка
; если это режим маяка, то по короткому нажатию сбрасываем в начало и запускаем передачу
; если не маяк - по короткому включаем/выключаем несущую, по длинному вкл/откл PTT
	;	cli
		push r16
		sbis PIND, PD3
		 rcall BTN_PRESSED	; нажата
		sbic PIND, PD3
		 rcall BTN_RELEASED	;отпущена
		pop r16
;		sei
		reti
;-------------
BTN_PRESSED: ; в момент нажатия сбрасываем и запускаем счетчики, режим сравнения запрещаем
		rcall setTimersNoBeacon
		ret
		
BTN_RELEASED: ;в момент отпускания смотрим сколько счетчики насчитали
		cpi r19,'E'	; если это отпускание кнопки в момент начала записи eeprom, то ничего не делаем
        breq BTN_PTT_OFF 
		cpi r19,0
		brne BTN_REL_BEACON

BTN_REL_NO_BEACON: ;это не маяк 
		;нажатие короткое?
		in r16,TCNT0
		cpi r16,1
		brsh BTN_LONG ; явно длинное (>5 сек)
		in r16, TCNT1L  ;игнорируем
		in r16, TCNT1H  
		cpi r16, 0x32	; порядка секунды
		brsh BTN_LONG	; длинное
		cpi r16 , 0x03  ; а если короче 0,1 сек - то дребезг, игнорируем
		brlo BTN_DREBEZG
		
BTN_SHORT: 	;короткое нажатие
		cpi r31,high(sine*2)
		breq BTN_TONE_OFF	;нужно выключить тон
		;нужно включить тон
		ldi		r31,high(sine*2)
		ldi		r30,low(sine*2)	
		ret
BTN_TONE_OFF:
		ldi		r31,high(no_sine*2)	
		ldi		r30,low(no_sine*2)	
		ret
BTN_LONG:	;длинное нажатие
		sbic GPIOR0,0   
		 rjmp BTN_PTT_OFF ;нужно выключить РТТ
		 ;нужно включить РТТ
		sbi PORTD,PD6			; PD6=1
		sbi GPIOR0,0
		ret
BTN_PTT_OFF:
		cbi PORTD,PD6			; PD6=0
		cbi GPIOR0,0
		ret
BTN_DREBEZG: ;дребезг
		ret
BTN_REL_BEACON:	; маяк 
		ldi r19,0x00
		clr r15
		ldi r18,0x00
		rcall LOAD_SET
		; если установки для маяка загрузились успешно, включаем PTT
		cpi r19,0
		breq BTN_REL_OUT
		 sbi PORTD,PD6			; PD6=1
		 sbi GPIOR0,0
		 rcall setBeaconTimers
		 rcall	TIM0_COMPB
		 ;ldi r16,(1<<OCF0B)
		 ;out TIFR,r16 ; искусственно вызываем прерывание, чтобы маяк начался немедленно

BTN_REL_OUT:
		ret
;--------------------------------------------------------------------------------------------
TIM1_COMPA:					; одинаковый обработчик двух прерываний
TIM1_OVF:											;2 цикла вход в прерывание
		sbi PORTD,PD5		;импульс на бит PIND5  	2 
		;sbi PIND,PD4 ; а это удобно для отладки
		;nop					;	1
		;nop					;	1
		;nop					;   1
		;cbi PORTD, PD5		;сбросили	2 = 9
		;cbi PIND, PD4
		; начинается коррекция фазы DDS 
		sbis GPIOR0,4;	1\2
		 rjmp TIM1_24;  2
		add		r12,r11			; 1
		adc		r28,r24			; 1
		adc		r29,r25			; 1
		adc		r30,r26			; 1

		add		r12,r11			; 1
		adc		r28,r24			; 1
		adc		r29,r25			; 1
		adc		r30,r26			; 1
		nop  
		cbi PORTD, PD5		;сбросили
	    reti				;4 = 24
TIM1_24:
							
		add		r28,r24		;1	
		adc		r29,r25		;1	
		adc		r30,r26		;1

		add		r28,r24		;1	
		adc		r29,r25		;1	
		adc		r30,r26		;1

		cbi PORTD, PD5		;сбросили
		reti				;4  весь обработчик прерывания = 22 цикла

;---------------------------------------------------------------------------------------------
TIM0_OVF:		; TX-timeout - нет никаких команд длительное время - выключаем передатчик
		cbi PORTD, PD6; PD6=0
		cbi GPIOR0,0
		reti

;******************************************************************************
; чтение-запись EEPROM (r18 - адрес, r16 - данные)
;******************************************************************************
READ_EEP:
		cli				; 1
		sbic EECR,EEWE	; 2 
		 rjmp READ_EEP
		andi r18,0b01111111; 1  защита от чтения eeprom по адресу больше 127
		out EEAR, r18	; 1
		sbi EECR,EERE	; 2
		in r16,EEDR		; 1
		inc r18			; 1
		nop				; 1
		sei				; 1
		ret				; 4  Всего=22 - ровно два отсчета

WRITE_EEP:
		cli
		sbic EECR,EEWE
		 rjmp WRITE_EEP
		andi r18,0b01111111	; защита от попытки записи в eeprom по адресу больше 127
		out EEAR, r18
		out EEDR, r16
		sbi EECR,EEMWE
		sbi EECR,EEWE
		inc r18
		sei
		ret 

LOAD_SET:
		push r16
		; так как загружается новое, сигнал выключаем и РТТ опускаем
		ldi	r31,high(no_sine*2)		; 1 setup Z pointer hi
		ldi	r30,low(no_sine*2)
		cbi PORTD,PD6
		cbi GPIOR0,0
		ldi r16,1
		mov r14,r16
		cpi r18, 0x76	; есть место откуда читать? (самая короткая команда=9 байт)
		brsh LS0		; нет - обнуляем счетчик адреса eeprom

LS:		rcall READ_EEP
		cpi r16,0xff	;если eeprom пуст (заполнен 0xff) то режим маяка отменяем
		breq LS7
		mov	r19,r16		; вид модуляции

		rcall READ_EEP
		out OCR1AH,r16 	;timer1	
		rcall READ_EEP
		out OCR1AL,r16 	;timer1
		rcall READ_EEP
		out OCR0B,r16 	;timer0

		rcall READ_EEP
		mov r17,r16		; количество посылок

		rcall READ_EEP
		mov r15,r16		; адрес начала данных

		rcall READ_EEP
		mov r13,r16		; адрес следующего режима

	    cpi r19,'N'	; нет операций, пауза на указанное время
		brne	LS6
		 mov r18,r15
		 pop r16
		 ret
LS6:		
		rcall READ_EEP	; код частоты 3 байта
		mov r26,r16
		mov r1,r16		; и в регистры частоты f0
		rcall READ_EEP	
		mov r25,r16
		mov r2,r16
		rcall READ_EEP	
		mov r24,r16
      	mov r3, r16		
	; если частота больше 200 кГц - поднимаем PD2=1 иначе PD2=0
	 sbi PORTD,PD2					; PD2=1
	 cpi r26, 0x2c 
	 brsh LS61
	 cbi PORTD,PD2					; PD2=0
LS61: 
		cpi		r19,'O'		; OPERA
		brne	LS1

		rcall READ_EEP		;код фазы для коррекции ОР
		mov r20,r16
		rcall READ_EEP
		mov r21,r16
		rcall READ_EEP
		mov r22, r16

		mov r18,r15
		 sbi PORTD,PD6	; поднять РТТ (если еще не поднято было)
		 sbi GPIOR0,0
		 
		pop r16
		ret

LS0:	ldi r18,0
		rjmp LS

LS7:	ldi r19,0
		cpi r18,1
		brne LS0	;если счетчик не указывает на самое начало, значит просто кончились записи, возвращаемся в начало и повторяем вновь
					;а если по нулевому адресу пусто, значит в eeprom вообще ничего нет - маяк откл
		pop r16
		ret

LS1:	cpi		r19,'B'		; BPSK
        brne	LS2
	;	rcall READ_EEP		;код фазы с инверсией
	;	mov r20,r16
	;	rcall READ_EEP
	;	mov r21,r16
	;	rcall READ_EEP
	;	mov r22,r16
		
	;	rcall READ_EEP		;код фазы с без инверсии
	;	mov r4,r16
	;	rcall READ_EEP
	;	mov r5,r16
	;	rcall READ_EEP
	;	mov r6,r16

		mov r18,r15
		 sbi PORTD,PD6	; поднять РТТ (если еще не поднято было)
		 sbi GPIOR0,0
		pop r16
		ret

LS2:	cpi		r19,'Q'		; QRSS
		brne	LS3
		
		mov r18,r15
		 sbi PORTD,PD6	; поднять РТТ (если еще не поднято было)
		 sbi GPIOR0,0
		pop r16
		ret

LS3:	cpi		r19,'D'		; DFCW
		brne	LS4
		rcall READ_EEP		;load f1 code
		mov r4,r16
		rcall READ_EEP
		mov r5,r16
		rcall READ_EEP
		mov r6,r16
		rcall READ_EEP		;load f2 code
		mov r7,r16
		rcall READ_EEP
		mov r8,r16
		rcall READ_EEP
		mov r9,r16
		rcall READ_EEP		;load f3 code
		mov r10,r16
		rcall READ_EEP
		mov r11,r16
		rcall READ_EEP
		mov r12,r16
		
		mov r18,r15
		 sbi PORTD,PD6	; поднять РТТ (если еще не поднято было)
		 sbi GPIOR0,0
		pop r16
		ret

LS4:	cpi		r19,'W'		; WSPR
		brne	LS5
		rcall READ_EEP		;load f1 code
		mov r4,r16
		rcall READ_EEP
		mov r5,r16
		rcall READ_EEP
		mov r6,r16
		rcall READ_EEP		;load f2 code
		mov r7,r16
		rcall READ_EEP
		mov r8,r16
		rcall READ_EEP
		mov r9,r16
		rcall READ_EEP		;load f3 code
		mov r10,r16
		rcall READ_EEP
		mov r11,r16
		rcall READ_EEP
		mov r12,r16
		
		mov r18,r15
		 sbi PORTD,PD6	; поднять РТТ (если еще не поднято было)
 		 sbi GPIOR0,0
		pop r16
		ret

LS5:
		pop r16
		ret
;******************************************************************************
; data tables
;******************************************************************************

	; force table to begin at 256 byte boundary
	.org 0x300
	
sine:		; 256 step sinewave table
	.DB 	0x80,0x83,0x86,0x89,0x8c,0x8f,0x92,0x95,0x98,0x9c,0x9f,0xa2,0xa5,0xa8,0xab,0xae
	.DB 	0xb0,0xb3,0xb6,0xb9,0xbc,0xbf,0xc1,0xc4,0xc7,0xc9,0xcc,0xce,0xd1,0xd3,0xd5,0xd8
	.DB 	0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xed,0xef,0xf0,0xf2,0xf3,0xf5
	.DB 	0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfc,0xfd,0xfe,0xfe,0xff,0xff,0xff,0xff,0xff
	.DB 	0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,0xfd,0xfc,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7
	.DB 	0xf6,0xf5,0xf3,0xf2,0xf0,0xef,0xed,0xec,0xea,0xe8,0xe6,0xe4,0xe2,0xe0,0xde,0xdc
	.DB 	0xda,0xd8,0xd5,0xd3,0xd1,0xce,0xcc,0xc9,0xc7,0xc4,0xc1,0xbf,0xbc,0xb9,0xb6,0xb3
	.DB 	0xb0,0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9c,0x98,0x95,0x92,0x8f,0x8c,0x89,0x86,0x83
	.DB 	0x80,0x7c,0x79,0x76,0x73,0x70,0x6d,0x6a,0x67,0x63,0x60,0x5d,0x5a,0x57,0x54,0x51
	.DB 	0x4f,0x4c,0x49,0x46,0x43,0x40,0x3e,0x3b,0x38,0x36,0x33,0x31,0x2e,0x2c,0x2a,0x27
	.DB 	0x25,0x23,0x21,0x1f,0x1d,0x1b,0x19,0x17,0x15,0x13,0x12,0x10,0x0f,0x0d,0x0c,0x0a
	.DB 	0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x03,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00
	.DB 	0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x05,0x06,0x07,0x08
	.DB 	0x09,0x0a,0x0c,0x0d,0x0f,0x10,0x12,0x13,0x15,0x17,0x19,0x1b,0x1d,0x1f,0x21,0x23
	.DB 	0x25,0x27,0x2a,0x2c,0x2e,0x31,0x33,0x36,0x38,0x3b,0x3e,0x40,0x43,0x46,0x49,0x4c
	.DB 	0x4f,0x51,0x54,0x57,0x5a,0x5d,0x60,0x63,0x67,0x6a,0x6d,0x70,0x73,0x76,0x79,0x7c

no_sine:
	.DB		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	.DB		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	.DB		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	.DB		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	.DB		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	.DB		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	.DB		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	.DB		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	.DB		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	.DB		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	.DB		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	.DB		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	.DB		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	.DB		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	.DB		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	.DB		0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

.eseg
	.DB		0x51,0x1a,0xaa,0x01,0x09,0x0b,0x1e,0x40,0x00,0x1d,0x75,0x54,0x4e,0xfe,0xff,0x02
	.DB		0x12,0x13,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
	.DB		0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
	.DB		0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
	.DB		0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
	.DB		0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
	.DB		0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
	.DB		0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
