; ***************************************************************************
; copyright   : (C) 2024 by Martin Preuss
; email       : martin@libchipcard.de
;
; ***************************************************************************
; * This file is part of the project "AqHome".                              *
; * Please see toplevel file COPYING of that project for license details.   *
; ***************************************************************************



; ---------------------------------------------------------------------------
; @macro m_uart_irq_handle_tick
;
; @clobbers any
;
; @param %0 COM_DATA_DDR
; @param %1 COM_DATA_INPUT
; @param %2 COM_DATA_OUTPUT
; @param %3 COM_DATA_PIN
; @param %4 COM_ATTN_DDR
; @param %5 COM_ATTN_INPUT
; @param %6 COM_ATTN_OUTPUT
; @param %7 COM_ATTN_PIN
; @param %8 uartIrqDataIface1

.macro m_uart_irq_handle_tick
  ldi yl, LOW(@8)
  ldi yh, HIGH(@8)
  ldi zl, LOW(_jumptable)
  ldi zh, HIGH(_jumptable)
  rjmp UART_Irq_HandleTick

_jumptable:
  rjmp _readDataBit  ; read DATA BIT  (r16=bit)
  rjmp _readAttnBit  ; read ATTN BIT  (r16=bit)
  rjmp _writeDataBit ; write DATA BIT (r16=bit)
  rjmp _writeAttnBit ; write ATTN BIT (r16=bit)

_readDataBit:
  clr r16
  sbic @1, @3
    inc r16 
  ret

_readAttnBit:
  clr r16
  sbic @5, @7
    inc r16 
  ret

_writeDataBit:
  tst r16
  brne _writeDataBit1
  sbi @0, @3   ; set data line to output
  cbi @2, @3   ; set line LOW
  ret
_writeDataBit1:
  cbi @0, @3   ; set data line to input (external pullup R makes it HIGH)
  cbi @2, @3   ; disable internal pullup
  ret
  
_writeAttnBit:
  tst r16
  brne _writeAttnBit1
  sbi @4, @7   ; set ATTN line to output (makes it LOW)
  cbi @2, @7   ; set line LOW
  ret
_writeAttnBit1:
  cbi @4, @7   ; set ATTN line to output (external pullup R makes it HIGH)
  cbi @2, @7   ; disable internal pullup
  ret
.endmacro
; @end



.dseg

uartIrqBase:         .byte 4
;uartIrqState:        .byte 1
;uartIrqCounter:      .byte 1
;uartIrqStateCounter: .byte 1
;uartIrqCurrentByte:  .byte 1



.cseg

UART_IRQ_BEGIN:



; ---------------------------------------------------------------------------
; @routine UART_Irq_InitIface @global
;
; @param Y pointer to interface data in SRAM (see @ref UART_IRQ_IFACE_OFFS_STATE)
; @clobbers any

UART_Irq_InitIface:
  ; preset SRAM data area
  mov xh, yh
  mov xl, yl
  clr r16
  ldi r17, UART_IRQ_IFACE_SIZE
  rcall Utils_FillSram
  ret
; @end



; ---------------------------------------------------------------------------
; @routine UART_Irq_HandleTick @global
;
; @param Y pointer to interface data in SRAM (see @ref UART_IRQ_IFACE_OFFS_STATE)
; @param Z pointer to IFACE jump table for the given interface
; @clobbers r16, r17, X

UART_Irq_HandleTick:
  ldd r16, Y+UART_IRQ_IFACE_OFFS_TICKCOUNTER
  tst r16
  breq UART_Irq_HandleTick_handle
  dec r16
  std Y+UART_IRQ_IFACE_OFFS_TICKCOUNTER, r16
UART_Irq_HandleTick_handle:
  ldd r16, Y+UART_IRQ_IFACE_OFFS_STATE
  rjmp uart_irq_JumpToStateFunction           ; (r16, r17, r18, r19, X)
; @end



