;****************************************************************
;* Автор:				Megavolt								*
;* Дата:				16/11/2009 г.							*
;* Версия:				1.1										*
;* Имя файла:			Dyn_indic_key							*
;* Для AVR:				ATtiny2313								*
;* Тактовая частота:	6 МГц									*
;****************************************************************

; Выполняемые функции: Динамическая индикация + управление кнопками
;__________________________________________________________________________

.device	ATtiny2313
.nolist
.include "d:\avr\def\tn2313def.inc"
.list

;=====================================================================
; Объявления:


.def 	key_mem_reg=r1
.def	temp1=r2
.def	n_digit=r3
.def	counter=r4
.def	digit_out=r5
.def 	n_point=r6
.def	temp=r16
.def	temp2=r17



.equ	crystal=6000000					;частота кварца
.equ	Sciler=1024						;предделитель таймера
.equ	N_TC0_2500uc=255-crystal/(Sciler*400);число тиков таймера ТС0 для организации
										;задержи динамической индикации
.equ    amount_digit=4					;маска, нужно ввести количество разрядов индикатора
										;в данном случае 4-х разрядный индикатор




;======================================================================
; Начало программы:

.dseg

Digit:		.byte 4
Point:		.byte 1
Key:		.byte 8

.cseg
.org 0
		rjmp RESET						;Reset Handler
		nop ;rjmp INT0						;External Interrupt0
		nop ;rjmp INT1					;External Interrupt1
		nop ;rjmp ICP1     				;Input capture interrupt 1
		nop ;rjmp OC1A   				;Timer/Counter1 Compare Match A     
		nop ;rjmp OVF1  				;Overflow1 Interrupt 
		rjmp OVF0     					;Overflow0 Interrupt
		nop ;rjmp URXC0     			;USART0 RX Complete Interrupt
		nop ;rjmp UDRE0     			;USART0 Data Register Empty Interrupt
		nop ;rjmp UTXC0     			;USART0 TX Complete Interrupt 
		nop ;rjmp ACI     				;Analog Comparator Interrupt 
		nop ;rjmp PCINT     			;Pin Change Interrupt
		nop ;rjmp OC1B     				;Timer/Counter1 Compare Match B
		nop ;rjmp OC0A     				;Timer/Counter0 Compare Match A     
		nop ;rjmp OC0B     				;Timer/Counter0 Compare Match B     
		nop ;rjmp USI_START     		;USI start interrupt
		nop ;rjmp USI_OVF     			;USI overflow interrupt
		nop ;rjmp ERDY     				;EEPROM write complete
		nop ;rjmp WDT     				;Watchdog Timer Interrupt
										; for compatibility purpose




;======================================================================
; Инициализация

	RESET:
		ldi temp,low (RAMEND)			;Определение начала стека
		out SPL,temp

		ldi temp,0b0001111				;Конфигурирование портов
		out DDRD,temp					;Порт D вход\выход
		ser temp
		out DDRB,temp					;Порт B выход	
		out PIND,temp					;Команда для отладчика
		out PORTD,temp					;Включаем подтягивающие резисторы
		out PORTB,temp					;Выключаем матрицу

		ldi temp,15						;Инициализация сторожевого таймера
		out WDTCR,temp
		rcall TNCT_0					;Инициализация таймера ТС0


;======================================================================
; для проверки работы индикатора выводит на индикатор число 1234
; запятая во втором знакоместе
		ldi Temp,4
		sts Digit  ,Temp      			;загрузка начальных значений число 4321
		ldi Temp,3
		sts Digit+1,Temp
		ldi Temp,2
		sts Digit+2,Temp
		ldi Temp,1
		sts Digit+3,Temp
	
		ldi Temp,1
		sts Point,Temp      			;загрузка номера разряда запятой 2-й разряд
		clr counter
;======================================================================
; кнопки ещё ни разу не нажимались
; 
		ldi Temp,0
		sts Key,Temp      			;загрузка начальных значений для борьбы с дребезгом
		ldi Temp,0
		sts Key+1,Temp
		ldi Temp,0
		sts Key+2,Temp
		ldi Temp,0
		sts Key+3,Temp
		ldi Temp,0
		sts Key+4,Temp      			;загрузка начальных значений для борьбы с дребезгом
		ldi Temp,0
		sts Key+5,Temp
		ldi Temp,0
		sts Key+6,Temp
		ldi Temp,0
		sts Key+7,Temp




;======================================================================
; Основной блок программы

	main:

		wdr								;"Бросим кость собаке"
	


		rjmp main						;Начинаем всё сначала
		 

;=======================================================================
; Инициализация таймеров		
	
	TNCT_0:
		cli								;запрещаем прерывания
		ldi temp,N_TC0_2500uc			; инициализируем таймер Т\С0 на Т=0,0025 с
		out TCNT0,temp
		ldi temp,0b00000000
		out TCCR0A,temp
		ldi temp,(1<<CS02)+(1<<CS00)	;прескайлер таймера 1024
		;ldi temp,(1<<CS00)				;прескайлер таймера 1 для отладки
		out TCCR0B,temp
		ldi temp,(1<<TOIE0)			 	;прерывания Т\С0 по переполнению
		out TIMSK,temp
		sei
		reti



;========================================================================
; Обработчик прерываний
	
	OVF0:
		rcall TNCT_0					;Инициализация таймера ТС0
		ldi ZL,Low(Digit)   			;инициализация массива
        ldi ZH,High(Digit)
		clr temp1
		add ZL,counter					;выбираем нужный номер ячейки
		adc ZH,temp1
		ld digit_out,Z      			;загружаем ячейку
		lds	n_point,Point
		rcall Decoder_n_digit
		rcall Decoder
		out PORTD,n_digit
		out PORTB,digit_out
		rcall Check_key
		inc counter						;увеличиваем номер разряда
		mov temp,counter
		andi temp,(amount_digit-1)	;отсекаем количество разрядов по маске
		mov counter,temp
		reti 
	
	
