.include "m16Adef.inc"
.def TEMP=R16							
.def TimeIsOver=R17
.def Counter=R18
.def Base=R19
.def Shift=R20

;в переменной Counter хранится счетчик нажатий на кнопку. При каждом нажатии на кнопку счетчик увеличивается на
;единицу. Стартовое значение при инициализации процессора 0. Благодаря использованию маски значение счетчика
;никогда не бывает больше 3, т.е. диапазон счетчика 0-3, что соответствует 4 режимам индикации светодиодов


;Переменные Base и Shift предназначены для адресации памяти. В переменной Base хранится адрес первого элемента 
;выбранного массива


;индикация каждого режима осуществляется через прерывания таймера 1 каждые 200мс, таймер 0 осуществляет программный антидребезг после нажатия кнопки смены режима - 250мс


.cseg
.org 	 $000
 		 RJMP Reset				;  прерывание по резету
         .ORG $002
         RJMP Choose			; (INT0) External Interrupt Request 0
         .ORG $004
         RETI					; (INT1) External Interrupt Request 1
         .ORG $006
         RETI					; (TIMER2 COMP) Timer/Counter2 Compare Match
         .ORG $008
         RETI					; (TIMER2 OVF) Timer/Counter2 Overflow
         .ORG $00A
         RETI					; (TIMER1 CAPT) Timer/Counter1 Capture Event
         .ORG $00C
         RJMP LED				; (TIMER1 COMPA) Timer/Counter1 Compare Match A
         .ORG $00E
         RETI					; (TIMER1 COMPB) Timer/Counter1 Compare Match B
         .ORG $010
         RETI					; (TIMER1 OVF) Timer/Counter1 Overflow
         .ORG $012
         RETI					; (TIMER0 OVF) Timer/Counter0 Overflow
         .ORG $014
         RETI					; (SPI,STC) Serial Transfer Complete
         .ORG $016
         RETI					; (USART,RXC) USART, Rx Complete
         .ORG $018
         RETI					; (USART,UDRE) USART Data Register Empty
         .ORG $01A
         RETI					; (USART,TXC) USART, Tx Complete
         .ORG $01C
         RETI					; (ADC) ADC Conversion Complete
         .ORG $01E
         RETI            		; (EE_RDY) EEPROM Ready
         .ORG $020
         RETI          			; (ANA_COMP) Analog Comparator
         .ORG $022
         RETI           		; (TWI) 2-wire Serial Interface
         .ORG $024
         RETI             		; (INT2) External Interrupt Request 2
         .ORG $026
         RJMP Delay		  		; (TIMER0 COMP) Timer/Counter0 Compare Match
         .ORG $028
         RETI             		; (SPM_RDY) Store Program Memory Ready
 
	 .ORG   INT_VECTORS_SIZE    ; конец таблицы векторов


Delay:			ldi TimeIsOver,1			;выждали время и выставили флаг того, что время вышло
				reti					

Reset:			cli							;нахуй прерывания пока что

				ldi Temp,Low(Ramend)		;инициализация стека
				out SPL,Temp
				ldi Temp,High(Ramend)
				out SPH,Temp



				ldi Temp,0b00000010			;срабатывание по отрицательному фронту
				out MCUCR,Temp
				ldi Temp,0b01000000			;разрешить прерывание INT0
				Out GICR,Temp



				ldi TEMP,0b11111111   		;направление ввода-вывода
        		out DDRA,TEMP


				ldi TEMP,0b00010010			;разрешить прерывания по компаратору для таймеров Timer0 и Timer1A
				out TIMSK,TEMP

				
				ldi TEMP,0b00000000
				out TCCR1A,TEMP
  	        	ldi TEMP,0b00001101   		;прескалер = CK/1024. очищать таймер при совпадении с компаратором. одинаково для двух таймеров
				out TCCR1B,TEMP
				
				
				
				ldi TEMP,0x00				;компаратор таймера 1 соответствует при таком прескалере 200мс
				out OCR1AH,TEMP
 				ldi TEMP,0xC3
				out OCR1AL,TEMP
				ldi TEMP,0b11110100         ;компаратор таймера 0 соответствует при таком прескалере 250мс
         		out OCR0,TEMP



       		   	ldi TEMP,0            		;обнуление таймеров
   		       	out TCNT0,TEMP
				out TCNT1H,TEMP
				out TCNT1L,TEMP



				ldi TimeIsOver,0			;загрузка начальных значений в регистры
				ldi Counter,0
				ldi Base,0
				ldi Shift,0

				sei
				