; ---------------------------------------------------------------------------
; @routine uart_irq_JumpToStateFunction
;
; @param r16 function
; @param Y pointer to interface data in SRAM (see @ref UART_IRQ_IFACE_OFFS_STATE)
; @param Z pointer to IFACE jump table for the given interface
; @clobbers r16, X (r17)

uart_irq_JumpToStateFunction:
  cpi r16, UART_IRQ_STATE_COUNT           ; invalid function num?
  brcc uart_irq_JumpToStateFunction_end
  ldi xl, LOW(uart_irq_state_jumptable)
  ldi xh, HIGH(uart_irq_state_jumptable)
  add xl, r16
  clr r16
  adc xh, r16
  push xl
  push xh
uart_irq_JumpToStateFunction_end:
  ret ; indirect jump to address we just pushed to the stack
uart_irq_state_jumptable:
  rjmp uart_irq_handle_idle            ; (R16)
  rjmp uart_irq_handle_waitforattnhigh ; (R16)
  rjmp uart_irq_handle_waitforstartbit ; (R16)
  rjmp uart_irq_handle_waitfordatabit  ; (R16)
  rjmp uart_irq_handle_waitforstopbit  ; (R16, R17, X)
  rjmp uart_irq_handle_sendingattn     ; (R16)
  rjmp uart_irq_handle_sendingstartbit ; (R16, R17, X)
  rjmp uart_irq_handle_sendingdatabit  ; (R16)
  rjmp uart_irq_handle_sendingstopbit  ; (R16)
; @end


; ---------------------------------------------------------------------------
; @routine uart_irq_ReadDataBit
;
; @param Y pointer to interface data in SRAM (see @ref UART_IRQ_IFACE_OFFS_STATE)
; @param Z pointer to IFACE jump table for the given interface
; @clobbers r16

uart_irq_ReadDataBit:
  adiw zh:zl, UART_IRQ_IFACE_PINFN_READDATA
  push zl
  push zh
  sbiw zh:zl, UART_IRQ_IFACE_PINFN_READDATA
  ret ; indirect jump to address we just pushed to the stack
; @end



; ---------------------------------------------------------------------------
; @routine uart_irq_ReadAttnBit
;
; @param Y pointer to interface data in SRAM (see @ref UART_IRQ_IFACE_OFFS_STATE)
; @param Z pointer to IFACE jump table for the given interface
; @clobbers r16

uart_irq_ReadAttnBit:
  adiw zh:zl, UART_IRQ_IFACE_PINFN_READATTN
  push zl
  push zh
  sbiw zh:zl, UART_IRQ_IFACE_PINFN_READATTN
  ret ; indirect jump to address we just pushed to the stack
; @end



; ---------------------------------------------------------------------------
; @routine uart_irq_WriteDataBit
;
; @param Y pointer to interface data in SRAM (see @ref UART_IRQ_IFACE_OFFS_STATE)
; @param Z pointer to IFACE jump table for the given interface
; @clobbers none

uart_irq_WriteDataBit:
  adiw zh:zl, UART_IRQ_IFACE_PINFN_WRITEDATA
  push zl
  push zh
  sbiw zh:zl, UART_IRQ_IFACE_PINFN_WRITEDATA
  ret ; indirect jump to address we just pushed to the stack
; @end



; ---------------------------------------------------------------------------
; @routine uart_irq_WriteAttnBit
;
; @param Y pointer to interface data in SRAM (see @ref UART_IRQ_IFACE_OFFS_STATE)
; @param Z pointer to IFACE jump table for the given interface
; @clobbers none

uart_irq_WriteAttnBit:
  adiw zh:zl, UART_IRQ_IFACE_PINFN_WRITEATTN
  push zl
  push zh
  sbiw zh:zl, UART_IRQ_IFACE_PINFN_WRITEATTN
  ret ; indirect jump to address we just pushed to the stack
; @end
  


; ---------------------------------------------------------------------------
; @routine uart_irq_handle_idle
;
; @param Y pointer to interface data in SRAM (see @ref UART_IRQ_IFACE_OFFS_STATE)
; @param Z pointer to IFACE jump table for the given interface
; @clobbers R16

