; Advanced Nixie Clock (6 digit) For STATIC INDICATION!
; Copyright Vladislav B. Ivanov (с) 2015-2016
; Russia, Astrakhan
; 
; vladislav370@gmail.com


.include "c:\vlad\asm\Appnotes\m8def.inc"
.org 0x000 

;--- общее
.equ max_digits = 6			; число разрядов в индикаторе
.equ default_mode = 1			; режим с которого стартует прошивка /ЧЧ:ММ:CC/
.equ blink_time = 30			; частота мигания символами в режиме установок
.equ key_delay = 30			; время перед повтором нажатия кнопки
.equ key_rate = 18			; время выдачи повторов символа
.equ screen_bright = 180		; яркость цифр по умолчанию
.equ screen_bright_user = 6		; яркость заданная пользователем по умолчанию (1-9)
.equ play_temp_def = 16		        ; темп воспроизведения по умолчанию (1/16)
.equ tim_500 = 163		        ; число тиков таймера для ~1/500 сек (константа для коррекции хода)

;--- линии порта вывода SPI
.equ OE = 0				; линия OE регистров (ШИМ)
.equ SS = 2				; защелкивание 595х
.equ MOSI = 3				; данные
.equ SCK = 5				; стробирование

; --- DALLAS 1-Wire
.equ DALLAS_PORT	= DDRD		; конфигур порта #D
.equ DALLAS_PORT_PIN    = PIND		; линия порта #D
.equ DALLAS_PORT_LINE   = 4
.equ DALLAS_PORT_line_0 = 0b00010000	; линия #4 порта D в состояние "0"
.equ DALLAS_PORT_line_Z = 0b00000000	; линия #4 порта D в состояние "Z"
.equ DALLAS_delay = 10			; задержка в протоколе 1-wire по 1.7 мКсек
					; подбирать под ёмкость линии связи с датчиком!
; -----------------------------
; --- переменные в области SRAM
; -----------------------------
.equ SRAM_DATA = 256		        ; адрес начала буфера в SRAM
.equ SRAM_DATA_SIZE = 200		; размер буфера

;-- общие
.equ BRIGHT = 0				; яркость экрана
.equ DM = 2				; ЧРВ день-месяц
.equ YY = 4				; ЧВР год
.equ TEMP = 6				; текущая температура


;--- проткол 1-Wire
.equ DALLAS_STATUS = 8			; статус протокола 1-Wire
					; Младший байт - низкоуровневый протокол
					; 0 - канал 1-Wire свободен, иначе занят
					; 1 - команда Reset
					;    2 - ожидание сигнала Presense
					;    3 - сигнал Presense получен
					; 4 - команда Presense
					; 5 - команда прочитать n битов с шины
					; 6 - команда вывести n битов в шину
					; 128 - команда выполнена
					; 255 - ошибка инициализации
					;
					; Старший байт - статус прикладного сценария
					; сам сценарий - задается в теле процедуры
					; 0 - нет активных сценариев
					; 1 - команда запуска сценария
					; X - промежуточные этапы выполенения (2-3-4-5-6 и тд)
					; бит 6  - пуаза сценария (величина паузы
					; 	   в тиках таймера в DALLAS_PAUSE)
					; 128 - сценарий выполнен
					; 255 - возникли ошибки
					;
.equ DALLAS_COUNTER = 10 		; счетчик таймслотов для проткола 1-Wire
.equ DALLAS_DATA = 12			; регистр данных протокола 1-Wire 16 бит
.equ DALLAS_PAUSE =14			; длительность паузы (в тиках таймера) 
					; при выполнении сценария обмена
;-- проигрыватель
.equ PLAY_STATUS  = 16			; младший байт - номер мелодии, 0 звука нет
					; старший байт - счетчик длительности звучания ноты
.equ PLAY_COUNTER = 18			; счетчик ноты в мелодии
.equ PLAY_TEMP    = 20			; общий темп воспроизводимой мелодии

;-- время сработки будильник
.equ ALRM_HHMM    = 22			; будильник Часы-Минуты
.equ ALRM_STATUS  = 24                  ; статус будильника и мелодия
					; младший байт - мелодия (0 - буд. отключен)
					; старший байт - длительность воспроизведения
					; мелодии будильником, в минутах
					; старший бит - будильник активен сработал

.equ ALRM_CNTR =    28			; счетчик длительности подачи сигналов
					; таймера и будильника, сек

.equ DELIM_STATUS = 30			; статус разделителей разрядов:
					; 0 - всегда выключены все
					; 1 - мигают в такт секундам
					; 2 - всегда включены
					; 3 - мигает точка в углу в такт секундам
					; старший бит - флаг обновления индикатора
					; используется как триггер для исключения лишних
					; обновлений индикатора
				
.equ CORRECTION = 32			; величина программной корреции хода часов
					; 0...50 коррекция в "+", 50...100 - в "-"

.equ SCREEN_SHUTTLE = 34		; младший байт:
					; число секунд вывода времени 
					; если 0 время выводится постоянно
					; старший байт:
					; число секунд которые выводить дату
					; и температуру 

.equ BEEP_STATUS = 36			; состояние Beeper'a
					; 0 - отключен
					; 1 - часы отбивают каждый час (5 коротких 1 длинный)


rjmp FULL_RESET				; на начало программы
reti
reti
rjmp tim2_OVF
reti
reti
rjmp tim1_CMP			
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti

;------------------------------------------------------------------------
; урезанная до безобразия таблица ASCII символов для 7 сегментных индикаторов
; можно выводить не только цифры но и некоторые буквы. Это полное извращение
; конечно, но все - читается нормально. Часть букв, увы, вывести так невозможно
;
led7_bit_mask:
.db 0b00111111, 0b00000110, 0b01011011, 0b01001111 ; 0, 1, 2, 3 
.db 0b01100110, 0b01101101, 0b01111101, 0b00000111 ; 4, 5, 6, 7
.db 0b01111111, 0b01101111, 0b01110111, 0b01111100 ; 8, 9, A, b
.db 0b01011000, 0b01011110, 0b01111001, 0b01111001 ; c, d, E, F
.db 0b00000000, 0b00000000, 0b00110000, 0b00000000 ; g, H, I, J
.db 0b00111001, 0b00111000, 0b00000000, 0b00000000 ; k, L, m, n
.db 0b00000000, 0b01110011, 0b00000000, 0b00000000 ; o, P, q, r
.db 0b01101101, 0b00000000, 0b00111110, 0b00011100 ; S, t, U, v
.db 0b00000000, 0b00000000, 0b00000000, 0b00000000 ; w, x, Y, Z
.db 0b01000000, 0b00001000, 0b00000001, 0b00110000 ; -, _, ^, |
;------------------------------------------------------------------------

;-- тема "мелофон"
MELODY1:
.db 106, 76, 58, 76, 58, 34, 76, 58, 76, 57, 106, 76, 58, 76, 58, 34
.db 76, 58, 76, 57, 106, 76, 58, 76, 58, 34, 76, 58, 76, 57, 100, 76
.db 46, 76, 46, 28, 76, 46, 76, 45, 100, 82, 46, 82, 46, 28, 82, 46
.db 82, 45, 106, 76, 58, 76, 58, 34, 76, 58, 76, 57, 100, 76, 58, 28
.db 58, 77, 100, 77, 88, 64, 46, 16, 46, 64, 88, 64, 88, 58, 34, 16
.db 34, 58, 88, 58, 28, 47, 76, 46, 16, 34, 58, 89, 100, 76, 46, 28
.db 46, 76, 100, 76, 94, 76, 40, 22, 40, 77, 94, 77, 82, 64, 34, 10
.db 34, 65, 82, 64, 104, 255

;-- тема "я люблю тебя жизнь"
MELODY2:
.db 232, 15
.db 178, 221, 178, 221, 146, 254, 220, 129, 147, 98, 218, 254, 220, 100, 219, 100
.db 105, 220, 117, 130, 220, 135, 220, 147, 221, 136, 129, 220, 147, 218, 221, 178
.db 220, 221, 178, 146, 218, 219, 129, 220, 148, 74, 218, 219, 75, 220, 76, 87
.db 220, 99, 220, 106, 117, 221, 129, 220, 118, 99, 220, 104, 218, 105, 220, 106
.db 61, 75, 82, 73, 219, 105, 100, 87, 220, 87, 221, 76, 87, 220, 99, 105
.db 75, 220, 116, 220, 221, 105, 220, 118, 97, 220, 105, 221, 118, 128, 217, 117
.db 221, 130, 105, 220, 129, 220, 148, 177, 220, 129, 221, 136, 129, 220, 146, 218
.db 255, 0

;-- "полонез Агинского"
MELODY3:
.db 232, 15
.db 115, 124, 118, 111, 117, 142, 220, 142, 148, 157, 141, 117, 117, 85, 117, 98
.db 106, 109, 129, 74, 88, 92, 112, 116, 130, 118, 220, 118, 130, 139, 159, 148
.db 142, 148, 160, 148, 130, 112, 118, 130, 142, 148, 142, 160, 142, 118, 88, 67
.db 87, 76, 70, 76, 88, 76, 58, 40, 46, 58, 70, 76, 88, 94, 88, 76
.db 94, 74, 85, 255

;-- "прекрасное далеко"
MELODY4:
.db 232, 16
.db 254, 58, 58, 221, 58, 221, 58, 221, 56, 64, 63, 46, 221, 45, 57, 64
.db 221, 63, 58, 76, 221, 76, 221, 76, 221, 76, 221, 76, 220, 75, 86, 34
.db 221, 34, 44, 34, 28, 32, 219, 58, 221, 58, 221, 58, 220, 58, 221, 56
.db 64, 221, 63, 46, 220, 45, 57, 64, 221, 63, 57, 76, 221, 76, 221, 76
.db 221, 75, 87, 99, 106, 76, 56, 106, 221, 105, 81, 63, 81, 73, 255, 0

;-- "постой паровоз"
MELODY5:
.db 117, 69, 220, 69, 221, 75, 69, 75, 86, 221, 117, 87, 136, 118, 81, 87
.db 99, 110, 220, 221, 111, 116, 220, 221, 99, 111, 221, 117, 129, 141, 147, 158
.db 255, 0

;-- "Бах шутка"
MELODY6:
.db 232, 15
.db 46, 220, 28, 46, 76, 220, 46, 76, 100, 220, 76, 100, 117, 220, 148, 118
.db 100, 118, 106, 118, 106, 118, 124, 106, 88, 106, 99, 118, 220, 46, 220, 28
.db 46, 76, 220, 46, 76, 100, 220, 76, 100, 117, 220, 100, 220, 100, 220, 100
.db 220, 100, 220, 45, 100, 220, 101, 89, 101, 89, 106, 220, 76, 220, 76, 220
.db 76, 220, 76, 220, 27, 76, 220, 77, 71, 77, 71, 82, 220, 106, 76, 58
.db 76, 64, 76, 64, 76, 82, 64, 46, 64, 58, 64, 58, 64, 76, 58, 76
.db 82, 76, 46, 76, 82, 76, 34, 76, 82, 76, 28, 76, 82, 76, 28, 34
.db 46, 34, 58, 64, 76, 58, 220, 65, 59, 65, 221, 75, 220, 46, 220, 28
.db 46, 76, 220, 46, 76, 100, 220, 76, 100, 117, 220, 148, 118, 100, 118, 106
.db 118, 106, 118, 124, 106, 88, 106, 99, 118, 220, 46, 220, 28, 46, 76, 220
.db 46, 76, 100, 220, 76, 100, 117, 220, 100, 220, 100, 220, 100, 220, 100, 220
.db 45, 100, 220, 101, 89, 101, 89, 106, 220, 76, 220, 76, 220, 76, 220, 76
.db 220, 27, 76, 220, 77, 71, 77, 71, 82, 220, 106, 76, 58, 76, 64, 76
.db 64, 76, 82, 64, 46, 64, 58, 64, 58, 64, 76, 58, 76, 82, 76, 46
.db 64, 76, 58, 220, 65, 59, 65, 221, 75, 220, 76, 220, 58, 76, 106, 220
.db 76, 106, 130, 220, 106, 130, 147, 220, 111, 118, 221, 87, 94, 76, 58, 221
.db 70, 76, 69, 88, 220, 70, 220, 46, 70, 88, 220, 70, 88, 106, 220, 88
.db 106, 128, 100, 76, 100, 88, 100, 88, 100, 106, 88, 70, 88, 76, 88, 76
.db 88, 100, 76, 100, 106, 100, 70, 100, 106, 100, 58, 100, 106, 100, 46, 100
.db 106, 100, 46, 58, 70, 58, 76, 88, 100, 76, 220, 89, 77, 89, 221, 99
.db 220, 76, 220, 76, 220, 76, 220, 76, 220, 28, 220, 76, 220, 77, 71, 77
.db 71, 88, 220, 88, 220, 88, 220, 88, 220, 88, 220, 34, 220, 88, 220, 89
.db 77, 89, 77, 100, 220, 46, 220, 28, 46, 58, 68, 47, 59, 71, 77, 86
.db 71, 77, 89, 101, 112, 88, 70, 88, 112, 118, 112, 118, 124, 220, 148, 220
.db 141, 148, 220, 117, 70, 82, 88, 82, 221, 86, 97, 255