;*****************************************************основной цикл******************************************
Inf:			rjmp Inf
;************************************************************************************************************



				
Choose:			ldi Shift,0
				ldi Temp,0b00000000			;запретить прерывание INT0
				Out GICR,Temp
				sei
				ldi TimeIsOver,0
				ldi TEMP,0b00001101			;Запуск таймера на антидребезг
				out TCCR0,TEMP

Loop:			cpi TimeIsOver,1			;ждем срабатывания таймера
				brne Loop
				
				inc Counter

				ldi TEMP,0					;остановка таймера антидребезга
				out TCCR0,TEMP				

				ldi TEMP,0b01000000			;теперь можно INT0 разрешить. вроде как:-D
				out GICR,TEMP
				reti
			
			
LED:				
SelectArray:	
				andi Counter,0b00000011		;убиваем все разряды кроме первых двух, чтобы при непрерывном росте Counter цифры циклично менялись лишь от 0 до 3	
				cpi Counter,0
				brne Cnt1
				ldi ZL,Low(First*2)			;загрузили адрес первого элемента массива First
				ldi ZH,High(First*2)
				rjmp Read					;выводим на индикацию		


Cnt1:			cpi Counter,1
				brne Cnt2
				ldi ZL,Low(Second*2)		;загрузили адрес второго массива
				ldi ZH,High(Second*2)
				rjmp Read

Cnt2:			cpi Counter,2
				brne Cnt3
				ldi ZL,Low(Third*2)			;загрузили адрес третьего массива
				ldi ZH,High(Third*2)
				rjmp Read

Cnt3:			ldi ZL,Low(Forth*2)			;загрузили адрес четвертого массива
				ldi ZH,High(Forth*2)
				rjmp Read



Read:			ldi Base,0					;увеличиваем адрес элемента массива. база благодаря первой строке не меняется в текущей программе
				add ZL,Shift
         		adc ZH,Base

				lpm							;загрузили значение по адресу Z в регистр R0

         		mov TEMP,R0           		;копирование элемента для индикации в рабочий регистр-мусорку
         		cpi TEMP,0            		;проверка на нулевой элемент, показывающий конец текущего прохода индикации
				breq Init
         		inc Shift             		;увеличение смешения адреса элемента массива на 1

         		rjmp Output           		;перейти на вывод в порт


Output:			out PortA,TEMP				;вывод на индикацию. TEMP содержит в себе конкретный элемент массива	
				reti


Init:			ldi Shift,0
				rjmp SelectArray



First:
.db				0b00000001,0b00000010
.db				0b00000100,0b00001000
.db				0b00010000,0b00100000
.db				0b01000000,0b10000000
.db				0,0

Second:			
.db				0b10000000,0b01000000
.db				0b00100000,0b00010000
.db				0b00001000,0b00000100
.db				0b00000010,0b00000001
.db				0,0

Third:			
.db				0b10000000,0b11000000
.db				0b11100000,0b11110000
.db				0b11111000,0b11111100
.db				0b11111110,0b11111111
.db				0,0

Forth:
.db				0b10000001,0b11000011
.db				0b11100111,0b11111111
.db				0b11111111,0b11100111
.db				0b11000011,0b10000001
.db				0,0