uart_irq_handle_idle:
  rjmp uart_irq_handle_idle_checksend ; DEBUG!!
  
  rcall uart_irq_ReadAttnBit                   ; (R16)
  tst r16
  brne uart_irq_handle_idle_checksend          ; jump if ATTN line high
  ; ATTN low, start receiving
  ldi r16, UART_IRQ_STATE_WAITFORSTARTBIT
  std Y+UART_IRQ_IFACE_OFFS_STATE, r16
  ldi r16, UART_IRQ_TIME_BITTIME10
  std Y+UART_IRQ_IFACE_OFFS_TICKCOUNTER, r16
  rjmp uart_irq_handle_idle_end
uart_irq_handle_idle_checksend:
  ; check whether there is something to send
  ldd r16, Y+UART_IRQ_IFACE_OFFS_WRITEBUF_USED
  tst r16
  breq uart_irq_handle_idle_end                ; nothing to send
  ; start sending
  clr r16
  rcall uart_irq_WriteAttnBit                  ; (none)
  ldi r16, UART_IRQ_STATE_SENDINGATTN
  std Y+UART_IRQ_IFACE_OFFS_STATE, r16
  ldi r16, UART_IRQ_TIME_BITTIME2
  std Y+UART_IRQ_IFACE_OFFS_TICKCOUNTER, r16
uart_irq_handle_idle_end:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine uart_irq_handle_waitforstartbit
;
; @param Y pointer to interface data in SRAM (see @ref UART_IRQ_IFACE_OFFS_STATE)
; @param Z pointer to IFACE jump table for the given interface
; @clobbers R16

uart_irq_handle_waitforstartbit:
  rcall uart_irq_ReadAttnBit                    ; (R16)
  tst r16
  brne uart_irq_handle_waitforstartbit_toidle
  ; ATTN still low
  rcall uart_irq_ReadDataBit                    ; (R16)
  tst r16
  breq uart_irq_handle_waitforstartbit_datalow
  ; DATA still high
  ldd r16, Y+UART_IRQ_IFACE_OFFS_TICKCOUNTER
  tst r16
  brne uart_irq_handle_waitforstartbit_end
  ldi r16, UART_IRQ_STATE_WAITFORATTNHIGH
  std Y+UART_IRQ_IFACE_OFFS_STATE, r16
  rjmp uart_irq_handle_waitforstartbit_end
uart_irq_handle_waitforstartbit_datalow:
  ldi r16, UART_IRQ_STATE_WAITFORDATABIT
  std Y+UART_IRQ_IFACE_OFFS_STATE, r16
  ldi r16, UART_IRQ_TIME_BITTIME1_5
  std Y+UART_IRQ_IFACE_OFFS_TICKCOUNTER, r16
  ldi r16, 8 ; 8 bit
  std Y+UART_IRQ_IFACE_OFFS_STATECOUNTER, r16
  clr r16
  std Y+UART_IRQ_IFACE_OFFS_STATEDATA, r16
  rjmp uart_irq_handle_waitforstartbit_end
uart_irq_handle_waitforstartbit_toidle:
  ldi r16, UART_IRQ_STATE_IDLE
  std Y+UART_IRQ_IFACE_OFFS_STATE, r16
uart_irq_handle_waitforstartbit_end:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine uart_irq_handle_waitfordatabit
;
; @param Y pointer to interface data in SRAM (see @ref UART_IRQ_IFACE_OFFS_STATE)
; @param Z pointer to IFACE jump table for the given interface
; @clobbers R16

