.nolist
.include "m8def.inc"
.list


.equ READ_KEY = 0x42
.equ AUTOMATIC_ADDRESS = 0x40
.equ FIX_ADDRESS = 0x44
.equ TEST_MODE = 0x48 



.equ VAL_CNT = 20
.equ FOSC = 8000000
.equ BAUD = 9600
.equ MYUBRR = FOSC/16/BAUD-1

.equ tm_clk       = PC3 
.equ tm_dio       = PC2

.def cnt = r21

.dseg
.cseg
.org 0
    rjmp reset
.org OVF0addr
    rjmp t0_ovf
.org INT_VECTORS_SIZE

;--------------------------------------------------------
reset:
    cli
    ldi r16,low(RAMEND)
    out SPL,r16
    ldi r16,High(RAMEND)
    out SPH,r16
    rcall delau_1ms
    
    rcall USART_Init

    ldi r16, (1<<TOIE0)
    out TIMSK, r16
    ldi r16, (1<<CS02)      ; clk/256
    out TCCR0, r16

    ldi cnt, VAL_CNT
    clt
    sei

    ldi r16, 'O'
    rcall USART_Transmit
    ldi r16, 'k'
    rcall USART_Transmit
    ldi r16, '\r'
    rcall USART_Transmit
    ldi r16, '\n'
    rcall USART_Transmit

loop:
    nop
    brtc loop
    clr r23
    
    ; Send memory write command. Automatic address adding
    rcall tm_start
    ldi r16, 0x40
    rcall tm_write_byte
    rcall tm_stop
    
    ; Set the initial address
    rcall tm_start
    ldi r16, 0xC0
    rcall tm_write_byte

    ; Transfer multiple words continuously
    ldi r19, 4
loop_dis:
    ldi r16, 0x4f
    rcall tm_write_byte
    dec r19
    brne loop_dis
    rcall tm_stop

    ; Send display control command
    rcall tm_start
    ldi r16, 0x8f
    rcall tm_write_byte
    rcall tm_stop

    rcall delau_10us

;---------------------------------------------------------------
    ;Send read key command
    ldi r23, 0x00
    rcall tm_start
    ldi r16, 0x42
    rcall tm_write_byte

    ; Read key command and store into the MCU register
    cli
    cbi DDRC, tm_dio        ; dio - input
    ldi r18, 8
loop_read:
    cbi DDRC, tm_clk        ; clk=1
    rcall delau_10us
    
    sbis PINC, tm_dio
    rjmp next_lsr
    ori r23, 0x01
next_lsr:
    lsl r23

    sbi DDRC, tm_clk        ; clk=0
    rcall delau_10us

    dec r18
    brne loop_read
    
    ; 9 - clock ACK
    cbi DDRC, tm_clk        ; clk=1
    rcall delau_10us
    sbi DDRC, tm_clk        ; clk=0
    rcall delau_10us
    cbi DDRC, tm_clk        ; clk=1
    rcall tm_stop

    cpi r23, 0x00
    breq zero
    mov r16, r23
    rjmp uart_t
zero:
    ldi r16, '0'
uart_t:    
    ori r16, 0x01
    rcall USART_Transmit
    sei
;---------------------------------------------------------------
    clt    
    rjmp loop


tm_start:
    cbi DDRC, tm_clk        ; clk=1
    cbi DDRC, tm_dio        ; dio=1
    rcall delau_5us
    sbi DDRC, tm_dio        ; dio=0
    rcall delau_5us
    ret
    
tm_stop:
    cbi DDRC, tm_clk        ; clk=1
    sbi DDRC, tm_dio        ; dio=0
    rcall delau_5us
    cbi DDRC, tm_dio        ; dio=1
    ret

; byte -> r16
; count -> r17
; ack -> r18
tm_write_byte:
    push r17
    in r17, SREG
    push r17
    ldi r17, 8
