725 lines
20 KiB
NASM
725 lines
20 KiB
NASM
; ***************************************************************************
|
|
; 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
|
|
|
|
|