uart_irq_handle_waitfordatabit:
  rcall uart_irq_ReadAttnBit                        ; (R16)
  tst r16
  brne uart_irq_handle_waitfordatabit_toidle
  ldd r16, Y+UART_IRQ_IFACE_OFFS_TICKCOUNTER
  tst r16
  brne uart_irq_handle_waitfordatabit_end
  ; counter=0: read data
  rcall uart_irq_ReadDataBit                        ; (R16)
  ror r16                                           ; rotate bit into carry flag
  ldd r16, Y+UART_IRQ_IFACE_OFFS_STATEDATA          ; doesn't change carry flag
  ror r16                                           ; rotate carry flag into data byte
  std Y+UART_IRQ_IFACE_OFFS_STATEDATA, r16
  ldd r16, Y+UART_IRQ_IFACE_OFFS_STATECOUNTER
  dec r16
  brne uart_irq_handle_waitfordatabit_bytecomplete
  ldi r16, UART_IRQ_TIME_BITTIME1                   ; read next bit
  std Y+UART_IRQ_IFACE_OFFS_TICKCOUNTER, r16
  rjmp uart_irq_handle_waitfordatabit_end
uart_irq_handle_waitfordatabit_bytecomplete:
  ldi r16, UART_IRQ_STATE_WAITFORSTOPBIT
  std Y+UART_IRQ_IFACE_OFFS_STATE, r16
  ldi r16, UART_IRQ_TIME_BITTIME1_5
  std Y+UART_IRQ_IFACE_OFFS_TICKCOUNTER, r16
  rjmp uart_irq_handle_waitfordatabit_end
uart_irq_handle_waitfordatabit_toidle:
  ldi r16, UART_IRQ_STATE_IDLE
  std Y+UART_IRQ_IFACE_OFFS_STATE, r16
uart_irq_handle_waitfordatabit_end:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine uart_irq_handle_waitforstopbit
;
; @param Y pointer to interface data in SRAM (see @ref UART_IRQ_IFACE_OFFS_STATE)
; @param Z pointer to IFACE jump table for the given interface
; @clobbers R16 (R17, X)

uart_irq_handle_waitforstopbit:
  rcall uart_irq_ReadAttnBit                   ; (R16)
  tst r16
  brne uart_irq_handle_waitforstopbit_toidle
  rcall uart_irq_ReadDataBit
  tst r16
  brne uart_irq_handle_waitforstopbit_datahigh
  ; still low
  ldd r16, Y+UART_IRQ_IFACE_OFFS_TICKCOUNTER
  tst r16
  breq uart_irq_handle_waitforstopbit_abortmsg ; timeout, abort
  rjmp uart_irq_handle_waitforstopbit_end
uart_irq_handle_waitforstopbit_datahigh:
  ldd r16, Y+UART_IRQ_IFACE_OFFS_STATEDATA     ; store received byte
  rcall uart_irq_rdbuf_writebyte               ; (R17, X)
  brcc uart_irq_handle_waitforstopbit_abortmsg ; readbuffer full, abort
  ldi r16, UART_IRQ_STATE_WAITFORSTARTBIT      ; wait for next byte
  std Y+UART_IRQ_IFACE_OFFS_STATE, r16
  ldi r16, UART_IRQ_TIME_BITTIME10
  std Y+UART_IRQ_IFACE_OFFS_TICKCOUNTER, r16
  rjmp uart_irq_handle_waitforstopbit_end
uart_irq_handle_waitforstopbit_abortmsg:
  ldi r16, UART_IRQ_STATE_WAITFORATTNHIGH
  std Y+UART_IRQ_IFACE_OFFS_STATE, r16
  rjmp uart_irq_handle_waitforstopbit_end
uart_irq_handle_waitforstopbit_toidle:
  ldi r16, UART_IRQ_STATE_IDLE
  std Y+UART_IRQ_IFACE_OFFS_STATE, r16
uart_irq_handle_waitforstopbit_end:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine uart_irq_handle_waitforattnhigh
;
; @param Y pointer to interface data in SRAM (see @ref UART_IRQ_IFACE_OFFS_STATE)
; @param Z pointer to IFACE jump table for the given interface
; @clobbers R16

uart_irq_handle_waitforattnhigh:
  rcall uart_irq_ReadAttnBit               ; (R16)
  tst r16
  breq uart_irq_handle_waitforattnhigh_end ; still low