loop_write:
    sbi DDRC, tm_clk        ; clk=0
    lsr r16
    brcs set_1              ; Перейти если перенос установлен
    sbi DDRC, tm_dio        ; dio=0
    rjmp next_rol
set_1:
    cbi DDRC, tm_dio        ; dio=1    
next_rol:
    rcall delau_10us
    cbi DDRC, tm_clk        ; clk=1
    rcall delau_10us
    dec r17
    brne loop_write   	    
    
    ; wait ack
    cbi DDRC, tm_dio        ; dio - input
    sbi DDRC, tm_clk        ; clk=0
    rcall delau_10us
    cbi DDRC, tm_clk        ; clk=1
    
    ; read ack
    rcall delau_5us
    in r18, PINC
    rcall delau_5us
    
    sbi DDRC, tm_dio        ; dio - output
    sbi DDRC, tm_clk        ; clk=0
    
    rcall delau_10us
    
    andi r18, (1<<tm_dio)
    pop r17
    out SREG, r17
    pop r17
    ret

delau_10us:
; Assembly code auto-generated
; by utility from Bret Mulvey
; Delay 80 cycles
; 10us at 8.0 MHz
    push r18
    in r18, SREG
    push r18

    ldi  r18, 26
L1: dec  r18
    brne L1
    rjmp PC+1

    pop r18
    out SREG, r18
    pop r18
    ret

delau_1ms:
; Assembly code auto-generated
; by utility from Bret Mulvey
; Delay 8 000 cycles
; 1ms at 8.0 MHz
    push r18
    push r19
    in r18, SREG
    push r18

    ldi  r18, 11
    ldi  r19, 99
L2: dec  r19
    brne L2
    dec  r18
    brne L2

    pop r18
    out SREG, r18
    pop r19
    pop r18
    ret

delau_5us:
; Assembly code auto-generated
; by utility from Bret Mulvey
; Delay 40 cycles
; 5us at 8.0 MHz
    push r18
    in r18, SREG
    push r18

    ldi  r18, 13
L3: dec  r18
    brne L3
    nop

    pop r18
    out SREG, r18
    pop r18
    ret


delau_30us:
; Assembly code auto-generated
; by utility from Bret Mulvey
; Delay 240 cycles
; 30us at 8.0 MHz
    push r18
    in r18, SREG
    push r18

    ldi  r18, 80
L4: dec  r18
    brne L4

    pop r18
    out SREG, r18
    pop r18
    ret


delau_300ms:
; Assembly code auto-generated
; by utility from Bret Mulvey
; Delay 2 400 000 cycles
; 300ms at 8.0 MHz
    push r18
    push r19
    push r20
    in r18, SREG
    push r18

    ldi  r18, 13
    ldi  r19, 45
    ldi  r20, 216
L5: dec  r20
    brne L5
    dec  r19
    brne L5
    dec  r18
    brne L5
    rjmp PC+1

    pop r18
    out SREG, r18
    pop r20
    pop r19
    pop r18
    ret


t0_ovf:
    push r18
    dec cnt
    brne exit_t0_ovf
    set
    ldi cnt, VAL_CNT
exit_t0_ovf:
    pop r18
    reti


USART_Init:
    ; Set baud rate
    push r17
    push r16

    ldi r16, low(MYUBRR)
    ldi r17, high(MYUBRR)
    out UBRRH, r17
    out UBRRL, r16
    ; Enable receiver and transmitter
    ldi r16, (1<<RXEN)|(1<<TXEN)
    out UCSRB,r16
    ; Set frame format: 8data, 2stop bit
    ldi r16, (1<<URSEL)|(3<<UCSZ0)
    out UCSRC,r16

    pop r16
    pop r17
    ret

USART_Transmit:
    ; Wait for empty transmit buffer
    sbis UCSRA,UDRE
    rjmp USART_Transmit
    ; Put data (r16) into buffer, sends the data
    out UDR, r16
    ret
