;*****************************************************************************
;передатчик
;*****************************************************************************

 	.def	Temp=R16
	.def	Temp1=R17
	.def	Temp2=R18
	.def	Temp3=R19
	.def	Temp4=R20
	.def	Temp5=R21
	.def	Temp6=R22
	.def	Temp7=R23
	.def	Temp8=R24
	.def	Temp9=R25


.dseg			;оперативка

key_buff: .byte 5	; зарезервируем 5 байт в ОЗУ


;******************************************************************************
;
;******************************************************************************

.EQU ImpLen=0xCE4 			; длина импульса
.EQU OneLen=0xCE4 			; длина паузы для единицы
.EQU NulLen=0x19C8			; длина паузы для нуля

;******************************************************************************
;
;******************************************************************************

.cseg
.org 0


					; СТАРТ
rjmp RESET				; External Pin, Power-on Reset, Brown-out Reset, and Watchdog Reset

.org	INT0addr;	= 0x0001	; External Interrupt Request 0
reti
.org	INT1addr;	= 0x0002	; External Interrupt Request 1
reti
.org	ICP1addr;	= 0x0003	; Timer/Counter1 Capture Event
reti
.org	OC1Aaddr;	= 0x0004	; Timer/Counter1 Compare Match A/////////////////////////
rjmp TIM1_COMPA
.org	OVF1addr;	= 0x0005	; Timer/Counter1 Overflow
reti
.org	OVF0addr;	= 0x0006	; Timer/Counter0 Overflow
reti
.org	URXCaddr;	= 0x0007	; USART, Rx Complete
reti
.org	UDREaddr;	= 0x0008	; USART Data Register Empty
reti
.org	UTXCaddr;	= 0x0009	; USART, Tx Complete
reti
.org	ACIaddr;	= 0x000a	; Analog Comparator
reti
.org	PCIBaddr;	= 0x000b	; Pin Change Interrupt Request B
reti
.org	OC1Baddr;	= 0x000c	;
reti
.org	OC0Aaddr;	= 0x000d	;
reti
.org	OC0Baddr;	= 0x000e	; 
reti
.org	USI_STARTaddr;	= 0x000f	; USI Start Condition
reti
.org	USI_OVFaddr;	= 0x0010	; USI Overflow
reti
.org	ERDYaddr;	= 0x0011	; 
reti
.org	WDTaddr;	= 0x0012	; Watchdog Timer Overflow
reti
.org	PCIAaddr;	= 0x0013	; Pin Change Interrupt Request A
reti
.org	PCIDaddr;	= 0x0014	; Pin Change Interrupt Request D
reti


;******************************************************************************
;старт
;******************************************************************************

reset:					; включение микроконтроллера

cli					; глобальный запрет на прерывания


ldi Temp,low(RamEnd)			; инициализации стека	
out SPL,Temp				;



ldi Temp,0b00001000			; настроили порт "В" (0-ввод, 1-вывод)
out DDRB,Temp				; 0000х000 - "вывод" на передатчик (PB3- 15 ножка)
					; хххх0000 - "ввод" для чтения строк клавиатуры
					; 
					 



ldi Temp,0b00001111			; настраиваем порт "D" (0-ввод, 1-вывод)
out DDRD,Temp 				; 0000хххх - на вывод столбцов клавы
					; 



ldi Temp,0b00000000			; выключено
out TCCR1A,Temp				;



ldi Temp,0b00000000			; установили тактовый сигнал = CK 0
out TCCR1B,Temp				; таймер выключен!!!
					; 


					; инициализация компаратора +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ldi Temp,0xFF				; наверно "0xFFFF"
out OCR1AH,Temp				; 
ldi Temp,0xFF				; 
out OCR1AL,Temp				; 


ldi Temp,(1<<OCIE1A)			; разрешить прерывание компаратора 
out TIMSK,Temp


;ldi Temp,0				; обнуление таймера при включении (здеь закоментировал т.к. перенес дальше по коду)
;out TCNT1H,Temp
;out TCNT1L,Temp


sei					; глобальное разрешение прерываний
        


ldi Temp,0b00000000			; выводим "0" в порт "Б" на "OC1A" +++++++++++++++++++++++++++++++++++++++++++++++++++++++
out PortB,Temp






;*******************************************************************************
; главный цикл
;*******************************************************************************


