;AT90S2313  @  External 4Mhz
.nolist
.include "2313def.inc"
.list
;***************Объявления*****************
.def temp=R16
.def temp1=r17
.def temp2=r18
.def temp3=r19
.def count=r20
.def temp5=r21
.def temp4=r22
.def inmask=r23
.def scancode=r24; код нажатой клавишы
.def flag1=r25;флаг равенства
.def flag2=r26;флаг смены пароля
.dseg
.org 0x60
Line:	.byte 4
.eseg
.org 0x08
Bufer: .byte 4
;***********************************************
.cseg 
.org 0 
    rjmp RESET    ; Reset Handler 
.org INT1addr 
    rjmp EXT_INT1 ; IRQ1 Handler 
.org INT0addr
    rjmp EXT_INT0 ; IRQ0 Handler
.org  OVF1addr
    rjmp TIM_OVF1 ; Timer1 Overflow Handler
;***************Инициализация*****************
RESET:   ldi temp,RamEnd	;инициализация стека
              out SPL,temp
              ldi temp,0b11111111;входы и выходы порта B
              out DDRB,temp
              ldi temp,0b10000011;входы и выходы порта D
              out DDRD,temp
              ldi temp,0b00000000;начальное состояние порта B и подтяжка
              out PortB,temp
              ldi temp,0b11110000;начальное состояние порта D и подтяжка
              out PortD,temp
			  ldi temp,0x80; Выкл компаратор нахуй, ибо тогда pb0 будет занята хуйней всякой
			  out ACSR,temp 
              ldi	Temp,0b11000000;разрешаем прерывание INT0 и INT1
              out	GIMSK,Temp
              ldi Temp,0b00001110; INT1 по возрастающему, INT0 по убывающему фронту
              out MCUCR,Temp
              ldi Temp,0b10000000; выбираем прерывание по переполнению 1 таймера 
              out TIMSK, Temp     
              ldi Temp,0            ;обнуление таймера
              out TCNT1H,Temp
              out TCNT1L,Temp
              sei 
;***************Основная программа*****************
Start:      
             rjmp Start; бесконечный цикл
;********Обработка прерываний от таймера********
TIM_OVF1:
              push temp3
              in temp3, SREG
              push temp3
              sbi PortD,0;зажег зеленый светодиод и он светиться пока устанавливаем новый пароль
              ldi flag2,1; установили флаг режима ввода пароля
			  pop temp3 
              out SREG,temp3
              pop temp3
              reti
;********Обработка прерываний от INT0 - клавиатура********
EXT_INT0:
              ldi Temp1,0;   -
              ldi Temp2,0;   -
l_res:;                          -
              dec Temp1;    -    антидребезг
              brne l_res;      -  
              dec Temp2;    -
              brne l_res;      - 
              push temp3
              in temp3, SREG
              push temp3
              in temp,MCUCR; проферяем фронт
              sbrc temp,0; если нарастающий то прыгаем по m3 
              rjmp m3
			  rcall beep
              rcall skan
              mov temp1,scancode;
              cpi temp1,10; 0 или не 0 нажат
              brne m4
              cli; если нажат 0 проверяем как долго нажат:
              ldi Temp,0b00001011; INT0 по нарастающему фронту
              out MCUCR,Temp
              ldi Temp,0b00000100;предделитель на 256 при частоте кварца 4 МГц он переполнится через 4,2 сек, пойдет ^_^
              out TCCR1B,Temp;запускаем таймер по переполнению
              rjmp konec1
m4:         cpi temp1,9; звонок нажат или нет?
              brne m5
              rcall zvonok;если нажат звонок - звоним в дверь
              rjmp m7;вызываем подпрограмму очистки ОЗУ
m5:        cpi temp1,11;сброс нажат?
              brne m2
m7:         rcall clear;если нажат сброс очищаем ОЗУ
              rjmp konec1
m3:;кнопка отжалась, проверяем таймер
              ldi Temp,0b00001010; INT0, INT1 по убывающему фронту
              out MCUCR,Temp
              in Temp,TCNT1H; проверяем остановился таймер или нет
              cpi Temp,0; если не остановился то прыгаем на метку ostanov, иначе выходим из подпрограммы
              brne ostanov;
              in Temp,TCNT1L
              brne ostanov
              rjmp konec1
ostanov:  clr temp
              out TCCR1B,temp ;остановили таймер чтобы не произошло прерывание по переполнению
              
 m2:          rcall zagrOZY;загружаем в ОЗУ код нажатой кнопки
              cpi count,4; проверяем не конец ли памяти озу
              brsh m8;если конец переходим к процедуре проверки кода 
              rjmp konec1
m8:         cpi temp5,1; проверка нужна или сразу ввод в епром?
              breq m14; нет, пишем в епром  
              rcall proverka
              cpi flag1,1; правильно введен пароль или нет?
              brne m12 ;нет 
              cpi flag2,1 ; мы в режиме ввода нового пароля?
              breq m13;да
              push temp3
              push r23
              push r24
              push r25
              ldi temp3,6 ; 6 раз по 0,5 = 3 секунды открыта дверь
              sbi PortB,4;открыть дверь
while1: 
              rcall Svitim 
              rcall Zadergka 
              rcall Gasim 
              rcall Zadergka 
              dec temp3 
              brne while1
		      cbi PortB,4 ; закрыли дверь 
		      pop r25
		      pop r24
		      pop r23
		      pop temp3
		      rjmp konec1          