;-- "Snap Rhytm is a dancer"
MELODY7:
.db 232, 15
.db 219, 221, 40, 82, 64, 82, 52, 82, 64, 82, 106, 136, 106, 136, 82, 136
.db 106, 136, 94, 124, 94, 124, 70, 124, 94, 124, 82, 112, 82, 112, 64, 112
.db 82, 112, 40, 82, 64, 82, 52, 82, 64, 82, 106, 136, 106, 136, 82, 136
.db 106, 136, 94, 124, 94, 124, 70, 124, 94, 124, 82, 112, 82, 112, 64, 112
.db 82, 112, 255, 0

;-- короткий beep
MELODY8:
.db  232, 19, 28, 255

;-- длинный beep
MELODY9:
.db  232, 9, 25, 255


; -------------------------------------------------------
; таблица из 3х октав и нот для проигрывания мелодий
; частота CPU=8 Мгц! Для другой частоты - надо пересчитывать!!!
NOTY:
;--- #3
.db low(8000000/8/1975/2), high(8000000/8/1975/2)    ; си
.db low(8000000/8/1864/2), high(8000000/8/1864/2)    ; ля#
.db low(8000000/8/1760/2), high(8000000/8/1760/2)    ; ля
.db low(8000000/8/1661/2), high(8000000/8/1661/2)    ; соль#
.db low(8000000/8/1568/2), high(8000000/8/1568/2)    ; соль
.db low(8000000/8/1479/2), high(8000000/8/1479/2)    ; фа#
.db low(8000000/8/1397/2), high(8000000/8/1397/2)    ; фа
.db low(8000000/8/1318/2), high(8000000/8/1318/2)    ; ми
.db low(8000000/8/1244/2), high(8000000/8/1244/2)    ; ре#
.db low(8000000/8/1174/2), high(8000000/8/1174/2)    ; ре
.db low(8000000/8/1108/2), high(8000000/8/1108/2)    ; до#
.db low(8000000/8/1046/2), high(8000000/8/1046/2)    ; до
;--- #2
.db low(8000000/8/987/2),  high(8000000/8/987/2)     ; си
.db low(8000000/8/932/2),  high(8000000/8/932/2)     ; ля#
.db low(8000000/8/880/2),  high(8000000/8/880/2)     ; ля
.db low(8000000/8/830/2),  high(8000000/8/830/2)     ; соль#
.db low(8000000/8/783/2),  high(8000000/8/783/2)     ; соль
.db low(8000000/8/739/2),  high(8000000/8/739/2)     ; фа#
.db low(8000000/8/698/2),  high(8000000/8/698/2)     ; фа
.db low(8000000/8/659/2),  high(8000000/8/659/2)     ; ми
.db low(8000000/8/622/2),  high(8000000/8/622/2)     ; ре#
.db low(8000000/8/587/2),  high(8000000/8/587/2)     ; ре
.db low(8000000/8/554/2),  high(8000000/8/554/2)     ; до#
.db low(8000000/8/523/2),  high(8000000/8/523/2)     ; до
;--- #1
.db low(8000000/8/493/2),  high(8000000/8/493/2)     ; си
.db low(8000000/8/466/2),  high(8000000/8/466/2)     ; ля#
.db low(8000000/8/440/2),  high(8000000/8/440/2)     ; ля
.db low(8000000/8/415/2),  high(8000000/8/415/2)     ; соль#
.db low(8000000/8/392/2),  high(8000000/8/392/2)     ; соль
.db low(8000000/8/370/2),  high(8000000/8/370/2)     ; фа#
.db low(8000000/8/349/2),  high(8000000/8/349/2)     ; фа
.db low(8000000/8/329/2),  high(8000000/8/329/2)     ; ми
.db low(8000000/8/311/2),  high(8000000/8/311/2)     ; ре#
.db low(8000000/8/293/2),  high(8000000/8/293/2)     ; ре
.db low(8000000/8/277/2),  high(8000000/8/277/2)     ; до#
.db low(8000000/8/261/2),  high(8000000/8/261/2)     ; до

;------------------------------------------------------------------------
;		*** ПРЕРЫВАНИЕ ЧАСОВ РЕАЛЬНОГО ВРЕМЕНИ ***
;------------------------------------------------------------------------
TIM2_OVF:
	push  r16
	in    r16, SREG
	push  r16
	
	mov   r16, r4			; счетчик прерываний таймера
	andi  r16, 0b01111111
	cpi   r16, 127			; старшая часть (0-127)
	breq  one_sec
	inc   r16
	ori   r16, 128
	mov   r4,  r16
	rjmp  exit_int	

one_sec:
	ldi   r16, 128
	mov   r4,  r16
	mov   r16, r5
	andi  r16, 0b01111111
	cpi   r16, 59
	breq  reset_sec
	inc   r16
	ori   r16, 128
	mov   r5, r16                           ; главный счетчик секунд
	rjmp  exit_int

reset_sec:
	ldi   r16, 128                    	; конец минутного интервала
	mov   r5, r16	
	ldi   r16, 59
	cp    r6, r16
	breq  reset_min
	inc   r6                          	; главный счетчик минут
	ldi   r16, 30
	cp    r6, r16
	breq  correct
	rjmp  exit_int

correct:
	ldi   r16, 0b10000000			; раз в час, в 30 минут, в r6
	or    r6, r16				; взводим старший бит
	rjmp  exit_int

reset_min:
	clr   r6				; конец часового интервала
	ldi   r16, 23
	cp    r7, r16
	breq  reset_hou
	inc   r7				; главный счетчик часов
	rjmp  exit_int

reset_hou:
	ldi   r16, 128				; уст. флага конца суточного интервала
	mov   r7, r16				

exit_int:
	pop   r16
	out   SREG, r16
	pop   r16
	reti
;------------------------------------------------------------------------
; 		*** СИНТЕЗАТОР ВОСПРОИЗВЕДЕНИЯ МЕЛОДИЙ ***
;------------------------------------------------------------------------
TIM1_CMP:
	push   r16
	in     r16, SREG
	sbic   PINC,  0
	rjmp   play_port
	sbi    PORTC, 0
	rjmp   exit_int1

play_port:
	cbi    PORTC, 0

exit_int1:
	out    SREG, r16
	pop    r16
	reti
;-----------------------------------------------------------------------------:
; процедура умножения беззнакового числа 
; r16 - множимое
; r17 - множитель
; r17:r18 младший:старший байт результата
mul_8x8:
	clr  r18      		;очистить  старший байт результата
	lsr  r17      		;cдвинуть вправо  множитель
	brcc noad80    	        ;переход, если С=0
	add  r18, r16 		;прибавить множимое к старшему байту результата
noad80:	ror  r18      		;сдвинуть вправо старший байт результата
	ror  r17      		;сдвинуть вправо младший байт результата и множитель
	brcc noad81    	        ;переход, если С=0
	add  r18, r16 		;прибавить множимое к старшему байту результата
noad81: ror  r18
	ror  r17
	brcc noad82
	add  r18, r16
noad82: ror  r18
	ror  r17
        brcc noad83
        add  r18, r16
noad83: ror  r18
        ror  r17
        brcc noad84
        add  r18,r16
noad84: ror  r18
        ror  r17
        brcc noad85
        add  r18,r16
noad85: ror  r18
        ror  r17
	brcc noad86
	add  r18,r16
noad86: ror  r18
	ror  r17
	brcc noad87
	add  r18,r16
noad87: ror  r18
	ror  r17
	ret
;------------------------------------------------------------------------
; 16bit/16bit Unsigned Division
;
; Register Variables
;  Call:  var1[1:0] = dividend (0x0000..0xffff)
;         var2[1:0] = divisor (0x0001..0x7fff)
;         mod[1:0]  = <don't care>
;         lc        = <don't care> (high register must be allocated)
;
;  Result:var1[1:0] = var1[1:0] / var2[1:0]
;         var2[1:0] = <not changed>
;         mod[1:0]  = var1[1:0] % var2[1:0]
;         lc        = 0
;
; Size  = 16 words
; Clock = 179..211 cycles (+ret)
; Stack = 0 byte
;
div16x16:
	push    r2
	push    r3
	push    r16        
	clr	r2		
	clr	r3		
	ldi	r16, 16					
	lsl	r17		
	rol	r18		
	rol	r2		
	rol	r3		
	cp	r2, r19		
	cpc	r3, r20 	
	brcs	PC+4		
	inc	r17		
	sub	r2, r19 	
	sbc	r3, r20 	
	dec	r16		
	brne	PC-11		
	mov 	r19, r2
	mov	r20, r3	
	pop r16
	pop r3
	pop r2
	ret
;-----------------------------------------------------------------------------
bin16_dec5_SPI:		 ; выводит в SPI число 0-65535 из r17:r18
	push r11
	push r12
	push r13
	push r14
	push r15
	push r21
	push r22
	mov  r11, r17
	mov  r12, r18
	rcall bin16_dec5
	mov r22, r16
	ldi r17, 1
	ldi r19, 1

	; 2 разряд
	mov r16, r22
	ori r16, $30
	rcall write_spi

	; 1 разряд
	mov r16, r11
        ori r16, $30
	rcall write_spi

	; 4 разряд
	mov r16, r14
	ori r16, $30
	rcall write_spi

	; 3 разряд
	mov r16, r13
	ori r16, $30
	rcall write_spi

	; пробел
        ldi r16, ' '
	rcall write_spi

	; 5 разряд
     	mov r16, r15
        ori r16, $30
	rcall write_spi

	pop r22
	pop r21
	pop r15
	pop r14
	pop r13
	pop r12
	pop r11
	ret
;------------------------------------------------------------------------
; процедура перевода числа из r11:r12 в десятичный формат
; результат в r15:r14:r13:r16:r11
bin16_dec5:
	push    r17
	push    r18
	ldi     r17, low(10000)
        ldi     r18, high(10000)
        rcall   bin2ASCII_digit
        mov     r15, r16
        ldi     r17, low(1000)
        ldi     r18, high(1000)
        rcall   bin2ASCII_digit
        mov     r14, r16
        ldi     r17, low(100)
        ldi     r18, high(100)
        rcall   bin2ASCII_digit
        mov     r13, r16
        ldi     r17, low(10)
        ldi     r18, high(10)
        rcall   bin2ASCII_digit
	pop     r18
	pop     r17
	ret

bin2ASCII_digit:                
	ldi     r16, -1
bin2ASCII_digit_loop:           
	inc     r16
        sub     r11, r17
        sbc     r12, r18
        brsh    bin2ASCII_digit_loop
        add     r11, r17
        adc     r12, r18
	ret
;------------------------------------------------------------------------
; процедура заполняет индикатор или нужное число его разрядов символом.
; символ просто выводится в порт SPI, последовательно, бит за битом. При 
; этом, то что ранее было в регистрах - не стирается, а смещается вправо.
;
; r16 - ASCII символ который надо вывести
; r17 - количество символов которе надо вывести 
; r19 - порядковый номер выводимого символа
write_spi:
	push r18	
	push r17
	push r16

	mov  r18, r22
	andi r18, 0b01000000            ; скроллинг включен?
	breq write_spi_blink		; нет - проверяем запрос мигания
	cp r23, r19			; при включенном скроллинге
	brne write_spi_skip             ; пропускаем вывод или
	rjmp write_spi_char             ; выводим только 1 нужный разряд

write_spi_blink:
	cpi r23, 0			; есть запрос на мигание символа?
	breq write_spi_char		; нет - выводим
	rcall select_char_blink

write_spi_char:
	cbi PORTB, MOSI
	sbi PORTB, SS
	nop
	nop
	nop
	nop
	rcall convert_7led		; на выходе в r16 будет битовая маска	

write_spi_loop:
	nop
	nop
	nop
	nop
	push r19
	ldi  r19, 8			; число сегментов в индикаторе
	push r16

write_next_bit_spi:
	cbi PORTB, SCK
	nop
	nop
	nop
	nop
	lsl  r16
	brcc set_spi_0
	sbi  PORTB, MOSI		; установка лог 1 
	rjmp set_spi_1

set_spi_0:
	cbi  PORTB, MOSI		; установку лог. 0 на шине

set_spi_1:
	nop
	nop
	nop
	nop
	nop
	sbi PORTB, SCK
	dec  r19
	brne write_next_bit_spi	
	pop  r16
	dec  r17
	pop  r19
	brne write_spi_loop

write_spi_skip:
	pop  r16
	pop  r17
	pop  r18
	add  r19, r17
	ret
;--------------------------------------------------------------------------
; процедура по битовой маске в r23 и текущему выводимому символу в r19
; определяет, выводить символ или нет. Что обеспечивает режимы мигания.
; в r16 возвращается или исходный символ или пробел кода символ надо потушить
select_char_blink:
	push r16
	clr r18				; запрет мигания при нажатых клавишах + -
	mov r16, r24
	andi r16, 0b00001111
	cpi r16, 1
	breq select_blink
	cpi r16, 2
	breq select_blink
	mov r18, r23

select_blink:
	pop r16
	cpi r19, 1
	breq blink_char_1
	cpi r19, 2
	breq blink_char_2
	cpi r19, 3
	breq blink_char_3
	cpi r19, 4
	breq blink_char_4
	cpi r19, 5
	breq blink_char_5
	cpi r19, 6
	breq blink_char_6
	cpi r19, 7
	breq blink_char_7
	cpi r19, 8
	breq blink_char_8
	ret			; для выводимого символа > 8 мигание не допускается