Main_cicle:



	rcall keyboardread		; вызов подпрограммы чтения клавиатуры

	rcall certain_buttons_keyboard	; вызов подпрограммы проверки нажатия

	
rjmp Main_cicle				; циклимся




;*******************************************************************************
;обработка прерывания
;*******************************************************************************

TIM1_COMPA:
					; включен режим CTC 
					; обнуление таймера  происходит автоматически
					; "OC1A" меняет свое логическое состояние автоматически


reti

;*******************************************************************************
; Чтение клавы и запись данных в ОЗУ
;*******************************************************************************

keyboardread:				; метка - опрос клавиатуры

          
	ldi Temp,5			; количество столбцов клавы = пять
         
	ldi Temp1,0b00000001		; первый столбец

          				; загружаем адрес метки (key_buff) находящейся в ОЗУ в регистровую пару X
	ldi XL,low(key_buff)		; младший байт адреса
	ldi XH,high(key_buff)		; старший байт адреса

keyboardread_loop:			; цикл опроса

	out PortD,Temp1			; выводим в порт "Д" значение "Temp1" для выбора столбца клавиатуры
	in Temp2,PinB			; прочитали состояние столбца
         
	st X+,Temp2			; сохраним в ОЗУ состояние столбца клавы, 
 					; адрес в регстровой паре "X" автоматом увеличится на 1

	lsl Temp1			; сдвинули единичку выбора столбца клавиатуры на 1
 					; позицию влево

	dec temp			; уменьшим счетчик
	brne keyboardread_loop		; если не все просканировали, то циклимся

ret




       
;******************************************************************************************
;проверка нажатия клавиатуры
;******************************************************************************************



certain_buttons_keyboard:
		

	ldi temp1,5			; УСТАНОВИМ СЧЕТЧИК столбцов клавы	

	
                  			; загружаем адрес метки (key_buff) находящейся в ОЗУ в регистровую пару "Z"
	ldi ZL,low (key_buff)		; младший байт адреса
	ldi ZH,high(key_buff)		; старший байт адреса 


Certain_button:


	ld Temp,Z+			; загрузим данные в регистр из ОЗУ по адресу из регистровой пары "Z", 
					; и после этого адресс в регистровой паре автоматически увеличится на еденицу


	cpi Temp,0b00000000		; проверяем, нажата ли какая ни будь кнопка?
	brne inform			; если нажата то переходим на метку "inform"


	dec temp1			; уменьшим счетчик
	brne Certain_button		; если не все столбцы, то циклимся

metka:


ret

;***********************************************************************************************
;вывод информации о состоянии клавиатуры в порт "Б" 
;***********************************************************************************************

inform:


							; включаем таймер
	ldi Temp,(1<<COM1A0)				; переключать ножку "OC1A" по совпадению (PB3- 15 ножка)
	out TCCR1A,Temp					; *1


	ldi Temp,(1<<wgm12)|(1<<cs10)			; подключили режим "CTC" (вместе с *1) 
	out TCCR1B,Temp					; и установили тактовый сигнал = CK 1:1  ++++++++++++++++++++++++++++++++++++++
							; таймер начал считать!!!

	
	ldi Temp,0					; обнуление таймера 
	out TCNT1H,Temp
	out TCNT1L,Temp
						

;======================================================================================================================================
;начало передачи
;--------------------------------------------------------------------------------------------------------------------------------------

OCR1A_COMP:

					; первоначальное значение R22 - 0
					; таким образом сначала будет выполнена инициализации передачи



					; проверяем фазу работы прерывания



	CPI R22, 1
	BREQ transmitt_byte		; фаза передачи байта

	CPI R22, 2
	BREQ transmitt_bite_imp		; фаза передачи импульса бита в байте

	CPI R22, 3
	BREQ transmitt_bite_pause	; фаза передачи паузы бита в байте

	CPI R22, 4
	BREQ transmitt_imp_chetn	; фаза передачи импульса бита четности

	CPI R22, 5
	BREQ transmitt_pausa_chetn	; фаза передачи паузы бита четности

	CPI R22, 6
	BREQ transmitt_complete		; передача завершена, выключение прерываний


;****************************************************************************************************************

					; инициализация передачи, (при R22=0)



	ldi R21,0			; это будет счетчик единичек в передаче (четность)

	ldi yl,low(key_buff)		; зададим адрес начала массива прочитанных кнопок
	ldi yh,high(key_buff)

	ldi R17,5			; количество байт для передачи