m12:       sbi PortD,1 ;зажгли красный светодиод
              rcall Zadergka
              cbi PortD,1
              rjmp konec1
 m13:       ;значит мы в режиме ввода пароля, старый пароль верен, надо вводить новый пароль в озу, потом
               ;в епром потом погасить зеленый диод, и сбросить флаг.
               ldi temp5,1; устанавливаем флаг того, что при следующем вводе с клавы проверка не нужна, 
                               ; а сразу после записи в ОЗУ, сохраняем в епром
               rjmp konec1
 m14:      ldi temp,bufer;  в temp начало адрес начала буфера епром
              ldi ZL,low(Line); адрес начала буфера в ОЗУ
              ldi ZH,high(Line)     
m15:       ld temp1,z+; читаем очередной байт из ОЗУ
              rcall eewr
              dec count
              brne m15
              clr temp5
              clr flag1
              clr flag2
              cbi PortD,0
              pop temp3 
              out SREG,temp3
              pop temp3
konec1:  reti; выход из обработчика INT0

;********Подпрограмма опроса строк********       
skan:      clr scancode; в ней будет код нажатой кнопки
             ldi inmask,0b00001110;первая строка выбрана
              rcall Keyskan
              brcc konec3
              ldi inmask,0b00001101; вторая строка выбрана
              rcall Keyskan
              brcc konec3
              ldi inmask,0b00001011;третья строка выбрана
              rcall Keyskan
              brcc konec3
              ldi inmask,0b00000111;четвертая строка выбрана строка 
              rcall Keyskan
konec3:       ret
;********Подпрограмма опроса столбцов********       
Keyskan:
              out PortB,inmask
              in temp2,PinD;читаем состояние клавиш
              swap temp2
              ldi temp1,3; загрузили счетчик опросов столбцов
m1:        ror temp2; сдвиг байта возврата
              brcc konec;выходим если нет переноса - кнопка нажалась
              inc scancode
              dec temp1
              brne m1
konec:    ret
;********Подпрограмма очистки ОЗУ******** 
clear:      clr temp
              sts line ,Temp   
              sts line+1,Temp
              sts line+2,Temp
              sts line+3,Temp    
              ret
     
;********Обработка прерываний от INT1 - это наш Грибок********
EXT_INT1:
              ldi Temp1,0;   -
              ldi Temp2,0;   -
l_res1:;                          -
              dec Temp1;    -    антидребезг
              brne l_res1;      -  
              dec Temp2;    -
              brne l_res1;      - 
              in temp3, SREG
              push temp3
              push r23
              push r24
              push r25
              ldi temp3,6 ; 6 раз по 0,5 = 3 секунды открыта дверь
              sbi PortB,4;открыть дверь
      while: 
              rcall Svitim 
              rcall Zadergka 
              rcall Gasim 
              rcall Zadergka 
              dec temp3 
              brne while
		      cbi PortB,4
		      pop r25            
		      pop r24            
		      pop r23 
		      pop temp3 
              out SREG,temp3
              reti 
Gasim: 
              cbi PortD,0;погасили зеленый диод 
              ret 
Svitim: 
              sbi PortD,0;зажгли зеленый диод 
              ret 
Zadergka:      ; задерка 0,5 секунды 
              ldi R25,5 
              for: 
              dec R23 
              brne for 
              dec R24 
              brne for 
              dec R25 
              brne for                   
              ret
              
              ;********Подпрограмма записи в ОЗУ********     
zagrOZY: 
              st Z+,scancode
              inc count
			  ret
;********Подпрограмма проверки введенного кода******** 
proverka: ldi temp,bufer;  в temp начало адрес начала буфера епром
              ldi ZL,low(Line); адрес начала буфера в ОЗУ
              ldi ZH,high(Line)     
m10:        rcall eerd; Читаем очередной байт из епром
              ld temp1,z+; читаем очередной байт из ОЗУ
              cp temp2,temp1; сравниваем их
              brne m9; если не равны переходим к началу поморгав красным диодом
              dec count; уменьшаем содержимое счетчика байтов
              brne m10;если не конец продолжаем проверку
              rjmp m11; все равны - выходим
 m9:         ldi flag1,1 ; устанавливаем флаг того что не равны
 m11:       ret             
;********Подпрограмма записи в Епром******** 
eewr:      cli
             sbic EECR,EEWE
             rjmp eewr
             out EEAR,temp
             out EEDR,temp1
             sbi EECR,EEMWE
             sbi EECR,EEWE
             inc temp
             ret
;********Подпрограмма чтения из епром******** 
eerd:       cli
              sbic EECR,EEWE
              rjmp eerd
              out eear,temp
              sbi EECR,EERE
              in temp2,eedr
              inc temp
              ret
;********Подпрограмма "Звонок"******** 
zvonok:
             sbi portb,5 ; включили звонок
m16:       sbis PinD,4;
             rjmp m16
             cbi portb,5
             ret
;********Подпрограмма "beep"******** 
beep:    
             push temp5
              push temp3
              push r23
              push r24
              push r25
              ldi temp5,125; количество импульсов
m17:      sbi PortB,6 ; послали первый импульс
              rcall zadergka2; длительность 1,9 мсек
              cbi PortB,6
              rcall zadergka2;
              dec temp5
              brne m17
              pop r25
              pop r24
              pop r23
              pop temp3
              pop temp5
              ret
              
 ;********Подпрограмма задержки ******** 
zadergka2:
push Temp1
          push Temp2
          ldi Temp1,0
          ldi Temp2,10
d11: dec Temp1
          brne d11
          dec Temp2
          brne d11
          pop Temp2
          pop Temp1
          ret

              
              