blink_char_1:
	andi r18, 0b00000001
	breq no_blink
	andi r16, 128
	ret

blink_char_2:
	andi r18, 0b00000010
	breq no_blink
	andi r16, 128
	ret

blink_char_3:
	andi r18, 0b00000100
	breq no_blink
	andi r16, 128
	ret

blink_char_4:
	andi r18, 0b00001000
	breq no_blink
	andi r16, 128
	ret

blink_char_5:
	andi r18, 0b00010000
	breq no_blink
	andi r16, 128
	ret

blink_char_6:
	andi r18, 0b00100000
	breq no_blink
	andi r16, 128
	ret

blink_char_7:
	andi r18, 0b01000000
	breq no_blink
	andi r16, 128
	ret

blink_char_8:
	andi r18, 0b10000000
	breq no_blink
	andi r16, 128

no_blink:
	ret
;------------------------------------------------------------------------
; процедура перевода ASCII символа  в битовую маску для 
; вывода  на 7 led индикаторе. Старший бит=1  включена точка.
; на входе r16 символ, на выходе в r16 битовая маска
;------------------------------------------------------------------------
convert_7led:
	push r17
	mov r17, r16
	andi r16, 0b01111111
	cpi r16, $30 ; "0"
	brlo char
	cpi r16, $3A ; "9"
	brsh char
	andi r16, 0b00001111
	rcall get_led_bit_mask
	rjmp test_dp_seg
char:   cpi r16, $41 ; 'A'
	brlo no_chr
	cpi r16, $5B ; 'Z'
	brsh no_chr
	andi r16, 0b00011111
	push r17
	ldi r17, 10
	dec r16
	add r16, r17
	pop r17
	rcall get_led_bit_mask
	rjmp test_dp_seg
no_chr:	cpi r16, '-'	; '-'
	brne sign1
	ldi r16, 36
	rcall get_led_bit_mask
	rjmp test_dp_seg
sign1:  cpi r16, '_'	; '_'
	brne sign2
	ldi r16, 37
	rcall get_led_bit_mask
	rjmp test_dp_seg
sign2:	cpi r16, '^'    ; '^'
	brne sign3
	ldi r16, 38
	rcall get_led_bit_mask
	rjmp test_dp_seg
sign3:	cpi r16, '|'    ; '|'
	brne char_empty
	ldi r16, 39
	rcall get_led_bit_mask
	rjmp test_dp_seg
char_empty:
	clr  r16               ; пусто, заданный символ вывести невозможно //
test_dp_seg:
	andi r17, 0b10000000   ; выключить сегмент DP
	breq end_convert_7led
	ori  r16, 0b10000000   ; включить DP сегмент
end_convert_7led:
	pop r17
	ret
;------------------------------------------------------------------------
; процедура возвращает битовую маску в r16
; на входе R16 содержит номер байта в массиве
;------------------------------------------------------------------------
get_led_bit_mask:	
	ldi ZH, high(led7_bit_mask*2)
	ldi ZL, low(led7_bit_mask*2) 
	add ZL, r16
	lpm
	mov r16, r0
	ret
;------------------------------------------------------------------------
; процедура выполняет "защелкивание" данных в регистрах
; вывода после чего данные сразу же выводятся на индикатор
store_spi:
	nop
	nop
	nop
	nop
	nop
	nop
	cbi PORTB, SS
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	sbi PORTB, SS
	nop
	nop
	nop
	nop
	nop
	ret
;------------------------------------------------------------------------
; процедура очищает буфер для данных в SRAM при старте
clear_SRAM:
	ldi XH,   high(SRAM_DATA)	; адрес
    	ldi XL,   low(SRAM_DATA)	;    массива хранения данных в SRAM
    	ldi r17,  SRAM_DATA_SIZE	; размер буфера
    	clr r16				; заполняем 0
clear_SRAM_loop:
    	st  X+, r16
    	dec r17
    	brne clear_SRAM_loop
	ret
;------------------------------------------------------------------------
; процедура возвращает значение параметра из SRAM
; r16 - адрес параметра
; r17:r18 - значение параметра
get_SRAM:
	ldi XH, high(SRAM_DATA)		; адрес
    	ldi XL, low(SRAM_DATA)		;    массива хранения данных в SRAM
	add XL, r16			; смещение на переменную в массиве
	ld r17, X+			; младшая часть
	ld r18, X+			; старшая часть
	ret

;------------------------------------------------------------------------
; процедура записывает в SRAM в параметр r16 значение из r17:r18
set_SRAM:
	ldi XH, high(SRAM_DATA)		; адрес
    	ldi XL, low(SRAM_DATA)		;    массива хранения данных в SRAM
	add XL, r16			; смещение на переменную в массиве
	st X+, r17			; младшая часть
	st X+, r18			; старшая часть
	ret
;------------------------------------------------------------------------
; деление однобайтового безнакового часла
div8u:
; r16 делимое
; r17 делитель
; r18 счетчик цикла

; r16 частное
; r15 остаток

                clr     r15          ;очистить остаток и перенос
                ldi     r18,9        ;инициализировать счетчик цикла
d8u_1:          rol     r16            ;делимое/результат сдвинуть влево
                dec     r18          ;уменьшить на единицу счетчик цикла
                brne    d8u_2           ;переход, если не ноль
                ret


d8u_2:          rol     r15          ;остаток сдвинуть влево
                sub     r15,r17     ;остаток= остаток -  делитель
                brcc    d8u_3           ;если результат < 0
                add     r15,r17     ;восстановить остаток
                clc                     ;сбросить перенос для формирования результата

                rjmp    d8u_1           ;иначе установить перенос для
d8u_3:          sec                     ;формирования результата
                rjmp    d8u_1           ;вернуться назад
;------------------------------------------------------------------------
; процедура управляет флагами в r23 что совместно с процедурой display
; заставляет мигать индикатор отдельными разрядами в режимах установок
; какими разрядами мигать и в каких режимах - задается в теле процедуры.
display_blink:
	mov r16, r4		        ; мигаем только по прерываниям таймера
	andi r16, 128
	brne test_key_pressed
	ret

test_key_pressed:
	rcall get_key_code		; проверяем нажатие клавиши
	andi r16, 0b00001111		; при нажатой клавише запрет мигания
	breq key_press_up
	ret

key_press_up:
	mov r16, r22
	andi r16, 0b00111111

	cpi r16, 20			; режим установки часа
	breq blink_12

	cpi r16, 21			; режим установки минут
	breq blink_34

	cpi r16, 22			; режим установки секунд
	breq blink_56

	cpi r16, 23			; режим установки числа
	breq blink_12

	cpi r16, 24			; режим установки месяца
	breq blink_34

	cpi r16, 25			; режим установки года
	breq blink_56

	cpi r16, 26			; режим установки мелодии
	breq blink_34

	cpi r16, 27			; режим установки длительности мелодии
	breq blink_56

	cpi r16, 28			; режим установки часа будильника
	breq blink_34

	cpi r16, 29			; режим установки минут будильника
	breq blink_56

	cpi r16, 30			; режим установки коррекции хода
	breq blink_56

	cpi r16, 31			; режим установки разделителей
	breq blink_56

	cpi r16, 32		        ; режим установки смены экранов
	breq blink_34

	cpi r16, 33		        ; режим установки смены экранов
	breq blink_56

	cpi r16, 34		        ; режим установки биппера
	breq blink_56
	ret

;- мигание 1-2 разрядами
blink_12:
	ldi r18, 0b00110000	
	rjmp blinking

;- мигание 3-4 разрядами
blink_34:
	ldi r18, 0b00001100
	rjmp blinking

;- мигание 5-6 разрядами
blink_56:
	ldi r18, 0b00000011
	rjmp blinking

;- мигание 1-2-3-4-5-6 разрядами
blink_123456:
	ldi r18, 0b00111111

blinking:
	ldi r16, blink_time
	cp r3, r16
	brsh switch_blinking
	inc r3
	ret

switch_blinking:
	clr r3
	mov r16, r23
	and r16, r18
	brne blinking_on
	mov r23, r18
	ori r22, 128
	ret

blinking_on:
	clr r23
	ori r22, 128
	ret
;------------------------------------------------------------------------
; сброс флага прерывания таймера
reset_timer_flag:
	ldi r16, 0b01111111
	and r4, r16	
	ret
;------------------------------------------------------------------------
; основная процедура вывода данных
;------------------------------------------------------------------------
display:
	mov r16, r22
	andi r16, 0b10000000		; флаг запроса вывода
	brne display_now		; если сброшен - сразу на выход
	ret

display_now:
	andi r22, 0b01111111		; сброс бита запроса вывода
	mov  r16, r22
	andi r16, 0b00111111

	; -- режимы вывода
	cpi  r16, 1
	breq displ_HH_MM_SS
	cpi  r16, 2
	breq displ_HH_MM
	cpi  r16, 3
	breq displ_DD_MM_YY
	cpi  r16, 4
	breq displ_DD_MM
	cpi  r16, 5
	breq displ_TEMP
	cpi  r16, 6
	breq displ_TEMP
	cpi  r16, 7
	breq displ_TEMP_C
	cpi  r16, 8
	breq displ_BLANK

	; -- режимы установок
	cpi  r16, 20
	breq displ_HH_MM_SS
	cpi  r16, 21
	breq displ_HH_MM_SS
	cpi  r16, 22
	breq displ_HH_MM_SS
	cpi  r16, 23
	breq displ_DD_MM_YY
	cpi  r16, 24
	breq displ_DD_MM_YY
	cpi  r16, 25
	breq displ_DD_MM_YY
	cpi  r16, 26
	breq displ_PLAY
	cpi  r16, 27
	breq displ_PLAY
	cpi  r16, 28
	breq displ_BUD_HH_MM
	cpi  r16, 29
	breq displ_BUD_HH_MM
	cpi  r16, 30
	breq displ_CORR	
	cpi  r16, 31
	breq displ_delimetrs
	cpi  r16, 32
	breq displ_shuttle
	cpi  r16, 33
	breq displ_shuttle
	cpi  r16, 34
	breq displ_bepper
	cpi  r16, 35
	breq displ_bepper
	ret	

displ_HH_MM_SS:
	rcall display_HH_MM_SS
	rjmp display_done

displ_HH_MM:
	rcall display_HH_MM
	rjmp display_done

displ_DD_MM_YY:
	rcall display_DD_MM_YY
	rjmp display_done

displ_DD_MM:
	rcall display_DD_MM
	rjmp display_done

displ_TEMP:
	rcall display_TEMP
	rjmp display_done

displ_TEMP_C:
	rcall display_TEMP_C
	rjmp display_done

displ_PLAY:
	rcall display_PLAY
	rjmp display_done

displ_BLANK:
	rcall display_BLANK
	rjmp display_done

displ_BUD_HH_MM:
	rcall display_BUD_HH_MM
	rjmp display_done

displ_CORR:
	rcall display_corr
	rjmp display_done

displ_delimetrs:
	rcall display_delimetrs
	rjmp display_done

displ_shuttle:
	rcall display_shuttle
	rjmp display_done

displ_bepper:
	rcall display_bepper

display_done:
	rcall store_spi

	; -- наиболее удобное место для вызова команд считывания датчика DS18B20
	cpi  r22, 3
	breq update_temp
	cpi  r22, 4
	breq update_temp
	cpi  r22, 7
	breq update_temp
	ret

update_temp:
	ldi  r18, 1			 
	ldi  r16, dallas_status
	rcall set_sram
	ret
;------------------------------------------------------------------------
display_delimetrs:
	ldi    r19, 1
	ldi    r16, delim_status
	rcall  get_sram
	mov    r16, r17
	andi   r16, 0b01111111
	rcall  display_2_char	;-- логика разделителей (0-1-2-3)
	ldi    r16, ' '
	ldi    r17, 2
	rcall  write_spi
	ldi    r16, 'L'
	ldi    r17, 1
	rcall  write_spi
	ldi    r16, 'D'
	ldi    r17, 1
	rcall  write_spi
	ret
;------------------------------------------------------------------------
display_bepper:
	ldi   r19, 1
	ldi  r16, BEEP_STATUS
	rcall get_sram
	mov   r16, r17
	rcall display_2_char_delim		;-- состояние биппера
	ldi   r16, ' '
	ldi   r17, 2
	rcall write_spi
	ldi   r16, 'E'
	ldi   r17, 1
	rcall write_spi
	ldi   r16, 'B'
	ldi   r17, 1
	rcall write_spi
	ret
;------------------------------------------------------------------------
display_shuttle:
	ldi   r19, 1
	ldi  r16, screen_shuttle
	rcall get_sram
	push  r17
	mov   r16, r18
	rcall display_2_char_delim	;-- длительность вывода времени
	pop   r16
	rcall display_2_char_delim	;-- длительность вывода даты и темп
	ldi   r16, 'U'
	ldi   r17, 1
	rcall write_spi
	ldi   r16, 'S'
	ldi   r17, 1
	rcall write_spi
	ret
;------------------------------------------------------------------------
display_BUD_HH_MM:
	ldi   r19, 1
	ldi  r16, ALRM_HHMM
	rcall get_sram
	push  r18
	mov   r16, r17
	rcall display_2_char_delim	;-- минуты будильника
	pop   r16
	rcall display_2_char_delim	;-- часы будильника
	ldi   r16, 'L'
	ldi   r17, 1
	rcall write_spi
	ldi   r16, 'A'
	ldi   r17, 1
	rcall write_spi
	ret
