; *********************************************************
; Автор:            Карпов Дмитрий Анатольевич
; Дата/Время:       01.10.2012/00:14:48
; Версия:           1.0
; *********************************************************
; Микроконтроллер:  ATmega8A-PU
; Тактовая частота: 16 МГц
; *********************************************************
; Выполняемые функции: индикация чисел на 4-х разрядном
;                      7 сегментном индикаторе
; *********************************************************

.include"m8Adef.inc"

    .def	Temp=R16
	.def	Temp1=R17
	.def	Temp2=R18
	.def    Temp3=R19
	.def    Temp4=R20
	.def    Temp5=R21
	.def    Temp6=R22
	.def    Dg=R23
	.def    Point=R24

.dseg

Digit:     .byte 4

.cseg
.org 0

;****************************************************
; Прерывания
;****************************************************
rjmp Reset           ; все прерывания
rjmp INT_0
rjmp INT_1
rjmp Timer2_comp2
rjmp Timer2_OVF2
rjmp Timer1_capt1
rjmp Timer1_compA1
rjmp Timer1_compB1
rjmp Timer1_OVF1
rjmp Timer0_OVF0
rjmp UART_STC
rjmp UART_RXC
rjmp UART_UDRE
rjmp UART_TXC
rjmp ADCC
rjmp EE_RDY
rjmp ANA_COMP
rjmp TWI
rjmp SPM_RDY

;Reset:               ; выход из неиспользуемых прерываний
INT_0:
INT_1:
Timer2_comp2:
Timer2_OVF2:
Timer1_capt1:
;Timer1_compA1:
Timer1_compB1:
Timer1_OVF1:
Timer0_OVF0:
UART_STC:
UART_RXC:
UART_UDRE:
UART_TXC:
ADCC:
EE_RDY:
ANA_COMP:
TWI:
SPM_RDY:
              reti

;****************************************************
; ИНИЦИАЛИЗАЦИЯ
;****************************************************

Reset:        ldi Temp,0b11111111   ;настройка портов на выход
              out DDRD,Temp
              ldi Temp,0b00001111
              out DDRC,Temp

              ldi Temp,0b00010000   ;разрешить прерывания компаратора
              out TIMSK,Temp

			  ldi Temp,0b00000100   ;тактовый сигнал СК/256
			  out TCCR1B,Temp

			  ldi Temp,0xF4         ;таймер считает до 62500
			  out OCR1AH,Temp
			  ldi Temp,0x24
			  out OCR1AL,Temp

              ldi Temp,low(RamEnd)  ;установка указателя стека
              out SPL,Temp
              ldi Temp,high(RamEnd)
              out SPH,Temp

              ldi Temp,0            ;загрузка начальных значений
              sts Digit,Temp      
              sts Digit+1,Temp
              sts Digit+2,Temp
              sts Digit+3,Temp
			  ldi Temp1,0
			  ldi Temp2,0
			  ldi Temp3,0
			  ldi Temp4,0
			  ldi Temp5,0
			  ldi Temp6,0
			  ldi Dg,0
			  ldi Point,0

			  ldi Temp,0            ;обнуление таймера
			  out TCNT1H,Temp
			  out TCNT1L,Temp

			  sei                   ;разрешить прерывания


;*********************************************************
;MAIN
;*********************************************************

IndicCycle:     		  
			  
	     cp Temp6,Dg       ;сравниваем 
         breq HappyEnd     ;если равны ничего не меняем

		 com Point         ;побитная инверсия

         mov Temp6,Dg      ;копируем в регистр 4 разряда
         cpi Temp6,0       ;сравниваем с 0 (первоначально Dg и Temp4 равны и до этого не доходит)
		 breq Load6        ;если равны-переходим к Load4 и увеличиваем 3 разряд
		 rjmp HappyEnd     ;если нет-выводим 4 разряд

Load6:   cpi Temp5,5       ;и т. д.
		 breq Load5
		 inc Temp5
		 rjmp HappyEnd