uart_irq_handle_waitforattnhigh_toidle:
  ldi r16, UART_IRQ_STATE_IDLE
  std Y+UART_IRQ_IFACE_OFFS_STATE, r16
uart_irq_handle_waitforattnhigh_end:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine uart_irq_handle_sendingattn
;
; @param Y pointer to interface data in SRAM (see @ref UART_IRQ_IFACE_OFFS_STATE)
; @param Z pointer to IFACE jump table for the given interface
; @clobbers R16

uart_irq_handle_sendingattn:
  ldd r16, Y+UART_IRQ_IFACE_OFFS_TICKCOUNTER
  tst r16
  brne uart_irq_handle_sendingattn_end
  ; send start bit
  clr r16
  rcall uart_irq_WriteDataBit                 ; (none)
  ldi r16, UART_IRQ_STATE_SENDINGSTARTBIT
  std Y+UART_IRQ_IFACE_OFFS_STATE, r16
  ldi r16, UART_IRQ_TIME_BITTIME1
  std Y+UART_IRQ_IFACE_OFFS_TICKCOUNTER, r16
uart_irq_handle_sendingattn_end:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine uart_irq_handle_sendingstartbit
;
; @param Y pointer to interface data in SRAM (see @ref UART_IRQ_IFACE_OFFS_STATE)
; @param Z pointer to IFACE jump table for the given interface
; @clobbers R16 (R17, X)

uart_irq_handle_sendingstartbit:
  ldd r16, Y+UART_IRQ_IFACE_OFFS_TICKCOUNTER
  tst r16
  brne uart_irq_handle_sendingstartbit_end
  ; get current data byte from ringbuffer
  rcall uart_irq_wrbuf_readbyte             ; (R17, X)
  std Y+UART_IRQ_IFACE_OFFS_STATEDATA, r16
  ; send data bit
  ldd r16, Y+UART_IRQ_IFACE_OFFS_STATEDATA
  andi r16, 1
  rcall uart_irq_WriteDataBit               ; (none)
  ldd r16, Y+UART_IRQ_IFACE_OFFS_STATEDATA
  ror r16
  std Y+UART_IRQ_IFACE_OFFS_STATEDATA, r16
  ldi r16, UART_IRQ_STATE_SENDINGDATABIT
  std Y+UART_IRQ_IFACE_OFFS_STATE, r16
  ldi r16, UART_IRQ_TIME_BITTIME1
  std Y+UART_IRQ_IFACE_OFFS_TICKCOUNTER, r16
  ldi r16, 8
  std Y+UART_IRQ_IFACE_OFFS_STATECOUNTER, r16
uart_irq_handle_sendingstartbit_end:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine uart_irq_handle_sendingdatabit
;
; @param Y pointer to interface data in SRAM (see @ref UART_IRQ_IFACE_OFFS_STATE)
; @param Z pointer to IFACE jump table for the given interface
; @clobbers R16

uart_irq_handle_sendingdatabit:
  ldd r16, Y+UART_IRQ_IFACE_OFFS_TICKCOUNTER
  tst r16
  brne uart_irq_handle_sendingdatabit_end
  ; all bits sent?
  ldd r16, Y+UART_IRQ_IFACE_OFFS_STATECOUNTER
  dec r16
  breq uart_irq_handle_sendingdatabit_tosendstopbit
  std Y+UART_IRQ_IFACE_OFFS_STATECOUNTER, r16
  ; send next data bit
  ldd r16, Y+UART_IRQ_IFACE_OFFS_STATEDATA
  andi r16, 1
  rcall uart_irq_WriteDataBit                        ; (none)
  ldd r16, Y+UART_IRQ_IFACE_OFFS_STATEDATA
  ror r16
  std Y+UART_IRQ_IFACE_OFFS_STATEDATA, r16
  ldi r16, UART_IRQ_TIME_BITTIME1                    ; send next bit
  std Y+UART_IRQ_IFACE_OFFS_TICKCOUNTER, r16
  rjmp uart_irq_handle_sendingstartbit_end