;------------------------------------------------------------------------
display_DEBUG:
	ldi  r16, TEMP
	rcall get_sram
	rcall bin16_dec5_SPI
	ret
;------------------------------------------------------------------------
display_PLAY:
	ldi    r19, 1
	ldi    r16, ALRM_STATUS
	rcall  get_sram
	push   r17
	mov    r16, r18
	andi   r16, 0b01111111
	rcall  display_2_char_delim		;-- длительность звучания
	pop    r16
	rcall  display_2_char_delim		;-- мелодия будильника
	ldi    r16, 'L'
	ldi    r17, 1
	rcall  write_spi
	ldi    r16, 'P'
	ldi    r17, 1
	rcall  write_spi
	ret
;------------------------------------------------------------------------
display_CORR:
	ldi    r19, 1
	ldi    r16, CORRECTION
	rcall  get_sram
	push   r17
	mov    r16, r17
	cpi    r17, 50
	brlo   cr_plus
	breq   cr_plus	
	ldi    r16, 101
	sub    r16, r17
cr_plus:
	rcall  display_2_char			;-- величина коррекции
	ldi    r16, ' '
	ldi    r17, 2
	rcall  write_spi

	pop    r17
	cpi    r17, 51
	brsh   disp_corr_minus
	cpi    r17, 1
	brsh   disp_corr_plus
	ldi    r16, ' '
	ldi    r17, 1
	rcall  write_spi			;-- ноль
	sbi    PORTC, 4				;-- и сегмент плюс откл
	rjmp   disp_corr_down

disp_corr_minus:
	ldi    r16, '-'
	ldi    r17, 1
	rcall  write_spi                        ;-- знак минус
	sbi    PORTC, 4				;-- и сегмент плюс откл
	rjmp   disp_corr_down

disp_corr_plus:
	ldi    r16, '-'
	ldi    r17, 1
	rcall  write_spi                        ;-- знак минус
	cbi    PORTC, 4				;-- и сегмент плюс вкл
	rjmp   disp_corr_down

disp_corr_down:
	ldi    r16, 'K'
	ldi    r17, 1
	rcall  write_spi			;-- символ 'C'
	ret
;------------------------------------------------------------------------
; хранитель экрана
display_BLANK:
	ldi    r19, 1
	ldi    r16, delim_STATUS
	rcall  get_sram
	andi   r17, 0b10000000
	breq   displ_normal_saver

	ldi    r17, 1
	ldi    r16, ' '
	ori    r16, 128				; точкой в углу мигаем
	rcall  write_spi
	ldi    r17, 5
	ldi    r16, ' '
	rcall  write_spi
	ret

displ_normal_saver:
	ldi    r16, ' '
	ldi    r17, 6				; просто пустой экран
	rcall  write_spi
	ret
;------------------------------------------------------------------------
; обычный вывод температуры - без десятых
display_TEMP:
	ldi    r19, 1
	ldi    r16, ' '
	ldi    r17, 1
	rcall  write_spi
	ldi    r16, 'C'
	ldi    r17, 1
	rcall  write_spi
	ldi    r16, TEMP
	rcall  get_sram
	push   r17
	mov    r16, r17
	rcall  display_2_char
	pop    r17
	rcall  display_TEMP_sign
	ldi    r16, ' '
	ldi    r17, 1
	rcall  write_spi
	ret
;------------------------------------------------------------------------
; расширенный вывод температуры с десятыми
display_TEMP_C:
	ldi    r19, 1
	ldi    r16, 'C'
	ldi    r17, 1
	rcall  write_spi
	ldi    r16, TEMP
	rcall  get_sram
	push   r17
	push   r17
	mov    r16, r18
	rcall  bin8_dec3
	ori    r16, $30
	ldi    r17, 1
	rcall  write_spi			; -- десятые
	pop    r16
	rcall  bin8_dec3
	ori    r16, $30
	ori    r17, $30
	ori    r16, 128				; -- точка вкл
	push   r17
	ldi    r17, 1
	rcall  write_spi			;-- градусы
	pop    r16
	ldi    r17, 1
	rcall  write_spi			;-- десятки градусов
	pop    r17
	rcall  display_TEMP_sign
	ldi    r16, ' '
	ldi    r17, 1
	rcall  write_spi
	ret
;------------------------------------------------------------------------
; вывод знака температуры
display_TEMP_sign:
	cpi    r17, 0
	brne   temp_no_zero
	ldi    r16, ' '
	ldi    r17, 1
	rcall  write_spi
	clr    r17
	ret					; 0C, знак не выводим

temp_no_zero:
	push   r17
	ldi    r16, '-'
	ldi    r17, 1
	rcall  write_spi
	pop    r17
	sbi    PORTC, 2
	sbi    PORTC, 3
	andi   r17, 0b10000000
	breq   temp_plus3	
	sbi    PORTC, 4		; минус
	ret

temp_plus3:
	cbi    PORTC, 4		; плюс
	ret
;------------------------------------------------------------------------
display_HH_MM_SS:
	ldi   r16, delim_STATUS
	rcall get_sram
	andi  r17, 0b10000000
	breq  displ_normal_MMHHSS

	mov   r16, r5
	andi  r16, 0b01111111
	ldi   r19, 1
	rcall display_2_char_delim		;-- секунды с мигающей точкой
	rjmp  display_continue_MMHHSS

displ_normal_MMHHSS:
	mov   r16, r5
	andi  r16, 0b01111111
	ldi   r19, 1
	rcall display_2_char			;-- секунды

display_continue_MMHHSS:
	mov   r16, r6
	andi  r16, 0b01111111
	rcall display_2_char			;-- минуты
	mov   r16, r7
	andi  r16, 0b01111111
	rcall display_2_char			;-- часы
	ret
;------------------------------------------------------------------------
display_HH_MM:
	ldi   r19, 1
	ldi   r16, ' '
	ldi   r17, 1
	rcall write_spi

	ldi   r16, delim_STATUS
	rcall get_sram
	andi  r17, 0b10000000
	breq  displ_normal_MMHH
	mov   r16, r6
	andi  r16, 0b01111111
	rcall display_2_char_delim		;-- минуты
	rjmp  displ_continue_MMHH

displ_normal_MMHH:
	mov   r16, r6
	andi  r16, 0b01111111
	rcall display_2_char			;-- минуты

displ_continue_MMHH:
	mov   r16, r7
	andi  r16, 0b01111111
	rcall display_2_char			;-- часы
	ldi   r16, ' '
	ldi   r17, 1
	rcall write_spi
	ret
;------------------------------------------------------------------------
display_DD_MM_YY:
	ldi r16, YY
	rcall get_sram
	mov   r16, r17                    
	ldi   r19, 1
	rcall display_2_char_delim	;-- год
	ldi   r16, DM
	rcall get_sram
	push  r17
	mov   r16, r18
	rcall display_2_char_delim	;-- месяц
	pop   r16
	rcall display_2_char_delim	;-- день
	ret
;------------------------------------------------------------------------
display_DD_MM:
	ldi r19, 1
	ldi r17, 1
	ldi r16, ' '
	rcall write_spi
	ldi r16, DM
	rcall get_sram
	push r17
	mov r16, r18
	rcall display_2_char_delim	;-- день
	pop r16
	rcall display_2_char_delim	;-- месяц
	ldi r16, ' '
	ldi r17, 1
	rcall write_spi
	ret
;------------------------------------------------------------------------
; процедура перевода числа из r16 в десятичное число
; результат возвращается в регистры r16:r17:r18
bin8_dec3:
     	clr R18          
div1_l: subi R16, 100    ;вычитаем 100 пока не получим отрицательную разность
	brcs d1_end
	inc R18          ; +1 к разряду сотен
	rjmp div1_l
d1_end: subi R16, -100   ;корректируем остаток, добавляя 100
     	clr R17
div2_l:	subi R16, 10     ;вычитаем 10 пока не получим отрицательную разность
     	brcs d2_end
	inc r17          ; +1 к разряду десяток
	rjmp div2_l
d2_end:	subi R16, -10    ;корректируем остаток, добавляя 10
     	ret
;------------------------------------------------------------------------
; процедура воводит в SPI два десятичных разряда из r16
display_2_char:
	rcall bin8_dec3
	ori r16, $30
	ori r17, $30
	push r17
	ldi r17, 1
	rcall write_spi		; единицы
	pop r16
	ldi r17, 1
	rcall write_spi		; десятки
	ret
;------------------------------------------------------------------------
; процедура аналогична предидущей с той лишь
; разницей, что после вывода включается точка
display_2_char_delim:
	rcall bin8_dec3
	ori r16, $30
	ori r16, 128
	ori r17, $30
	push r17
	ldi r17, 1
	rcall write_spi		; единицы
	pop r16	
	ldi r17, 1
	rcall write_spi		; десятки
	ret
;------------------------------------------------------------------------
; в зависимости от нажатой клавиши возвращает в r24 код клавиши
get_key_code:
	clr r16
	sbic PIND, 0		; "DISPL" (4)
	ori r16,  0b00000100
	sbic PIND, 1            ; "SETUP" (5)
	ori r16,  0b00000101
	sbic PIND, 3            ; "-"  \            (1)
	ori r16,  0b00000001    ;       = "RESET"   (3)
	sbic PIND, 2            ; "+"  /            (2)
	ori r16,  0b00000010
	or r24, r16
	ret
;------------------------------------------------------------------------
interface:
	mov r16, r24
	andi r16, 0b10000000
	brne key_press_command
	ret

key_press_command:
	mov r16, r24
	andi r16, 0b00001111
	cpi r16, 4
	breq switch_displ
	cpi r16, 5
	breq switch_setup
	cpi r16, 1
	breq change_setup
	cpi r16, 2
	breq change_setup
	ret

switch_displ:
	rcall browse_display
	ori r22, 0b10000000
	clr r23
	ret

switch_setup:
	rcall browse_setup
	ori r22, 0b10000000
	clr r23
	ret

change_setup:
	rcall command_change
	ori r22, 0b10000000
	clr r23
	ret

;------------------------------------------------------------------------
command_change:
	clT
	cpi   r22, 20
	breq  setup_hh
	cpi   r22, 21
	breq  setup_mm
	cpi   r22, 22
	breq  setup_ss
	rjmp  setup_23

;--- установка часа
setup_hh:
	ldi r18, 23
	mov r19, r7
	andi  r19, 0b01111111
	rcall change
	mov r7, r19
	ret

;--- установка минут
setup_mm:
	ldi r18, 59
	mov r19, r6
	andi r19, 0b01111111
	rcall change
	mov r6, r19
	ret

;--- установка секунд
setup_ss:
	mov r18, r24
	andi r18, 0b00001111
	cpi r18, 2
	breq ss_add
	clr r16
	out TCNT2, r16
	clr r4
	clr r5	
	ret
ss_add:
	ldi r18, 59
	mov r19, r5
	andi r19, 0b01111111
	rcall change
	mov r5, r19
	ret

setup_23:
	cpi   r22, 23
	breq  setup_dd
	cpi   r22, 24
	breq  setup_mn
	cpi   r22, 25
	breq  setup_yy
	rjmp  setup_26

;--- установка числа
setup_dd:	
	ldi   r16, DM
	rcall get_sram
	push  r18
	ldi   r18, 31
	mov   r19, r17
	rcall change
	mov   r17, r19
	pop   r18
	ldi   r16, DM
	rcall set_sram
	ret

;--- установка месяца
setup_mn:
	ldi   r16, DM
	rcall get_sram
	push  r17
	mov   r19, r18
	ldi   r18, 12
	rcall change
	mov   r18, r19
	pop   r17
	ldi   r16, DM
	rcall set_sram
	ret

;--- установка года
setup_yy:
	ldi   r16, YY
	rcall get_sram
	push  r18
	mov   r19, r17
	ldi   r18, 100
	rcall change
	mov   r17, r19
	pop   r18
	ldi   r16, YY
	rcall set_sram
	ret

setup_26:
	cpi   r22, 26
	breq  setup_play
	cpi   r22, 27
	breq  setup_dly_play
	cpi   r22, 28
	breq  setup_ALRM_HH
	cpi   r22, 29
	breq  setup_ALRM_MM
	cpi   r22, 30
	breq  setup_CORRECTION
	rjmp  setup_31

;--- выбор мелодии будильника
setup_play:
	ldi   r16, ALRM_STATUS
	rcall get_sram
	push  r18
	mov   r19, r17
	ldi   r18, 7
	rcall change
	mov   r17, r19
	pop   r18
	ldi   r16, ALRM_STATUS
	rcall set_sram
	mov   r17, r19
	rcall reset_player	; проиграть выбранную мелодию
	ret

;--- выбор длительности мелодии будильника
setup_dly_play:
	ldi   r16, ALRM_STATUS
	rcall get_sram
	push  r17
	mov   r19, r18
	ldi   r18, 10
	rcall change
	mov   r18, r19
	pop   r17
	ldi   r16, ALRM_STATUS
	rcall set_sram
	ret