Load5:   ldi Temp5,0
         cpi Temp4,9       
		 breq Load4
		 inc Temp4
		 rjmp HappyEnd

Load4:   ldi Temp4,0
         cpi Temp3,5       
		 breq Load3
		 inc Temp3
		 rjmp HappyEnd

Load3:   ldi Temp3,0
         cpi Temp2,3
         breq LoadX
OutX:	 cpi Temp2,9
		 breq Load2
		 inc Temp2
		 rjmp HappyEnd

LoadX:   cpi Temp1,2
         breq Load1
		 rjmp OutX

Load2:   ldi Temp2,0
		 inc Temp1
		 rjmp HappyEnd

Load1:   ldi Temp2,0
         ldi Temp1,0
		 rjmp HappyEnd
		 		 
HappyEnd:     sts Digit,Temp1        ;загрузка актуальных значений
              sts Digit+1,Temp2
			  sts Digit+2,Temp3
			  sts Digit+3,Temp4
			  
			  push Temp1             ;заносим содержимое регистров в стек, т. к. в подпрограмме Display эти регистры будут использованы
			  push Temp2
			  push Temp3
			  push Temp4           

              rcall Display          ;цикл индикации

	          pop Temp4              ;восстанавливаем содержимое регистров из стека (в обратном порядке)
			  pop Temp3
			  pop Temp2
			  pop Temp1

              rjmp IndicCycle

;*********************************************************
Display:
;последовательный вывод на индикацию содержимого
;переменной Digit

              lds Temp1,Digit      ;загружаем 0-ю ячейку
              ldi Temp,0b00001110  ;активируем 0-й разряд индикации
              out PortC,Temp
              rcall Decoder        ;вызываем 7-сегм. декодер
              out PortD,Temp1      ;выводим значение в порт
              rcall Delay1         ;ждем

              lds Temp1,Digit+1    ;и .т.д
              ldi Temp,0b00001101
              out PortC,Temp
              rcall Decoder
              out PortD,Temp1
			  sbrc Point,0
			  SBI PORTD,PB7
              rcall Delay1

              lds Temp1,Digit+2
              ldi Temp,0b00001011
              out PortC,Temp
              rcall Decoder
              out PortD,Temp1
              rcall Delay1

              lds Temp1,Digit+3
              ldi Temp,0b00000111
              out PortC,Temp
              rcall Decoder
              out PortD,Temp1
              rcall Delay1

              ret


;*********************************************************
Decoder:
;преобразование двоичного числа
;в код 7-сегментного индикатора

              ldi ZL,Low(DcMatrix*2)   ;инициализация массива
              ldi ZH,High(DcMatrix*2)

              ldi Temp2,0             ;прибавление переменной
              add ZL,Temp1            ;к 0-му адресу массива
              adc ZH,Temp2

              lpm                     ;загрузка значения
              mov Temp1,r0
              ret

DcMatrix:
;массив - таблица истинности декодера
              ;     hgfedcba   hgfedcba
              .db 0b00111111,0b00000110	;0,1
              .db 0b01011011,0b01001111	;2,3
              .db 0b01100110,0b01101101	;4,5
              .db 0b01111101,0b00000111	;6,7
              .db 0b01111111,0b01101111	;8,9

;*********************************************************
Delay1:
;цикл задержки

              push Temp1
              push Temp2


              ldi Temp1,0
              ldi Temp2,50

d11:          dec Temp1
              brne d11
              dec Temp2
              brne d11

              pop Temp2
              pop Temp1

              ret

;****************************************************
; ОБРАБОТЧИК ПРЕРЫВАНИЯ КОМПАРАТОРА
;****************************************************

Timer1_compA1:
         ldi Temp,0            ;обнуление таймера
         out TCNT1H,Temp
         out TCNT1L,Temp

         cpi Dg,9
         breq Load
         inc Dg
		 rjmp Output

Load:    ldi Dg,0
Output:  reti                  ;выход из обработчика
