;=======================================================
; Проект 25. Часы: минуты и секунды на прерывании T1 (CTC)
; ATmega8, 8 МГц. Сегменты PB0..PB6, разряды PD0/PD1
; Показываются секунды, минуты считаются в фоне
;=======================================================
.include "m8def.inc"
.def    temp  = r16
.def    tens  = r17
.def    ones  = r18
.def    secs  = r19
.def    mins  = r20
.def    tmp2  = r21
.def    isrsav= r22
.def    d1    = r23
.def    d2    = r24

.cseg
.org    0x0000
        rjmp    RESET
.org    OC1Aaddr                        ; вектор совпадения T1
        rjmp    TIMER1_CMP

SEGTAB: .db 0b00111111, 0b00000110, 0b01011011, 0b01001111, 0b01100110
        .db 0b01101101, 0b01111101, 0b00000111, 0b01111111, 0b01101111

RESET:
        ldi     temp, low(RAMEND)
        out     SPL, temp
        ldi     temp, high(RAMEND)
        out     SPH, temp
        ldi     temp, 0x7F
        out     DDRB, temp
        ldi     temp, 0x03
        out     DDRD, temp

        ; CTC: совпадение раз в секунду при 8 МГц и предделителе 1:256
        ldi     temp, high(31249)
        out     OCR1AH, temp
        ldi     temp, low(31249)
        out     OCR1AL, temp
        ldi     temp, (1<<WGM12)|(1<<CS12)  ; режим CTC, предделитель 1:256
        out     TCCR1B, temp
        ldi     temp, (1<<OCIE1A)           ; разрешаем прерывание
        out     TIMSK, temp
        clr     secs
        clr     mins
        sei

MAIN:
        mov     temp, secs
        rcall   SPLIT                   ; секунды -> разряды
        cbi     PORTD, PD1
        mov     temp, tens
        rcall   SEG
        out     PORTB, temp
        sbi     PORTD, PD0
        rcall   DELAY5MS
        cbi     PORTD, PD0
        mov     temp, ones
        rcall   SEG
        out     PORTB, temp
        sbi     PORTD, PD1
        rcall   DELAY5MS
        rjmp    MAIN

TIMER1_CMP:
        in      isrsav, SREG
        inc     secs
        cpi     secs, 60
        brne    T1_END
        clr     secs
        inc     mins
        cpi     mins, 60
        brne    T1_END
        clr     mins
T1_END:
        out     SREG, isrsav
        reti

;--- разложить temp на десятки и единицы ---
SPLIT:
        clr     tens
SP_LOOP:
        cpi     temp, 10
        brlo    SP_END
        subi    temp, 10
        inc     tens
        rjmp    SP_LOOP
SP_END:
        mov     ones, temp
        ret

SEG:
        ldi     ZL, low(SEGTAB<<1)
        ldi     ZH, high(SEGTAB<<1)
        add     ZL, temp
        clr     temp
        adc     ZH, temp
        lpm     temp, Z
        ret

DELAY5MS:
        ldi     d2, 52
F2:     ldi     d1, 255
F1:     dec     d1
        brne    F1
        dec     d2
        brne    F2
        ret