;--- установка часа будильника
setup_ALRM_HH:
	ldi   r16, ALRM_HHMM
	rcall get_sram
	push  r17
	mov   r19, r18
	ldi   r18, 23
	rcall change
	mov   r18, r19
	pop   r17
	ldi   r16, ALRM_HHMM
	rcall set_sram
	ret

;--- установка минут будильника
setup_ALRM_MM:
	ldi   r16, ALRM_HHMM
	rcall get_sram
	push  r18
	mov   r19, r17
	ldi   r18, 59
	rcall change
	mov   r17, r19
	pop   r18
	ldi   r16, ALRM_HHMM
	rcall set_sram
	ret

setup_CORRECTION:
	ldi   r16, CORRECTION
	rcall get_sram
	push  r18
	mov   r19, r17
	ldi   r18, 100
	rcall change
	mov   r17, r19
	pop   r18
	ldi   r16, CORRECTION
	rcall set_sram
	ret

setup_31:
	cpi   r22, 31
	breq  setup_delimetrs
	cpi   r22, 32
	breq  setup_shuttle_time
	cpi   r22, 33
	breq  setup_shuttle_date_temp
	cpi   r22, 34
	breq  setup_beeper
	; иначе режим установок неактивен
	; регулировка яркости цифр индикатора
	rcall bright_change
	ret

setup_delimetrs:
	ldi   r16, delim_status
	rcall get_sram
	push  r18
	andi  r17, 0b01111111
	mov   r19, r17
	ldi   r18, 3
	rcall change
	mov   r17, r19
	pop   r18
	ldi   r16, delim_status
	rcall set_sram
	ret

setup_shuttle_time:
	ldi   r16, SCREEN_SHUTTLE
	rcall get_sram
	push  r18
	mov   r19, r17
	ldi   r18, 99
	rcall change
	mov   r17, r19
	pop   r18
	ldi   r16, SCREEN_SHUTTLE
	rcall set_sram
	ret

setup_shuttle_date_temp:
	ldi   r16, SCREEN_SHUTTLE
	rcall get_sram
	push  r17
	mov   r19, r18
	ldi   r18, 99
	rcall change
	mov   r18, r19
	pop   r17
	ldi   r16, SCREEN_SHUTTLE
	rcall set_sram
	ret

setup_beeper:
	ldi   r16, BEEP_STATUS
	rcall get_sram
	push  r18
	mov   r19, r17
	ldi   r18, 1
	rcall change
	mov   r17, r19
	pop   r18
	ldi   r16, BEEP_STATUS
	rcall set_sram
	ret

;------------------------------------------------------------------------
; процедура сопоставляет значение яркости табло заданное пользователем
bright_change:
	push  r16
	ldi   r16, BRIGHT
	rcall get_sram
	ldi   r18, 9
	mov   r19, r17
	pop   r16
	seT
	rcall change
	cpi   r19, 0
	breq  bright0
	cpi   r19, 1
	breq  bright1
	cpi   r19, 2
	breq  bright2
	cpi   r19, 3
	breq  bright3
	cpi   r19, 4
	breq  bright4
	cpi   r19, 5
	breq  bright5
	cpi   r19, 6
	breq  bright6
	cpi   r19, 7
	breq  bright7
	cpi   r19, 8
	breq  bright8
	cpi   r19, 9
	breq  bright9
	clr   r16
	rjmp  set_new_bright
bright0:
	ldi r16, 40
	rjmp  set_new_bright
bright1:
	ldi r16, 50
	rjmp  set_new_bright
bright2:
	ldi r16, 65
	rjmp  set_new_bright
bright3:
	ldi r16, 100
	rjmp  set_new_bright
bright4:
	ldi r16, 120
	rjmp  set_new_bright
bright5:
	ldi r16, 145
	rjmp  set_new_bright
bright6:
	ldi r16, 180
	rjmp  set_new_bright
bright7:
	ldi r16, 200
	rjmp  set_new_bright
bright8:
	ldi r16, 225
	rjmp  set_new_bright
bright9:
	ldi r16, 255
set_new_bright:
	mov   r11, r16
	ldi   r16, BRIGHT
	mov   r17, r19
	clr   r18
	rcall set_sram
	ret
;------------------------------------------------------------------------
; процедура последовательно перебирает режимы вывода по нажатии кнопки 1
;------------------------------------------------------------------------
browse_display:
	ldi   r16, PLAY_STATUS
	rcall get_sram
	cpi   r17, 0		
	breq  set_display       ; звука нет
	clr   r17
	clr   r18
	rcall reset_player	; если включен звук - отключить
	ldi   r16, ALRM_CNTR    ; будильник тоже прерываем
	rcall set_sram		; если проигрывается
	ret

set_display:
	andi r22, 0b00111111
	cpi r22, 1
	breq set_display_2
	cpi r22, 2
	breq set_display_7
	cpi r22, 7
	breq set_display_8
	
; -- ЧЧ:ММ:CC
set_display_1:
	ldi r22, 1
	ori r22, 128
	ret

; -- ЧЧ:ММ
set_display_2:
	ldi r22, 2
	ori r22, 128
	ret

; -- температура вывод непрерывно
set_display_7:
	ldi r22, 7
	ori r22, 128
	ret

;-- пустой экран
set_display_8:
	ldi r22, 8
	ori r22, 128
	ret
;------------------------------------------------------------------------
; процедура последовательно перебирает режимы установок по нажанию кнопки 2
;------------------------------------------------------------------------
browse_setup:
	andi r22, 0b00111111
	cpi  r22, 34
	brsh set_setup_20
	cpi  r22, 20
	brlo set_setup_20
	inc  r22
	ret

set_setup_20:
	ldi r22, 20
	ret
;-----------------------------------------------------------------------------
FULL_RESET:
	rjmp RESET
;-----------------------------------------------------------------------------
; универсальная процедурка изменяющая значение любого параметра
; вход: r18 максимальное значение параметра 23 или 59 и тд
;       r19 исходное значение параметра
;       флаг T=1 запрещает переход через 0 или максимум, иначе - разрешено
; выход:
;	r19 новое значение параметра
;
change:	mov r16, r24
	andi r16, 0b00001111
	cpi r16, 2
	breq chg_add
	cpi r16, 1
	breq chg_sub
	ret
chg_add:
	cp r19, r18
	brsh chg_rst
	inc r19
	ret
chg_max:
	brTs exit_change
	mov r19, r18
	ret
chg_sub:
	cpi r19, 0
	breq chg_max
	dec r19
	ret	
chg_rst:
	brTs exit_change
	clr r19
exit_change:
	ret
;-----------------------------------------------------------------------------
; обработчик клавиатуры
inkey: 	andi r24, 0b01111111
	mov r16, r22
	
	rcall get_key_code
	cpi r16, 0
	breq key_up

	mov r16, r24
	andi r16, 0b11110000
	brne key_is_pressed

	ori r24,  0b00010000
	ret

key_press_first_ok:
	clr  r1
	andi r24, 0b00001111
	ori  r24, 0b10100000
	ret

key_up:	clr r24
	clr r1
	ret

key_press_start_delay:
	; выдача автоповторов разрешена 
	; только для кнопок "+" и "-" !
	mov  r16, r24
	andi r16, 0b00001111
	cpi r16, 1	
	breq key_34_pressed
	cpi r16, 2
	breq key_34_pressed
	cpi r16, 3
	breq key_34_pressed
	ret

key_34_pressed:
	clr r1
	andi r24, 0b00001111
	ori r24,  0b01000000
	ret

key_press_wait_delay:
	mov r16, r4
	andi r16, 0b10000000
	brne inc_wait_delay
	ret

inc_wait_delay:
	rcall reset_timer_flag
	mov r16, r1
	cpi r16, key_delay
	breq wait_delay_stop
	inc r1
	ret

wait_delay_stop:
	andi r24, 0b00001111
	ori r24,  0b11100000
	clr r1
	ret

set_key_rate:
	mov r16, r4
	andi r16, 0b10000000
	brne inc_key_rate
	ret

inc_key_rate:
	rcall reset_timer_flag
	mov r16, r1
	cpi r16, key_rate
	breq stop_key_rate
	inc r1	
	ret

stop_key_rate:
	clr r1
	ori r24,  0b10000000
	ret
	
key_is_pressed:
	clr  r2                    ; при нажатиях клавиш сброс счетчика смены режимов
	mov  r16, r24
	andi r16, 0b01100000
	cpi  r16, 0b01100000
	breq set_key_rate

	mov  r16, r24
	andi r16, 0b00010000
	brne key_press_first_ok

	mov  r16, r24
	andi r16, 0b00100000
	brne key_press_start_delay

	mov  r16, r24
	andi r16, 0b01000000
	brne key_press_wait_delay

	clr r24		; заглушка
	ret
;------------------------------------------------------------------------
; процедура обрабатывает секундные интервалы для формирования событий
; связанных с течением времени - обновление часов, календаря, будильника и тд
scheduler:
	mov r16, r5
	andi r16, 128
	brne clear_sec_flag
	ret

clear_sec_flag:
	ldi r16, 0b01111111
	and r5,  r16
	mov r16, r22
	andi r16, 0b00111111
	rcall display_switch
	brTc update_screen
	rjmp exit_scheduler

update_screen:
	cpi r16, 1			; режим часов HH:MM:SS
	breq update_clock
	cpi r16, 2			; режим часов HH:MM
	breq update_clock
	cpi r16, 7			; непрерывный вывод температуры
	breq update_clock

	; режимы установки времени (часы при этом идут)
	cpi r16, 20			; установка часа
	breq update_clock
	cpi r16, 21                     ; установка минут
	breq update_clock		
	cpi r16, 22			; установка секунд
	breq update_clock
	rjmp exit_scheduler

update_clock:
	ori r22, 128
	rjmp exit_scheduler

exit_scheduler:
	rcall chk_alarm
	rcall play_alarm
	rcall kalendar
	rcall beeper
	inc r2
	ret
;------------------------------------------------------------------------
beeper:	ldi   r16, BEEP_STATUS
	rcall get_sram
	cpi   r17, 0
	brne  beep_hour
	ret

beep_hour:
	mov   r19, r6
	andi  r19, 0b01111111
	cpi   r19, 59
	breq  beep_hour_sec
	cpi   r18, 59
	breq  beep_hour_sec
	ret

beep_hour_sec:
	cpi   r18, 59
	breq  beep_large
	mov   r18, r5
	andi  r18, 0b01111111
	rcall set_sram
	cpi   r18, 55
	brsh  beep_shrink
	ret

beep_shrink:
	ldi  r17, 8
	rcall reset_player
       	ret

beep_large:
	clr  r18
	rcall set_sram
	ldi  r17, 9
	rcall reset_player
       	ret

;------------------------------------------------------------------------
; календарь. cмена даты-месяца-года-века по окончанию суточного интервала
kalendar:
	mov  r16, r7
	andi r16, 0b10000000		; сутки закончились?
	brne next_day
	ret

;-- следующий день
next_day:
	clr  r7
	ldi  r16, DM
	rcall get_sram
	rcall return_last_day
	cp   r17, r20
	breq next_month
	inc  r17
	rcall set_sram	
	ret

;-- следующий месяц
next_month:
	cpi  r18, 12
	breq next_year
	inc  r18
	ldi  r17, 1
	rcall set_sram
	ret

;-- следующий год
next_year:
	ldi  r18, 1
	ldi  r17, 1
	rcall set_sram
	ldi  r16, YY
	rcall get_sram
	cpi  r17, 99
	breq next_vek
	inc  r17
	rcall set_sram
	ret

; -- следующее столетие	 :)
next_vek:
	clr  r17
	inc  r18
	rcall set_sram
	ret
;------------------------------------------------------------------------
; функция возвращвет последний день текущего месяца с учетом года
; in:  r17 - текущий день (1-31)
;      r18 - ткущий месяц (1-12)
; out: r20 - последний день этого месяца и года
return_last_day:
	ldi  r20, 31
	cpi  r18, 2
	breq mn2829
	cpi  r18, 4
	breq mn30
	cpi  r18, 6
	breq mn30
	cpi  r18, 9
	breq mn30
	cpi  r18, 11
	breq mn30
	; 31 день
	ret

;--- февраль отдельно проверяем високосный не високосный
mn2829:	ldi  r20, 29
	push r16
	push r17
	push r18
	ldi  r16, YY
	rcall get_sram	
	mov  r16, r17		; год - десятки единицы
	ldi  r17, 4
	rcall div8u		; делим на 4
	pop  r18
	pop  r17
	pop  r16
	clr  r19
	cp   r15, r19		; если не делится год не високосный
	breq mn29
mn30:   dec  r20		; 30 или 28 дней
mn29:	ret			; 29 дней
;------------------------------------------------------------------------
; процедура проверяет сработку будильника
; взводит статус будильника  при сработке
chk_alarm:
	ldi  r16, ALRM_STATUS
	rcall get_sram
	cpi  r17, 0                     ; мелодия не задана?
	brne chk_play_dly		; да - буд и таймер отключены
	ret

chk_play_dly:
	cpi  r18, 0                     ; длительность не задана? 
	brne chk_alrm_mm		; да - будильник отключен
	ret