uart_irq_handle_sendingdatabit_tosendstopbit:
  ; send stop bit
  ldi r16, 1
  rcall uart_irq_WriteDataBit                        ; (none)
  ldi r16, UART_IRQ_STATE_SENDINGSTOPBIT
  std Y+UART_IRQ_IFACE_OFFS_STATE, r16
  ldi r16, UART_IRQ_TIME_BITTIME1
  std Y+UART_IRQ_IFACE_OFFS_TICKCOUNTER, r16
uart_irq_handle_sendingdatabit_end:
  ret
; @end



; ---------------------------------------------------------------------------
; @routine uart_irq_handle_sendingstopbit
;
; @param Y pointer to interface data in SRAM (see @ref UART_IRQ_IFACE_OFFS_STATE)
; @param Z pointer to IFACE jump table for the given interface
; @clobbers R16

uart_irq_handle_sendingstopbit:
  ldd r16, Y+UART_IRQ_IFACE_OFFS_TICKCOUNTER
  tst r16
  brne uart_irq_handle_sendingstopbit_end
  ; more to send?
  ldd r16, Y+UART_IRQ_IFACE_OFFS_WRITEBUF_USED
  tst r16
  breq uart_irq_handle_sendingstopbit_toidle ; nothing in buffer, go idle
  ; wait some time before sending next byte
  ldi r16, UART_IRQ_STATE_SENDINGATTN
  std Y+UART_IRQ_IFACE_OFFS_STATE, r16
  ldi r16, UART_IRQ_TIME_BITTIME1
  std Y+UART_IRQ_IFACE_OFFS_TICKCOUNTER, r16
  rjmp uart_irq_handle_sendingstopbit_end
uart_irq_handle_sendingstopbit_toidle:
  ldi r16, 1
  rcall uart_irq_WriteAttnBit                ; (none)
  ldi r16, UART_IRQ_STATE_IDLE
  std Y+UART_IRQ_IFACE_OFFS_STATE, r16
uart_irq_handle_sendingstopbit_end:
  ret






; ---------------------------------------------------------------------------
; @routine uart_irq_rdbuf_writebyte
;
; @param R16 byte to write
; @param Y   base address (for "LDD Y+nn" and "STD Y+nn")
; @return CFLAG set if okay, cleared on error (i.e. buffer full)
; @clobbers R17, X

uart_irq_rdbuf_writebyte:
  m_ringbuffer_y_writebyte \
    UART_IRQ_IFACE_READBUF_SIZE, \
    UART_IRQ_IFACE_OFFS_READBUF_USED, \
    UART_IRQ_IFACE_OFFS_READBUF_RDPOS, \
    UART_IRQ_IFACE_OFFS_READBUF_WRPOS, \
    UART_IRQ_IFACE_OFFS_READBUF_BUF
  ret
; @end



; ---------------------------------------------------------------------------
; @routine uart_irq_rdbuf_readbyte
;
; @param Y   base address (for "LDD Y+nn" and "STD Y+nn")
; @return CFLAG set if okay, cleared on error (i.e. buffer full)
; @return R16 byte read
; @clobbers R17, X

uart_irq_rdbuf_readbyte:
  m_ringbuffer_y_readbyte \
    UART_IRQ_IFACE_READBUF_SIZE, \
    UART_IRQ_IFACE_OFFS_READBUF_USED, \
    UART_IRQ_IFACE_OFFS_READBUF_RDPOS, \
    UART_IRQ_IFACE_OFFS_READBUF_WRPOS, \
    UART_IRQ_IFACE_OFFS_READBUF_BUF
  ret
; @end



; ---------------------------------------------------------------------------
; @routine uart_irq_wrbuf_writebyte
;
; @param R16 byte to write
; @param Y   base address (for "LDD Y+nn" and "STD Y+nn")
; @return CFLAG set if okay, cleared on error (i.e. buffer full)
; @clobbers R17, X