transmitt_byte:				; фаза начала передачи - передача байта

 
	ld temp,y+			; прочитаем байт для передачи, увеличим на единицу адрес в "Y" 

	ldi r18,8			; количество бит в байте для передачи





transmitt_bite_imp:			; фаза передачи импульса в передаваемом бите


	LDI R19 ,high(ImpLen)		; зададим фиксированную длительность импульса
	OUT OCR1AH, R19			; и выведем ее в порт сравнения
	LDI R19,low(ImpLen)   
	OUT OCR1AL ,R19       

	LDI  R22, 3			; в следующий раз передаем паузу

;*********************************************************************************************************************\/*\/*\/

int_reti:

	RETI				; точка выхода из прерывания


;**********************************************************************************************************************

transmitt_bite_pause:			; фаза передачи паузы в передаваемом бите


					; здесь кодируем импульс для бита


	LDI XL,low(Nullen)		; длительность для передачи нуля
	LDI XH,high(Nullen)

	ROL temp			; двигаем байт влево (циклический сдвиг влево)
	BRCC send_nullen		; если "С"=0 то записываем нулевую длительность

	
	LDI XL,low(onelen)		; длительность для передачи единицы
	LDI XH,high(onelen)

	INC R21				; передаем единицу - увеличим счетчик единичек (четность) 



send_nullen:

	OUT OCR1AH,XH			; установим длительность
	OUT OCR1AH,XL         
               
	LDI R22,2			; в следующий раз передадим импульс бита

	dec R18				; уменьшим счетчик бит на передачу
	brne int_reti			; если это непоследний бит в байте - то выход из прерывания

	LDI R22,1			; в следующий раз передадим новый байт

	dec R17				; уменьшим счетчик Байт для передачи
	brne int_reti			; если это не последний байт в массиве - то выход из прерывания
                   
	LDI R22,4			; в следующий раз передадим импульс бита четности

	RJMP int_reti			; выход из прерывания

;*********************************************************************************************************************                   


transmitt_imp_chetn:			; передача импульса бита четности


	
	LDI R19 ,high(ImpLen)		; зададим фиксированную длительность импульса
	OUT OCR1AH, R19			; и выведем ее в порт сравнения
	LDI R19,low(ImpLen)   
	OUT OCR1AL,R19       


	LDI R22,5			; в следующий раз передаем паузу бита четности

	rjmp int_reti			; выход из прерывания

;**********************************************************************************************************************


transmitt_pausa_chetn:			; передача паузы импульса четности

					; здесь кодируем длительность паузы для бита четности


	LDI XL,low(Nullen)		; длительность для передачи нуля
	LDI XH,high(Nullen)

	COM R21				; Побитная инверсия

	ROR R21				; Циклический сдвиг вправо

	BRCC send_chetn 		; если "С"=0 то записываем нулевую длительность

	LDI XL,low(onelen)		; длительность для передачи единицы
	LDI XH,high(onelen)

	INC R21				; если передаем единицу - увеличим счетчик//////////////////это тут не нужно скорее всего!!!!!!!!!



send_chetn:

	OUT OCR1AH,XH			; установим длительность
	OUT OCR1AH,XL         

	LDI R22,6			; ОТКЛЮЧЕНИЕ ПРЕРЫВАНИЯ
	rjmp int_reti

;*************************************************************************************************************************

transmitt_complete:				; ЗДЕСЬ ДОЛЖЕН БЫТЬ КОД ДЛЯ ОТКЛЮЧЕНИЯ ПРЕРЫВАНИЙ 


	ldi Temp,0b00000000			; выключено
	out TCCR1A,Temp				;



	ldi Temp,0b00000000			; установили тактовый сигнал = CK 0  ++++++++++++++++++++++++++++++++++++++++++++++++++++
	out TCCR1B,Temp				; таймер выключен!!!
	


						; инициализация компаратора +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
	ldi Temp,0xFF				; наверно "0xFFFF"
	out OCR1AH,Temp				; 
	ldi Temp,0xFF				; 
	out OCR1AL,Temp				; 
				

;*************************************************************************************************************************
;конец передачи
;=========================================================================================================================


	ldi Temp,0b00000000			; выводим "0" в порт "Б" на "OC1A" +++++++++++++++++++++++++++++++++++++++++++++++++++++++
	out PortB,Temp


	rjmp metka

;***********************************************************************************************