;--- проверка минут
chk_alrm_mm:
	ldi  r16, ALRM_HHMM		; берем ЧЧ:ММ сработки будильника
	rcall get_sram
	mov  r19, r6			
	mov  r20, r7                    
	andi r19, 0b01111111            ; флаги обновления ЧРВ
	andi r20, 0b01111111            ;    игнорируем
	cp   r17, r19
	breq chk_alrm_hh
	; -- сброс флага сработки будильника при несовпадении
	ldi  r16, ALRM_STATUS
	rcall get_sram
	andi r18, 0b01111111		
	rcall set_sram
	ret

;--- проверка часа
chk_alrm_hh:
	cp   r18, r20
	breq alrm_activate
	; -- сброс флага сработки будильника при несовпадении
	ldi  r16, ALRM_STATUS
	rcall get_sram
	andi r18, 0b01111111
	rcall set_sram
	ret

;--- будильник сработал
alrm_activate:
	ldi  r16, ALRM_STATUS
	rcall get_sram
	mov  r19, r18
	andi r19, 0b10000000		; будильник уже сработал?
	breq set_alrm_flag		; нет - активируем его
	ret

set_alrm_flag:
	ori  r18, 0b10000000		; иначе уст. флага сработки будильника
	rcall set_sram
	mov  r16, r18
	andi r16, 0b01111111
	ldi  r17, 60			; длительность звучания будильника из минут
	rcall mul_8x8			; переводим в секунды,
	ldi  r16, ALRM_CNTR		; и столько времени и будет звучать будильник
	rcall set_sram			; сохраняем это значение счетчика
	ret
;-------------------------------------------------------------------------
; программная коррекция хода часов, алгоритм такой
; раз в час, к значению r4:TCNT2 добавляем/отнимаем
; по 1 сотой секунды * на значение в r11, что в итоге
; дает нужную суточную точность хода часов.
; Можно скорректировать погрешность кварца где-то до 10
; секунд в сутки, но это - уже очень плохие кварцы. Обычно,
; значения погрешности часовых кварцев 2-5 сек/сутки,
; поэтому пределов коррекции +50...-50 вполне достаточно.
;-------------------------------------------------------------------------
correction_proc:
	mov  r16, r6            ; главный счетчик минут берем
	andi r16, 0b10000000    ; флаг коррекции раз в 30 минут
	brne cor_on		; взведен выполняем процедуру
	ret			

cor_on:
	ldi r16, CORRECTION	; значение коррекции берем
	rcall get_sram
	cpi r17, 0              ; если не задано
	breq exit_corr          ; выходим
	cpi r17, 50		; коррекция в плюс или в минус?
	brlo crr_plus
	breq crr_plus	

	mov  r16, r4
	andi r16, 0b01111111
	cpi  r16, 64		; ждем, пока значение счетчика TCNT2:r4 не 
	brsh set_corr_minus     ; станет больше 16384 чтоб избежать
	ret			; возможного переполнения при вычитании

; коррекция в минус
set_corr_minus:
	ldi r16, 101
	sub r16, r17		; значение корр без знака будет теперь в r16
	ldi r17, tim_500	; * на число тиков таймера для 1/500 секунды
	rcall mul_8x8
	add r17, r17		; и результат *2
	adc r18, r18
	in  r16, TCNT2		
	mov r19, r4             
	andi r19, 0b01111111
	sub r16, r17		; вычитаем из него значение
	sbc r19, r18            ;       коррекции
	mov r4,  r19		; и записываем
	out TCNT2, r16		; 	в счет. регистр новые данные
	rjmp exit_corr

; коррекция в плюс
crr_plus:
	mov  r16, r4
	andi r16, 0b01111111
	cpi  r16, 64		; ждем, пока значение счетчика TCNT2:r4
	brlo set_corr_plus      ; будет меньше 16384 чтоб избежать 
	ret			; возможного переполнения при сложении

set_corr_plus:
	ldi r16, tim_500	; интервал для 1/500 секунды
	rcall mul_8x8		; умножаем на значение коррекции
	add r17, r17		; и результат умножаем еще на 2
	adc r18, r18
	in r16, TCNT2		; тек. значение слова 
	mov  r19, r4
	andi r19, 0b01111111
	add  r16, r17		; добавляем к нему значение
	adc  r19, r18           ;       коррекции
	mov  r4,  r19		; и записываем
	out TCNT2, r16		; 	в счет. регистр новые данные

exit_corr:
	ldi  r16, 0b01111111	; старший бит выделяем,
	and  r6, r16		; 	и сбрасываем флаг в r6
	ret
;------------------------------------------------------------------------
; воспроизведение выбранной мелодии при сработке будильника
; или таймера, пока счетчик секунд в ALRM_CNTR не обнулится
play_alarm:
	ldi  r16, ALRM_CNTR
	rcall get_sram
	clr   r19
	cp    r17, r19			; счетчик уже обнулен?
	cpc   r18, r19                  ; да - сразу на выход
	brne  play_alrm_next
	ret

;--- в счетчике не нуль, проигрываем мелодию пока не обнулится
play_alrm_next:
	subi  r17, 1
	sbci  r18, 0
	breq  play_alrm_done		; воспроизводим пока счетчик не обнулится
	rcall set_sram

	ldi   r16, PLAY_STATUS
	rcall get_sram
	cpi   r17, 0			; мелодия проиграна или не начиналась?
	breq  repeat_play		; да - запускаем ее по новой
	ret				; иначе ждем пока вся мелодия проиграется

;--- запуск/повтор воспроизведения мелодии
repeat_play:
	ldi   r16, ALRM_STATUS		; получаем мелодию
	rcall get_sram			
	rcall reset_player              ; запуск плэйера
	ret

;--- конец воспроизведения звука по истечению времени
play_alrm_done:
	rcall set_sram			; обнуляем счетчик,
	clr   r17			; прерываем мелодию,
	rcall reset_player              ; ибо нефик пиликать
	ret
;------------------------------------------------------------------------
; процедура выполняет автоматическое переключение между 
; режимами вывода в r16 должен быть текущий режим вывода
display_switch:
	clT
	cpi  r16, 1
	breq clock_1_active
	cpi r16, 2
	breq clock_2_active
	cpi r16, 3
	breq data_1_active
	cpi r16, 4
	breq data_2_active
	cpi r16, 5
	breq temp_5_active
	cpi r16, 6
	breq temp_6_active
	cpi r16, 7
	breq screen_no_change
	cpi r16, 8
	breq screen_no_change

	cpi r16, 22
	breq setup_long_active
	cpi r16, 26
	breq setup_long_active

	; ---
	; по умолчанию - активен режим других установок
	mov r17, r2
	cpi r17, 15
	breq select_clock_1_disp_short
	ret

screen_no_change:
	ret

;-- длительное ожидание выхода из setup
setup_long_active:
	mov r17, r2
	cpi r17, 99			; сколько секунд выводить экран
	breq select_clock_1_disp_short
	ret

;-- дата формат DD-MM
data_2_active:
	rcall get_display_clock_ts
	cpi r18, 0		
	brne data_2_active_def
	ldi r18, 3
data_2_active_def:
	cp  r18, r2			; сколько секунд выводить экран
	breq select_temp_6
	ret

;-- часы формат HH:MM
clock_2_active:
	rcall get_display_clock_ts
	cpi r17, 0			; 0 - вывод часов постоянный
	breq clock_2_active_only
	cp  r2, r17			; сколько секунд выводить экран
	breq select_data_2_disp
clock_2_active_only:
	ret

;-- часы формат HH:MM:SS
clock_1_active:
	rcall get_display_clock_ts
	cpi r17, 0			; 0 - вывод часов постоянный
	breq clock_1_active_only
	cp  r2, r17			; сколько секунд выводить экран
	breq select_data_1_disp
clock_1_active_only:
	ret

;-- дата формат DD-MM-YY
data_1_active:
	rcall get_display_clock_ts
	cpi r18, 0		
	brne data_1_active_def
	ldi r18, 3
data_1_active_def:
	cp  r18, r2			; сколько секунд выводить экран
	breq select_temp_5
	ret

select_clock_1_disp_short:
	rjmp select_clock_1_disp

;-- температура
temp_6_active:
	rcall get_display_clock_ts
	cpi r18, 0
	brne temp_6_active_def
	ldi r18, 3
temp_6_active_def:
	cp  r18, r2			; сколько секунд выводить экран
	breq select_clock_2_disp
	ret

;-- температура
temp_5_active:
	rcall get_display_clock_ts
	cpi r18, 0			; 0 - вывод часов постоянный
	brne temp_5_active_def
	ldi r18, 3
temp_5_active_def:
	cp  r18, r2			; сколько секунд выводить экран
	breq select_clock_1_disp
	ret

; ----------------------------------
; СМЕНА РЕЖИМОВ ПО ИСТЕЧЕНИЮ ВРЕМЕНИ
;

;--- температура С
select_temp_5:
	clr r2
	ldi r22, 5
	ori r22, 0b10000000
	clr r23
	seT
	ret

;--- температура С
select_temp_6:
	clr r2
	ldi r22, 6
	ori r22, 0b10000000
	clr r23
	seT
	ret

;--- вывод часов HH:MM:SS
select_clock_1_disp:
	clr r2
	ldi r22, 1
	ori r22, 0b10000000
	clr r23
	seT
	ret

;--- вывод часов HH:MM
select_clock_2_disp:
	clr r2
	ldi r22, 2
	ori r22, 0b10000000
	clr r23
	seT
	ret

;--- вывод даты DD-MM-YY
select_data_1_disp:
	clr r2
	ldi r22, 3
	ori r22, 128
	clr r23
	seT
	ret

;--- вывод даты DD-MM
select_data_2_disp:
	clr r2
	ldi r22, 4
	ori r22, 0b10000000
	clr r23
	seT
	ret

get_display_clock_ts:
	push r16
	ldi r16, SCREEN_SHUTTLE
	rcall get_sram
	pop r16
	ret
;------------------------------------------------------------------------
; управление логикой точек-разделителей
delimeters:
	; режимы вывода
	mov  r16, r22
	andi r16, 0b01111111
	cpi  r16, 1
	breq clock_mode
	cpi  r16, 2
	breq clock_mode
	cpi  r16, 3
	breq setup_mode
	cpi  r16, 4
	breq setup_mode
	cpi  r16, 5
	breq temp_mode
	cpi  r16, 6
	breq temp_mode
	cpi  r16, 7
	breq temp_mode_1
	cpi  r16, 8
	breq clock_mode

	; режимы установок
	cpi  r16, 20
	breq clock_mode
	cpi  r16, 21
	breq clock_mode
	cpi  r16, 22
	breq clock_mode
	cpi  r16, 23
	breq setup_mode
	cpi  r16, 24
	breq setup_mode
	cpi  r16, 25
	breq setup_mode
	cpi  r16, 28
	breq setup_mode
	cpi  r16, 29
	breq setup_mode
	cpi  r16, 30
	breq temp_mode_1
	cpi  r16, 31
	brsh setup_mode
	rjmp lamp_off


setup_mode:
	sbi  PORTC, 4		; плюс выключить
	sbi  PORTC, 3		; между ЧЧ и CC выключить
	sbi  PORTC, 1		; градус выключить
	sbi  PORTC, 2           ; в середине тоже выключить
	ret

temp_mode:
	sbi  PORTC, 3		; между ЧЧ и CC выключить
	sbi  PORTC, 2           ; в середине тоже выключить
	cbi  PORTC, 1		; градус включить
	ret

temp_mode_1:
	sbi  PORTC, 1		; градус выключить
	sbi  PORTC, 3		; между ЧЧ и CC выключить
	sbi  PORTC, 2           ; в середине тоже выключить
	ret

clock_mode:
	push r16
	ldi  r16, DELIM_STATUS
	rcall get_sram
	pop  r16
	mov  r18, r17
	andi r18, 0b01111111
	cpi  r18, 0		; всегда выключены
	breq lamp_off
	cpi  r18, 2		; всегда включены
	breq lamp_on
	cpi  r18, 3		; всегда включены, в такт секундам мигает точка в углу
	breq blink_point
	; иначе - мигание разделителей ':' в такт секундам
	mov  r19, r4
	andi r19, 0b01111111
	cpi  r19, 64
	brsh lamp_off

lamp_on:
	cpi  r16, 2
	breq lamp_short_on
	sbi  PORTC, 4		; плюс выключить
	sbi  PORTC, 2		; в середине
	cbi  PORTC, 1		; градус
	cbi  PORTC, 3		; между ЧЧ и СС
	ret

lamp_off:
	sbi  PORTC, 4		; плюс выключить
	sbi  PORTC, 3		; между ЧЧ и CC
	sbi  PORTC, 1		; градус
	sbi  PORTC, 2		; в середине
	ret

lamp_short_on:
	cbi  PORTC, 2		; в середине включить
	sbi  PORTC, 4		; плюс выключить
	sbi  PORTC, 3		; между ЧЧ и CC
	sbi  PORTC, 1		; градус
	ret

	; мигание точки в углу в такт секундам
blink_point:
	andi r17, 0b10000000
	mov  r19, r4
	andi r19, 0b01111111
	cpi  r19, 64
	brsh point_off
	cpi  r17, 0		; точка уже включена?
	brne lamp_point_on	; да - на выход
	push r16
	ldi  r16, delim_STATUS
	ldi  r17, 3
	ori  r17, 128
	rcall set_sram
	pop  r16
	ori  r22, 128		; команда обновить индикатор
	rjmp lamp_point_on