uart_irq_wrbuf_writebyte:
  m_ringbuffer_y_writebyte \
    UART_IRQ_IFACE_WRITEBUF_SIZE, \
    UART_IRQ_IFACE_OFFS_WRITEBUF_USED, \
    UART_IRQ_IFACE_OFFS_WRITEBUF_RDPOS, \
    UART_IRQ_IFACE_OFFS_WRITEBUF_WRPOS, \
    UART_IRQ_IFACE_OFFS_WRITEBUF_BUF
  ret
; @end



; ---------------------------------------------------------------------------
; @routine uart_irq_wrbuf_readbyte
;
; @param Y   base address (for "LDD Y+nn" and "STD Y+nn")
; @return CFLAG set if okay, cleared on error (i.e. buffer full)
; @return R16 byte read
; @clobbers R17, X

uart_irq_wrbuf_readbyte:
  m_ringbuffer_y_readbyte \
    UART_IRQ_IFACE_WRITEBUF_SIZE, \
    UART_IRQ_IFACE_OFFS_WRITEBUF_USED, \
    UART_IRQ_IFACE_OFFS_WRITEBUF_RDPOS, \
    UART_IRQ_IFACE_OFFS_WRITEBUF_WRPOS, \
    UART_IRQ_IFACE_OFFS_WRITEBUF_BUF
  ret
; @end



; ---------------------------------------------------------------------------
; @routine uart_irq_timer_init
;
; setup timer0 for irq every 52/4 ns

uart_irq_timer_init:                           ; setup timer for IRQ every 52/4 ns
  ldi r16, (1<<WGM01) | (0<<WGM00)             ; CTC mode
  out TCCR0A, r16

;
; Settings for clock 8Mhz
; use timer0 with prescaler 1, OCR0A=104-1 (irq every 13us)
;
.if clock == 8000000

  ldi r16, (0<<CS02) | (0<<CS01) | (1<<CS00)  ; Prescaler 1
  out TCCR0B, r16
;  ldi r16, 52-1                    ; set timer for 8 times baudrate (fixed to 19200 for now)
  ldi r16, 104-1                    ; set timer for 4 times baudrate (fixed to 19200 for now)
;  ldi r16, 208-1                   ; set timer for 2 times baudrate (fixed to 19200 for now)
  out OCR0A, r16
.endif


;
; Settings for clock 16Mhz
; use timer0 with prescaler 1, OCR0A=208-1 (irq every 13us)
; alternative:    prescaler 8, OCR0A=26-1  (irq every 13us)
;
.if clock == 16000000
  ldi r16, (0<<CS02) | (0<<CS01) | (1<<CS00)  ; Prescaler 1
  out TCCR0B, r16

  ldi r16, 208-1                   ; set timer for 4 times baudrate (fixed to 19200 for now)
  out OCR0A, r16
.endif



  ldi r16, (1<<OCF0A)             ; clear pending interrupts
.ifdef TIFR0
  out TIFR0, r16
.else
  out TIFR, r16
.endif
  
  ldi r16, (1<<OCIE0A)            ; Timer/Counter0 Output Compare Match A Interrupt Enable
.ifdef TIMSK0
  out TIMSK0, r16
.else
  out TIMSK, r16
.endif
  sec
  ret
; @end



; ---------------------------------------------------------------------------
; @routine uartIrqIsrOC0A @isr
;
; OC0A interrupt handler
;

uartIrqIsrOC0A:
  push r15
    in r15, SREG
      push r16
        push r17
          push xh
            push xl
              push yh
                push yl
                  push zh
                    push zl
                      push r15
                        rcall UART_Irq_Iface1_HandleTick
                        rcall UART_Irq_Iface2_HandleTick
                      pop r15
                    pop zl
                  pop zh
                pop yl
              pop yh
            pop xl
          pop xh
        pop r17
      pop r16
    out SREG, r15
  pop r15
  reti
; @end






UART_IRQ_END:
.equ MODULE_SIZE_UART_IRQ = UART_IRQ_END-UART_IRQ_BEGIN