;=========================================================================
; Подпрограммы	
	Decoder:
	;преобразует десятичную цифру разряда в 7-ми сегментный код индикатора		
			
           	clr temp		
			ldi ZL,Low(DcMatrix*2)   	;инициализация массива перекодировки
            ldi ZH,High(DcMatrix*2)
			clr temp1	             	;прибавление переменной
            add ZL,digit_out        	;к 0-му адресу массива
            adc ZH,temp1
            lpm                     	;загрузка значения 7-ми сегментного кода индикатора
            mov digit_out,r0
			clr temp
			cp n_point,temp				;проверяем номер разряда зяпятой если 
			breq PC+6					;если он равен 0 то выходим из подрограммы
			cp counter,n_point			;если он не равен нулю сравниваем с 
			brne PC+4					;номером разряда вкл в данный момент
			mov temp,digit_out
			andi temp,0b01111111		;если равен зажигаем зяпятую иначе
          	mov digit_out,temp  
			ret							;выходим из подпрограммы




	DcMatrix:
	;массив - таблица истинности декодера
		;     hgfedcba   hgfedcba
		.db 0b11000000,0b11111001		;0;1
		.db 0b10100100,0b10110000		;2;3
		.db 0b10011001,0b10010010		;4;5
		.db 0b10000010,0b11111000		;6;7
		.db 0b10000000,0b10010000		;8;9
	

	
	Decoder_n_digit:
			ldi ZL,Low(DnMatrix*2)   	;инициализация массива
            ldi ZH,High(DnMatrix*2)
            clr temp1	             	;прибавление переменной
            add ZL,counter            	;к 0-му адресу массива
            adc ZH,temp1
            lpm                     	;загрузка значения
            mov n_digit,r0
            ret


	DnMatrix:
	;массив - таблица истинности декодера разряда
		
		.db 0b11111110,0b11111101	;0;1
		.db 0b11111011,0b11110111	;2;3

		



	Check_key:

			ldi XL,Low(Key)   				;борьба с дребезгом
        	ldi XH,High(Key)
			inc temp2
			andi temp2,0b00000111			;будем блокировать для борьбы 
			add XL,temp2					;с дребезгом 8 кнопок
			ld temp2,X
			cpi temp2,0
			breq PC+3
			dec temp2
			st X,temp2
					
			in temp,PIND
			andi temp,0b00110000
			cpi	temp,0b00110000
			breq End_Decoder_key
			add temp,counter
			
			cpi temp,0b00010000
			breq	Set_key1
			

			cpi temp,0b00010001
			breq	Set_key2
			

			cpi temp,0b00010010
			breq	Set_key3
			

			cpi temp,0b00010011
			breq	Set_key4
			

			cpi temp,0b00100000
			breq	Set_key5
			

			cpi temp,0b00100001
			breq	Set_key6
			

			cpi temp,0b00100010
			breq	Set_key7
			

			cpi temp,0b00100011
			breq	Set_key8
			

			
	End_Decoder_key:

			ret



;обработчик действия кнопок


		Set_key1:
			
			lds temp,Key
			cpi temp,0
			breq PC+2
			ret
			ldi temp,64
			sts Key,temp
			lds temp,Digit
			inc temp
			cpi temp,10
			brne PC+2
			ldi temp,0
			sts Digit,temp		
			ret


		Set_key2:

			lds temp,Key+1
			cpi temp,0
			breq PC+2
			ret
			ldi temp,64
			sts Key+1,temp
			lds temp,Digit+1
			inc temp
			cpi temp,10
			brne PC+2
			ldi temp,0
			sts Digit+1,temp	
			ret



		Set_key3:
			lds temp,Key+2
			cpi temp,0
			breq PC+2
			ret
			ldi temp,64
			sts Key+2,temp
			lds temp,Digit+2
			inc temp
			cpi temp,10
			brne PC+2
			ldi temp,0
			sts Digit+2,temp		
			ret

	Set_key4:
			lds temp,Key+3
			cpi temp,0
			breq PC+2
			ret
			ldi temp,64
			sts Key+3,temp
			lds temp,Digit+3
			inc temp
			cpi temp,10
			brne PC+2
			ldi temp,0
			sts Digit+3,temp
			ret



	Set_key5:
			lds temp,Key
			cpi temp,0
			breq PC+2
			ret
			ldi temp,64
			sts Key,temp
			lds temp,Digit
			dec temp
			cpi temp,255
			brne PC+2
			ldi temp,9
			sts Digit,temp	
			ret



	Set_key6:
			lds temp,Key+1
			cpi temp,0
			breq PC+2
			ret
			ldi temp,64
			sts Key+1,temp
			lds temp,Digit+1
			dec temp
			cpi temp,255
			brne PC+2
			ldi temp,9
			sts Digit+1,temp	
			ret


	Set_key7:
			lds temp,Key+2
			cpi temp,0
			breq PC+2
			ret
			ldi temp,64
			sts Key+2,temp
			lds temp,Digit+2
			dec temp
			cpi temp,255
			brne PC+2
			ldi temp,9
			sts Digit+2,temp	
			ret


	Set_key8:
			lds temp,Key+3
			cpi temp,0
			breq PC+2
			ret
			ldi temp,64
			sts Key+3,temp
			lds temp,Digit+3
			dec temp
			cpi temp,255
			brne PC+2
			ldi temp,9
			sts Digit+3,temp	
			ret