point_off:
	cpi  r17, 0		; точка уже выключена?
	breq lamp_point_on	; да - на выход
	push r16
	ldi  r16, delim_STATUS
	ldi  r17, 3
	rcall set_sram
	pop  r16
	ori  r22, 128		; команда обновить индикатор
	rjmp lamp_point_on

lamp_point_on:
	cpi  r16, 8
	breq lamp_off
	rjmp lamp_on

;------------------------------------------------------------------------
; ШИМ регулировка яркости
;
anode_manage:
	inc  r12		; счетчик ШИМ регулировки яркости
	cp   r12, r11           ; сравниваем со значением заданным пользователем
	brsh anode_off
	cbi  PORTB, OE
	ret
		
anode_off:
	sbi  PORTB, OE
	ret
;------------------------------------------------------------------------
; процедура задержек на величины до 100 мксек. Используется в протоколе 1-wire
; r16 - число задержек по ~0.75 мксек (при 8 мГц)
delay:	nop
	nop
	nop
	nop
	nop
	dec r16
	brne delay
      	ret
;------------------------------------------------------------------------
;           Набор подпрограмм для работы с протколом 1-Wire 
;                  и датчиком температуры Dallas-18B20
;------------------------------------------------------------------------
; инициализация 1-Wire протокола
dallas_init:
	ldi  r16, dallas_status
	mov  r19, r18
	rcall get_sram
	cpi r17, 0
	brne dallas_init_cmd
	ret

dallas_init_cmd:
	cpi r17, 1
	breq reset_sig
	cpi r17, 2
	breq presense_wait
	cpi r17, 3
	breq presense_delay
	ret

;-- ожидание окончания сигнала Responce
presense_delay:
	sbic DALLAS_PORT_PIN, DALLAS_PORT_LINE
	rjmp presense_done
	ldi  r16, dallas_counter
	rcall get_sram
	inc  r17
	rcall set_sram
	cpi  r17, 99
	brsh presense_fail
	ret

;-- сигнал presense окончен
presense_done:
	ldi  r16, dallas_status
	ldi  r17, 128				; инициализация выполнена
	mov  r18, r19
	rcall set_sram

	ldi  r16, dallas_counter
	clr  r17
	clr  r18
	rcall set_sram
	ret

;-- ожидание сигнала presense после сброса
presense_wait:
	sbic DALLAS_PORT_PIN, DALLAS_PORT_LINE
	rjmp wait_probe
	ldi  r16, dallas_status
	ldi  r17, 3
	mov  r18, r19
	rcall set_sram
	ret

;-- цикл ожидания presense
wait_probe:
	ldi  r16, dallas_counter
	rcall get_sram
	inc  r17
	rcall set_sram
	cpi  r17, 99
	brsh presense_fail
	ret

;-- ошибка получения сигнала presense
presense_fail:
	ldi  r16, dallas_status
	ldi  r17, 255				; ошибка инициализации устройства
	mov  r18, r19
	rcall set_sram
	ret

;-- окончание выдачи сигнала Reset
reset_stop:
	rcall set_sram
	ldi  r16, DALLAS_PORT_line_Z
	out  DALLAS_PORT, r16
	ldi  r16, dallas_status
	ldi  r17, 2
	mov  r18, r19	
	rcall set_sram
	ret

;--- выдача и передача сигнала Reset
reset_sig:
	ldi r17, DALLAS_PORT_line_0
	out DALLAS_PORT, r17
	ldi  r16, dallas_counter
	rcall get_sram
	dec  r17
	breq reset_stop
	rcall set_sram
	ret
;------------------------------------------------------------------------
; побитовое чтение 1-Wire протокола
; В переменную dallas_counter пишем сколько бит надо прочитать (16 - значит
; надо прочитать 16 бит). После чтения, результат помещается в переменную 
; dallas_data, а переменная dallas_counter обнуляется.
dallas_read:
	mov  r19, r18
	ldi  r16, dallas_counter	; сколько битов 
	rcall get_sram                  ; будем читать
	cpi  r17, 0			; читаем пока счетчик не обнулится
	brne dallas_read_continue
	ldi  r16, dallas_status
	ldi  r17, 128			; конец
	mov  r18, r19
	rcall set_sram                  ; операции чтения
	ret

dallas_read_continue:
	ldi  r16, dallas_data
	rcall get_sram
	lsr  r18
	ror  r17
	ldi  r16, DALLAS_PORT_line_0    ; начало тайм-слота проваливаем
	out  DALLAS_PORT, r16		; шину
	ldi  r16, dallas_DELAY		; ждем разряда емкости
	rcall delay
	ldi  r16, DALLAS_PORT_line_Z
	out  DALLAS_PORT, r16			; отпускаем шину
	ldi  r16, dallas_DELAY		; ждем установления SLAVом
	rcall delay                     ; бита на шине
	sbic DALLAS_PORT_PIN, DALLAS_PORT_LINE
	ori  r18, 0b10000000
	ldi  r16, dallas_data		; сохраняем результат
	rcall set_sram
	ldi  r16, dallas_counter
	rcall get_sram
	dec  r17
	rcall set_sram
	ret
;------------------------------------------------------------------------
; побитовый вывод 1Wire проткола
; в переменную dallas_counter пишем сколько бит надо вывести (8 - значит
; надо вывести 8 бит). После записи,  переменная dallas_counter обнуляется.
dallas_write:
	mov  r19, r18
	ldi  r16, dallas_counter	; сколько битов 
	rcall get_sram                  ; будем писать
	cpi  r17, 0			; пишем пока счетчик не обнулится
	brne dallas_write_continue
	ldi  r16, dallas_status
	ldi  r17, 128			; конец
	mov  r18, r19                   ; операции записи
	rcall set_sram                  
	ldi  r16, DALLAS_PORT_line_Z	; отпускаем шину
	out  DALLAS_PORT, r16
	ret

dallas_write_continue:
	ldi  r16, DALLAS_PORT_line_Z	; отпускаем шину
	out  DALLAS_PORT, r16
	ldi  r16, dallas_DELAY		; ждем восстановления шины
	rcall delay
	ldi  r16,  DALLAS_PORT_line_0
	out  DALLAS_PORT, r16		; начало тайм-слота опускаем шину
	ldi  r16, dallas_DELAY
	rcall delay
	ldi  r16, dallas_data
	rcall get_sram
	ror  r17                        ; младший бит пишем в CF
	brCc master_say_0
	ldi  r16, DALLAS_PORT_line_Z	; устанавливаем "1" на шине
	out  DALLAS_PORT, r16

master_say_0:
	ldi  r16, dallas_data
	rcall set_sram
	ldi  r16, dallas_counter
	rcall get_sram
	dec  r17
	rcall set_sram
	ret
;------------------------------------------------------------------------
;  *** Основная процедура работы с датчиком DS18B20 ***
;------------------------------------------------------------------------
dallas:	ldi   r16, dallas_status
	rcall get_sram
	cpi   r18, 0			; сценарий активен?
	brne  scenic_active
	ret

scenic_active:
	cpi   r18, 255			; возникли ошибки?
	brne  scenic_no_error
	ret

scenic_no_error:
	cpi   r18, 128			; сценарий окончен?
	brne  scenic_no_end
	clr   r17
	clr   r18
	rcall set_sram
	ret

scenic_no_end:
	cpi   r17, 0			; низкоуровневой операции не было?
	breq  scenic_next		
	cpi   r17, 128			; низкоуровневая операция завершена?
	breq  scenic_next
	cpi   r17, 255			; низкоуровневая операция завершена с ошибкой?
	breq  scenic_error
	cpi   r17, 5			; запрос на чтение?
	breq  read_1wire
	cpi   r17, 6			; запрос на запись?
	breq  write_1wire
	rcall dallas_init		; иначе инициализация
	ret

read_1wire:
	rcall dallas_read
	ret

write_1wire:
	rcall dallas_write
	ret

	;--- ошибка сценария
scenic_error:
	ldi   r18, 255			; при ошибках низкого уровня
	rcall set_sram		        ; сразу завершаем и сценарий
	ldi   r16, TEMP
	ldi   r17, 255
	clr   r18
	rcall set_sram
	ret

	;--- следующий пункт сценария	
scenic_next:
	mov   r19, r18
	andi  r19, 0b01000000		; бит 6 включает паузу в сценарии
	breq  scenic_continue           ; сброшен? продолжаем сценарий
	ldi   r16, DALLAS_PAUSE		; величина паузы в тиках таймера
	rcall get_sram	
	subi  r17, 1
	sbci  r18, 0
	brcS  scenic_pause_done		; ждем пока счетчик не обнулится
	rcall set_sram
	ret

	;-- окончание паузы
scenic_pause_done:
	ldi   r16, dallas_status
	rcall get_sram
	andi  r18, 0b10111111
	rcall set_sram

	;--- ход сценария	
scenic_continue:
	cpi   r18, 1
	breq  scenic_1st		; Reset
	cpi   r18, 2
	breq  scenic_2st		; отправка команды $CC
	cpi   r18, 3
	breq  scenic_3st		; отправка команды $44
	cpi   r18, 4
	breq  scenic_1st		; Reset
	cpi   r18, 5
	breq  scenic_2st		; снова команда $CC
	cpi   r18, 6
	breq  scenic_6st		; команда $BE
	cpi   r18, 7
	breq  scenic_7st		; чтение данных

	;--- конец сценария отмечаем
	ldi   r18, 128
	rcall set_sram

	;--- преобразование температуры в град C
	rcall converse_T
	ret

	;-- 1 пункт сценария
scenic_1st:
	ldi   r17, 1
	inc   r18
	rcall set_sram
	ldi   r17, 16
	clr   r18
	ldi   r16, dallas_counter
	rcall set_sram
	rcall setup_pause_05
	ret

	;-- следующий пункт сценария 
scenic_2st:
	ldi   r17, 6
	inc   r18
	rcall set_sram
	ldi   r17, $CC
	rcall write_byte_dallas
	rcall setup_pause_05
	ret

	;-- и тд
scenic_3st:
	ldi   r17, 6
	inc   r18
	rcall set_sram
	ldi   r17, $44
	rcall write_byte_dallas
	rcall setup_pause_1
	ret

scenic_6st:
	ldi   r17, 6
	inc   r18
	rcall set_sram
	ldi   r17, $BE
	rcall write_byte_dallas
	rcall setup_pause_05
	ret

scenic_7st:
	ldi   r17, 5
	inc   r18
	rcall set_sram
	ldi   r16, dallas_data
	clr   r17
	clr   r18
	rcall set_sram
	ldi   r16, dallas_counter
	ldi   r17, 16
	clr   r18
	rcall set_sram
	ret

	; -- выдача 1 байта данных в устройство по 1-Wire
write_byte_dallas:
	ldi   r16, dallas_data
	clr   r18
	rcall set_sram
	ldi   r16, dallas_counter
	ldi   r17, 8
	clr   r18
	rcall set_sram
	ret

	;--- короткая пауза
setup_pause_05:	
	ldi   r16, DALLAS_PAUSE
	ldi   r17, 15			; число тиков таймера
	clr   r18
	rcall set_sram
	ldi   r16, DALLAS_STATUS
	rcall get_sram
	ori   r18, 0b01000000
	rcall set_sram
	ret

	;--- длинная пауза
setup_pause_1:
	ldi   r16, DALLAS_PAUSE
	ldi   r17, low(16384)
	ldi   r18, high(16384)
	rcall set_sram
	ldi   r16, DALLAS_STATUS
	rcall get_sram
	ori   r18, 0b01000000
	rcall set_sram
	ret
;------------------------------------------------------------------------
; Преобразование значения температуры с датчика в градусы С
converse_T:
	clr   r0
	ldi   r16, dallas_data
	rcall get_sram
	mov   r16, r18
	andi  r16, 0b10000000
	breq  temp_plus1 

	; --- знак "-"
	ldi   r19, 255
	ldi   r20, 255
	sub   r19, r17
	sbc   r20, r18
	mov   r17, r19
	mov   r18, r20
	ldi   r19, 1
	clr   r20
	add   r17, r19
	adc   r18, r20
	inc   r0

	; --- перевод в градусы C из r17:r18
temp_plus1:
	ldi   r19, 16				; делим на 16
	clr   r20				; и получаем целые градусы
	rcall div16x16
	push  r17				; целые градусы в r17
	; --- остаток по 0.06 градуса в r19
	mov   r16, r19
	lsl   r19		
	lsl   r19  
	add   r19, r16		
	add   r19, r16
	mov   r16, r19
	ldi   r17, 10
	rcall div8u
	mov   r18, r16
	pop   r17
	clr   r16	
	cp    r0, r16
	breq  temp_plus2
	ori   r17, 0b10000000			; старший бит "1" - значит T минус
temp_plus2:
	ldi   r16, TEMP
	rcall set_sram
	ret
;------------------------------------------------------------------------
; выключает проигрыватель мелодии при r17=0
; или запускает его, в r17 будет номер мелодии
reset_player:
	ldi    r16, PLAY_STATUS
	clr    r18
	rcall  set_sram
	clr    r17
	ldi    r16, PLAY_COUNTER
	rcall  set_sram
	ldi    r16, PLAY_TEMP
	rcall  set_sram
	ldi    r19, 0b00001000		; отключение таймера
	out    TCCR1B, r19
	ldi    r19, 1<<OCIE2		; запрет прерывания
	out    TIMSK, r19               ; выключкение звука
	ret
;------------------------------------------------------------------------
; *** Набор подпрограмм для проигрывания простых мелодий ***
;------------------------------------------------------------------------
player:	mov    r16, r4		        ; смена нот будет по прерываниям таймера
	andi   r16, 128
	brne   continue_play
	ret

	;--- начало/продолжение воспроизыедения
continue_play:
	ldi    r16, PLAY_STATUS
	rcall  get_sram
	mov    r19, r17
	andi   r19, 0b10000000
	brne   play_next
	cpi    r17, 0
	brne   play_init
	ret

	;--- начало воспроизведения
play_init:
	mov    r19, r17
	andi   r19, 0b01111111
	cpi    r19, 1
	breq   mel1
	cpi    r19, 2
	breq   mel2
	cpi    r19, 3
	breq   mel3
	cpi    r19, 4
	breq   mel4
	cpi    r19, 5
	breq   mel5
	cpi    r19, 6
	breq   mel6
	cpi    r19, 7
	breq   mel7	
	cpi    r19, 8
	breq   mel8
	cpi    r19, 9
	breq   mel9
	ret

	;--- мелодия 1
mel1:   ldi    ZH, high(MELODY1*2)
	ldi    ZL, low(MELODY1*2)
	rjmp   play_melody_start

	;--- мелодия 2
mel2:   ldi    ZH, high(MELODY2*2)
	ldi    ZL, low(MELODY2*2)
	rjmp   play_melody_start

	;--- мелодия 3
mel3:   ldi    ZH, high(MELODY3*2)
	ldi    ZL, low(MELODY3*2)
	rjmp   play_melody_start

	;--- мелодия 4
mel4:   ldi    ZH, high(MELODY4*2)
	ldi    ZL, low(MELODY4*2)
	rjmp   play_melody_start

	;--- мелодия 5
mel5:   ldi    ZH, high(MELODY5*2)
	ldi    ZL, low(MELODY5*2)
	rjmp   play_melody_start

	;--- мелодия 6
mel6:   ldi    ZH, high(MELODY6*2)
	ldi    ZL, low(MELODY6*2)
	rjmp   play_melody_start

	;--- мелодия 7
mel7:   ldi    ZH, high(MELODY7*2)
	ldi    ZL, low(MELODY7*2)
	rjmp   play_melody_start

	;--- мелодия 8
mel8:   ldi    ZH, high(MELODY8*2)
	ldi    ZL, low(MELODY8*2)
	rjmp   play_melody_start

	;--- мелодия 9
mel9:   ldi    ZH, high(MELODY9*2)
	ldi    ZL, low(MELODY9*2)


	;--- начало воспроизведения
play_melody_start:
	ori    r17, 128
	clr    r18
	rcall  set_sram

	ldi    r16, PLAY_COUNTER
	mov    r17, ZL
	mov    r18, ZH
	rcall  set_sram
	ret

	;--- продолжение воспроизведения
play_next:
	cpi    r18, 0			; звучание ноты закончено?
	breq   mel_delay_done           ; да - берем слудующую ноту
	dec    r18
	rcall  set_sram
	ret

	;--- мелодия проиграна
play_stop:
	clr    r17
	rcall  reset_player
	ret

	;--- установка общего темпа воспроизведения
setup_play_temp:
	rcall  read_play_next_byte	; следующий байт величина темпа
	mov    r17, r16
	ldi    r16, PLAY_TEMP
	rcall  set_sram

	;--- следующая воспроизводимая нота
mel_delay_done:
	rcall  read_play_next_byte
	cpi    r16, 255			; конец мелодии?
	breq   play_stop
	cpi    r16, 254			; пустая команда?
	breq   mel_delay_done
	cpi    r16, 232			; темп мелодии?
	breq   setup_play_temp
	ldi    r17, 6			; число из массива делим на 6
	rcall  div8u
	; частное r16 -> номер ноты 0-35
	; остаток r15 -> длительность 0-5
	cpi    r16, 36           	; только пауза воспроизведения?
	breq   play_delay_only

	; --- получение частоты из массива нот для данной ноты
	ldi    ZH, high(NOTY*2)
	ldi    ZL, low(NOTY*2)
	clr    r19
	lsl    r16			; по 2 байта на ноту
	add    ZL,  r16
	adc    ZH,  r19
	lpm				; младшая часть делителя
	mov    r16, r0
	ldi    r20, 1
	add    ZL,  r20
	adc    ZH,  r19
	lpm				; старшая часть делителя

	ldi    r17, 0b00001010			; делитель на 8 включение таймера
	ldi    r19, (1<<OCIE1A)|(1<<OCIE2)	; включаем прерывания
	out    OCR1AH, r0
	out    OCR1AL, r16
	out    TCNT1H, r0
	out    TCNT1L, r16
	out    TCCR1B, r17
	out    TIMSK, r19			; сразу и будет звук )
	rjmp   setup_play_delay

	;--- только пауза звук - выкл
play_delay_only:
	ldi    r17, 0b00001000			; отключение таймера 1
	out    TCCR1B, r17

	;--- установка длительности
setup_play_delay:
	rcall  converse_delay
	ldi    r16, PLAY_STATUS			; установка длительности
	rcall  get_sram				; звучания или паузы
	mov    r18, r19
	rcall  set_sram
	ret
;------------------------------------------------------------------------
; считывает байт из массива с мелодией и сдвигает указатель на след ноту
read_play_next_byte:
	ldi    r16, PLAY_COUNTER
	rcall  get_sram
	mov    ZL, r17
	mov    ZH, r18
	lpm			; упакованное значение следующей ноты в массиве
	ldi    r19, 1
	add    r17, r19
	clr    r19
	adc    r18, r19
	rcall  set_sram
	mov    r16, r0
	ret
;------------------------------------------------------------------------
; функция преобразования длительности/паузы
; из массива в число  прерываний  таймера
converse_delay:
	ldi    r16, PLAY_TEMP
	rcall  get_sram
	cpi    r17, 0
	brne   play_temp_setting
	ldi    r17, PLAY_TEMP_DEF

play_temp_setting:
	mov    r19, r15
	inc    r19
	cpi    r19, 1		; 1/1
	breq   dly_1
	cpi    r19, 2           ; 1/2
	breq   dly_2
	cpi    r19, 3           ; 1/4
	breq   dly_4
	cpi    r19, 4		; 1/8
	breq   dly_8
	cpi    r19, 5		; 1/16
	breq   dly_16
	cpi    r19, 6		; 1/32
	breq   dly_32
	; default 1/16
	ldi    r19, 16
	ret

dly_1:	lsl    r17
	lsl    r17
	lsl    r17
	lsl    r17
	mov    r19, r17
	ret

dly_2:	lsl    r17
	lsl    r17
	lsl    r17
	mov    r19, r17
	ret

dly_4:	lsl    r17
	lsl    r17
	mov    r19, r17
	ret

dly_8: 	lsl    r17
	mov    r19, r17
	ret

dly_16:	mov    r19, r17
	ret

dly_32:	mov    r19, r17
	subi   r19, 2
	ret
;------------------------------------------------------------------------
RESET:  ldi r16, high(RAMEND)
	out SPH, r16
	ldi r16, low(RAMEND)
	out SPL, r16
	
	rcall clear_sram

	ldi  r16, BRIGHT
	ldi  r17, screen_bright_user
	clr  r18
	rcall set_sram

	ldi  r16, DM
	ldi  r17, 01
	ldi  r18, 01
	rcall set_sram

	ldi  r16, YY
	ldi  r17, 16
	ldi  r18, 20
	rcall set_sram

	ldi  r16, DELIM_STATUS
	ldi  r17, 1
	rcall set_sram

	ldi  r16, SCREEN_SHUTTLE
	ldi  r17, 40		; время выводить 20 сек, 0 выводить непрерывно,
	ldi  r18, 3		; и по 3 сек выводить дату и температуру
	rcall set_sram


	ldi  r16, BEEP_STATUS
	ldi  r17, 1		; часы бьют каждый час
	clr  r18
	rcall set_sram

	ldi  r16, CORRECTION
	ldi  r17, 20		; величина программной коррекции хода часов
	clr  r18
	rcall set_sram

	                        ; весь порт D работает на вход
	clr  r16	        ; линия 4 порта D работает в 2 состояниях:
	out PORTD, r16          ; Z и 0. Так сделано потому что по этой
				; линии работает  датчик температору 1-Wire
				; Dallas 18B20.

	ldi r16, DALLAS_PORT_line_Z
	out DALLAS_PORT, r16
			


	ldi r16, 255		; весь порт B
	out DDRB, r16		; работает на выход
	out DDRC, r16		; и порт C тоже
	out PORTC, r16
	out PORTB, r16


	clr   r2                ; счетчик сек автомат смены режимов вывода
	clr   r3		; счетчик задержек при мигании
	clr   r4		; счетчик числа прерываний таймера
	clr   r5                ; ЧРВ секунды
	clr   r6		; ЧРВ минуты
	clr   r7		; ЧРВ часы

;	ldi  r16, 50
;	mov  r5, r16
;	ldi  r16, 59
;	mov  r6, r16


	clr   r10		; сохраненное значение таймера
	ldi   r16, screen_bright
	mov   r11, r16		; яркость цифр по умолчанию полная
	clr   r12		; счетчик дл. включения анодов (ШИМ яркости)

	; ---
	; регистры управления выводом

	clr r22			; режимы вывода:
				; 0 -  пустой экран очистка индикатора
				; 1 -  время формат HH:MM:SS
				; 2 -  время формат HH:MM
				; 3 -  полный формат даты DD-MM-YY
				; 4 -  краткий формат даты DD-MM
				; 5 -  температура (из длинного формата)
				; 6 -  температура (из короткого формата)
				; 7 -  пустой экран (все лампы откл)

				; установки:
				; 20 - установка часа
				; 21 - устанока минут
				; 22 - устанока секунд
				; 23 - устанока дня
				; 24 - установка месяца
				; 25 - установка года
				; 26 - выбор мелодии будильника
				; 27 - установка длительности звучаения мелодии
				; 28 - установка часа будильника
				; 29 - установка минут будильника
				; 30 - установка коррекции хода часов
				; 31 - установка логики разделителей
				; 32 - длительность цикла вывода времени, сек или 0 непрерывно
				; 33 - длительность цикла вывода даты и темп, сек
				; последние 2 бита:
				;   6 -/-
				;   7 бит запрос вывода
				; 34 - управление Beep (1- часы отбивают каждый час)


	clr r23			; регистр опций вывода (мигания)
				; при мигании - номер бита в регистре соответствует
				; знаку на индикаторе которые (которые) будут мигать

				; таким образом, вызывая процедуру display через
				; какое-то время соответсвующее интервалу мигания
				; можно выводить одни и теже данные но при этом,
				; отдельные разряды индикатора будут мигать.

				; когда нужно просто вывести данные без мигания
				; регистр должен быть обнулен!

	clr r24			; регистр управления клавиатурой
				; биты 0-3 код нажатой клавиши (до 16 значений)
				; бит 4 - старт задержки для подавления дребезга
				; бит 5 - задержка окончена
				; бит 6 - старт задержки перед автоповтором
				; бит 7 - код клавиши готов


	ldi r22, DEFAULT_MODE	; режим по умолчанию - часы полный формат
	ori r22, 128            ; команда вывести

	cli
	ldi r16, (1<<PSR10)
	out SFIOR, r16
	ldi r16, (1<<AS2)
	out ASSR, r16
	clr r16
	out TCNT2, r16
	out OCR2, r16
	ldi r16, (1<<CS20)	; подделитель отключен, работаем от CK кварца
	out TCCR2, r16

wait_t:	nop
	nop
	nop
	in r16, ASSR
	cpi r16, 0b00001000
	brne wait_t		; ждем готовности битов в регистре ASSR

	clr r16
	out TIFR, r16

	ldi r16, (1<<OCIE2)	; активируем прерывание по переполнению
	out TIMSK, r16
	sei

;	cbi  PORTC, 4		; разделители ЧЧ:ММ:СС 
;	cbi  PORTC, 1		; знак градус 
;	cbi  PORTC, 3		; знак +
;       cbi  PORTC, 2           ; разделитель в середине


;--- ОСНОВНОЙ ЦИКЛ
MAIN:   IN     r16, TCNT2
	cp     r10, r16
	brne   task_switcher
	rjmp   end_task_switcher

;--- ДИСПЕТЧЕР ЗАДАЧ
task_switcher:
	mov   r10, r16
	rcall anode_manage
	rcall dallas
	rcall correction_proc
	mov   r16, r10
	cpi   r16, 100
	brsh  end_task_switcher
	cpi   r16, 80
	brsh  task_scheduler
	cpi   r16, 40
	brsh  task_blink
	cpi   r16, 20
	brsh  task_inkey
	cpi   r16, 0
	brsh  task_display
	rjmp  end_task_switcher

task_inkey:
	andi  r16, 0b00000001
	breq  end_task_switcher
	rcall inkey
	rcall interface
	rjmp end_task_switcher

task_scheduler:
	rcall scheduler
	rjmp end_task_switcher	

task_blink:
	rcall display_blink
	rcall player
	rcall reset_timer_flag
	rjmp end_task_switcher

task_display:
	rcall display
	rcall delimeters

end_task_switcher:
	rjmp MAIN


