Files
aqhomecontrol/avr/modules/com2w/com2wi2.asm

1230 lines
30 KiB
NASM

; ***************************************************************************
; copyright : (C) 2025 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. *
; ***************************************************************************
; work in progress!
#ifndef AVR_MODULES_COM2W_COM2WI_H
#define AVR_MODULES_COM2W_COM2WI_H
.equ COM2WI_BUFFER_SIZE = NET_BUFFERS_SIZE-1
.equ COM2WI_R_MAX_WAIT_HI_TIME = 100 ; max 1ms
.equ COM2WI_S_MAX_WAIT_HI_TIME = 100 ; max 1ms
.equ COM2WI_S_MAX_WAIT_LO_TIME = 100 ; max 1ms
.equ COM2WI_W_MAX_WAIT_BUSFREE = 100 ; max 1ms
.equ COM2WI_STATETIMER_W_BYTEHOLDCLOCKLOW = 2 ; 20 us
.equ COM2WI_STATETIMER_W_BITHOLDCLOCKLOW = 2 ; 20 us
.equ COM2WI_STATETIMER_W_BITSETDATA = 2 ; 20 us
.equ COM2WI_STATETIMER_W_BITHOLDCLOCKHIGH = 2 ; 20 us
.equ COM2WI_STATETIMER_R_WAITFORCLOCKHIGH = 100 ; 1 ms
.equ COM2WI_STATETIMER_R_WAITFORCLOCKLOW = 100 ; 1 ms
.equ COM2WI_STATETIMER_S_WAITFORCLOCKLOW = 100 ; 1 ms
.equ COM2WI_STATE_IDLE = 0
.equ COM2WI_STATE_W_MSGWAITBUSFREE = 1
.equ COM2WI_STATE_W_BYTEHOLDCLOCKLOW = 2
.equ COM2WI_STATE_W_BITHOLDCLOCKLOW = 3
.equ COM2WI_STATE_W_BITSETDATA = 4
.equ COM2WI_STATE_W_BITHOLDCLOCKHIGH = 5
.equ COM2WI_STATE_W_MSGSENT = 6
.equ COM2WI_STATE_R_WAITFORCLOCKHIGH = 7
.equ COM2WI_STATE_R_WAITFORCLOCKLOW = 8
.equ COM2WI_STATE_R_MSGRECVD = 9
.equ COM2WI_STATE_S_WAITFORCLOCKLOW = 10
.equ COM2WI_STATE_S_WAITFORCLOCKHIGH = 11
.equ COM2WI_STATE_COUNT = 12
.equ COM2WI_IFACE_OFFS_BEGIN = NET_IFACE_SIZE
.equ COM2WI_IFACE_OFFS_STATE = COM2WI_IFACE_OFFS_BEGIN+0
.equ COM2WI_IFACE_OFFS_STATETIMER = COM2WI_IFACE_OFFS_BEGIN+1
.equ COM2WI_IFACE_OFFS_STATECOUNTER = COM2WI_IFACE_OFFS_BEGIN+2
.equ COM2WI_IFACE_OFFS_PINMASK_CLK = COM2WI_IFACE_OFFS_BEGIN+3
.equ COM2WI_IFACE_OFFS_PINMASK_DATA = COM2WI_IFACE_OFFS_BEGIN+4
.equ COM2WI_IFACE_OFFS_BITCOUNTER = COM2WI_IFACE_OFFS_BEGIN+5
.equ COM2WI_IFACE_OFFS_CURRBYTE = COM2WI_IFACE_OFFS_BEGIN+6
.equ COM2WI_IFACE_OFFS_BUFPOS_LOW = COM2WI_IFACE_OFFS_BEGIN+7
.equ COM2WI_IFACE_OFFS_BUFPOS_HIGH = COM2WI_IFACE_OFFS_BEGIN+8
.equ COM2WI_IFACE_OFFS_BUFUSED = COM2WI_IFACE_OFFS_BEGIN+9
.equ COM2WI_IFACE_OFFS_BUFLEFT = COM2WI_IFACE_OFFS_BEGIN+10
.equ COM2WI_IFACE_OFFS_BUFFER = COM2WI_IFACE_OFFS_BEGIN+11
.equ COM2WI_IFACE_SIZE = COM2WI_IFACE_OFFS_BUFFER+COM2WI_BUFFER_SIZE
; ---------------------------------------------------------------------------
; @macro mCOM2WI_INIT
;
; @param @0 interface number (beginning with 0)
.macro mCOM2WI_INIT
ldi yl, LOW(com2wi@0_iface)
ldi yh, HIGH(com2wi@0_iface)
mov xl, yl
mov xh, yh
ldi r17, COM2WI_IFACE_SIZE
clr r16
rcall Utils_FillSram ; (R17, X)
rcall NET_Interface_Init ; (R16, R17, X)
ldi r16, @0 +1
std Y+NET_IFACE_OFFS_IFACENUM, r16
ldi r16, COM_MASK_CLK@0
std Y+COM2WI_IFACE_OFFS_PINMASK_CLK, r16
ldi r16, COM_MASK_DATA@0
std Y+COM2WI_IFACE_OFFS_PINMASK_DATA, r16
; ldi r16, COM_MASK_IRQ@0
; std Y+COM2WI_IFACE_OFFS_PINMASK_IRQ, r16
rcall com2wiInit
.endmacro
; @end
.dseg
.if COM_PORTS >0
com2wi0_iface: .byte COM2WI_IFACE_SIZE
.endif
.if COM_PORTS >1
com2wi1_iface: .byte COM2WI_IFACE_SIZE
.endif
.if COM_PORTS >2
com2wi2_iface: .byte COM2WI_IFACE_SIZE
.endif
.if COM_PORTS >3
com2wi3_iface: .byte COM2WI_IFACE_SIZE
.endif
.if COM_PORTS >4
com2wi4_iface: .byte COM2WI_IFACE_SIZE
.endif
.if COM_PORTS >5
com2wi5_iface: .byte COM2WI_IFACE_SIZE
.endif
.if COM_PORTS >6
com2wi6_iface: .byte COM2WI_IFACE_SIZE
.endif
.if COM_PORTS >7
com2wi7_iface: .byte COM2WI_IFACE_SIZE
.endif
.cseg
; ---------------------------------------------------------------------------
; @routine COM2WI_Init
COM2WI_Init:
.if COM_PORTS >0
mCOM2WI_INIT 0
.endif
.if COM_PORTS >1
mCOM2WI_INIT 1
.endif
.if COM_PORTS >2
mCOM2WI_INIT 2
.endif
.if COM_PORTS >3
mCOM2WI_INIT 3
.endif
.if COM_PORTS >4
mCOM2WI_INIT 4
.endif
.if COM_PORTS >5
mCOM2WI_INIT 5
.endif
.if COM_PORTS >6
mCOM2WI_INIT 6
.endif
.if COM_PORTS >7
mCOM2WI_INIT 7
.endif
rcall com2wiSetupTimer1
ret
; @end
; ---------------------------------------------------------------------------
; @routine COM2WI_Timer1Isr @global @isr
;
; ISR for timer1
;
; @clobbers: none
COM2WI_Timer1Isr:
push r15
in r15, SREG
push r1
push r2
inr r1, COM_CLK_INPUT
inr r2, COM_DATA_INPUT
push r16
push r17
push r18
push yl
push yh
push zl
push zh
rcall COM2WI_HandleTimerIrq ; (r16, r17, r18, Y, Z)
pop zh
pop zl
pop yh
pop yl
pop r18
pop r17
pop r16
pop r2
pop r1
out SREG, r15
pop r15
reti
; @end
; ---------------------------------------------------------------------------
; @routine COM2WI_Run
COM2WI_Run:
ldi yl, LOW(com2wi0_iface)
ldi yh, HIGH(com2wi0_iface)
ldi r18, COM_PORTS
clr r19
COM2WI_Run_loop:
push r18
push r19
rcall com2wiRun
pop r19
pop r18
sbci r19, 0
ldi r16, COM2WI_IFACE_SIZE
add yl, r16
adc yh, r16
sub yh, r16
dec r18
brne COM2WI_Run_loop
; check for repeat request
tst r19
clc
breq COM2WI_Run_end
sec
COM2WI_Run_end:
ret
; @end
; ---------------------------------------------------------------------------
; @routine COM2WI_HandleTimerIrq
;
; @param Y pointer to interface data in SRAM
; @clobbers R16, R17, R18, Y, Z
COM2WI_HandleTimerIrq:
ldi yl, LOW(com2wi0_iface)
ldi yh, HIGH(com2wi0_iface)
ldi r18, COM_PORTS
COM2WI_HandleTimerIrq_loop:
push r18
rcall com2wiHandleIrq ; R16, R17, R18, Z
pop r18
ldi r16, COM2WI_IFACE_SIZE
add yl, r16
adc yh, r16
sub yh, r16
dec r18
brne COM2WI_HandleTimerIrq_loop
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wiInit
com2wiInit:
rcall com2wiSetupLines
ldi r16, COM2WI_STATE_IDLE
std Y+COM2WI_IFACE_OFFS_STATE, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wiSetupLines
com2wiSetupLines:
; setup CLK line (as input, disable internal pull-up resistor)
.ifdef COM_CLK_PUE
ldd r16, Y+COM2WI_IFACE_OFFS_PINMASK_CLK
com r16
inr r17, COM_CLK_PUE
and r17, r16
outr COM_CLK_PUE, r17
.endif
rcall com2wiClkSetHigh
; setup DATA line (as input, disable internal pull-up resistor)
.ifdef COM_DATA_PUE
ldd r16, Y+COM2WI_IFACE_OFFS_PINMASK_DATA
com r16
inr r17, COM_DATA_PUE
and r17, r16
outr COM_DATA_PUE, r17
.endif
rcall com2wiDataSetHigh
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wiSetupTimer1
;
; setup timer for IRQ every 20us
com2wiSetupTimer1:
; CTC mode, no prescaler, OCR1A=100 (every 20us at 20MHz)
; WGM13=0, WGM12=1, WGM11=0, WGM10=0
ldi r16, 0
outr TCCR1A, r16 ; WGM11=0, WGM10=0
ldi r16, (0<<CS12) | (0<<CS11) | (1<<CS10) | (0<<WGM13) | (1<<WGM12)
outr TCCR1B, r16
clr r17 HIGH(200)
ldi r16, LOW(200)
outr OCR1AH, r17
outr OCR1AL, r16
ldi r16, (1<<OCF1A) ; clear pending interrupts
outr TIFR1, r16
inr r16, TIMSK1
sbr r16, (1<<OCIE1A) ; Timer/Counter1 Output Compare Match A Interrupt Enable
outr TIMSK1, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wiClkSetHigh
;
; @clobbers none
com2wiClkSetHigh:
push r16
push r17
ldd r16, Y+COM2WI_IFACE_OFFS_PINMASK_CLK
; clear bit in io reg (AND with complement)
com r16
inr r17, COM_CLK_DDR
and r17, r16
outr COM_CLK_DDR, r17 ; make pin input
.ifndef COM_CLK_PUE
inr r17, COM_CLK_OUTPUT
and r17, r16 ; disable pullup
outr COM_CLK_OUTPUT, r17
.endif
pop r17
pop r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wiClkSetLow
;
; @clobbers none
com2wiClkSetLow:
push r16
push r17
ldd r16, Y+COM2WI_IFACE_OFFS_PINMASK_CLK
; set bit in io reg
inr r17, COM_CLK_DDR
or r17, r16
outr COM_CLK_DDR, r17 ; make pin output
com r16
inr r17, COM_CLK_OUTPUT
and r17, r16
outr COM_CLK_OUTPUT, r17 ; set pin low
pop r17
pop r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wiDataSetHigh
;
; @param Y pointer to interface data in SRAM
; @clobbers none
com2wiDataSetHigh:
push r16
push r17
ldd r16, Y+COM2WI_IFACE_OFFS_PINMASK_DATA
; clear bit in io reg (AND with complement)
com r16
inr r17, COM_DATA_DDR
and r17, r16
outr COM_DATA_DDR, r17 ; make pin input
.ifndef COM_DATA_PUE
inr r17, COM_DATA_OUTPUT
and r17, r16 ; disable pullup
outr COM_DATA_OUTPUT, r17
.endif
pop r17
pop r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wiDataSetLow
;
; @param Y pointer to interface data in SRAM
; @clobbers none
com2wiDataSetLow:
push r16
push r17
ldd r16, Y+COM2WI_IFACE_OFFS_PINMASK_DATA
; set bit in io reg
inr r17, COM_DATA_DDR
or r17, r16
outr COM_DATA_DDR, r17 ; make pin output
com r16
inr r17, COM_DATA_OUTPUT
and r17, r16
outr COM_DATA_OUTPUT, r17 ; set pin low
pop r17
pop r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wiHandleIrq
;
; @param Y pointer to interface data in SRAM
; @clobbers R16, R17, R18, Z
com2wiHandleIrq:
; dec state timer
ldd r17, Y+COM2WI_IFACE_OFFS_STATETIMER
tst r17
breq com2wiHandleIrq_jmp
dec r17
std Y+COM2WI_IFACE_OFFS_STATETIMER, r17
; jump
com2wiHandleIrq_jmp:
ldi zl, LOW(com2wiIrqJumpTable)
ldi zh, HIGH(com2wiIrqJumpTable)
ldd r16, Y+COM2WI_IFACE_OFFS_STATE
cpi r16, COM2WI_STATE_COUNT
brcc com2wiHandleIrq_ret
add zl, r16
adc zh, r16
sub zh, r16
ijmp
com2wiHandleIrq_ret:
ret
com2wiIrqJumpTable:
rjmp com2wiIrqStateIdle ; 0: COM2WI_STATE_IDLE (r16, r18)
rjmp com2wiIrqStateWMsgWaitBusFree ; 1: COM2WI_STATE_W_MSGWAITBUSFREE (r16, r18)
rjmp com2wiIrqStateWByteHoldClockLow ; 2: COM2WI_STATE_W_BYTEHOLDCLOCKLOW (r16)
rjmp com2wiIrqStateWBitHoldClockLow ; 3: COM2WI_STATE_W_BITHOLDCLOCKLOW (r16)
rjmp com2wiIrqStateWBitSetData ; 4: COM2WI_STATE_W_BITSETDATA (r16)
rjmp com2wiIrqStateWBitHoldClockHigh ; 5: COM2WI_STATE_W_BITHOLDCLOCKHIGH (r16)
ret ; 6: COM2WI_STATE_W_MSGSENT
rjmp com2wiIrqStateRWaitForClockHigh ; 7: COM2WI_STATE_R_WAITFORCLOCKHIGH
rjmp com2wiIrqStateRWaitForClockLow ; 8: COM2WI_STATE_R_WAITFORCLOCKLOW
ret ; 9: COM2WI_STATE_R_MSGRECVD
rjmp com2wiIrqStateSWaitForClockLow ; 10: COM2WI_STATE_S_WAITFORCLOCKLOW
rjmp com2wiIrqStateSWaitForClockHigh ; 11: COM2WI_STATE_S_WAITFORCLOCKHIGH
; @end
; ---------------------------------------------------------------------------
; @routine com2wiIrqStateIdle
;
; @param Y pointer to interface data in SRAM
; @param r17 current state timer
; @clobbers r16, r18
com2wiIrqStateIdle:
mov r16, r1
; inr r16, COM_CLK_INPUT
ldd r18, Y+COM2WI_IFACE_OFFS_PINMASK_CLK
and r16, r18
brne com2wiIrqStateIdle_ret
; CLK is low, start receiving
push xl
push xh
mov xh, yh
mov xl, yl
adiw xh:xl, COM2WI_IFACE_OFFS_BUFFER
std Y+COM2WI_IFACE_OFFS_BUFPOS_LOW, xl
std Y+COM2WI_IFACE_OFFS_BUFPOS_HIGH, xh
ldi r16, COM2WI_BUFFER_SIZE
std Y+COM2WI_IFACE_OFFS_BUFLEFT, r16
clr r16
std Y+COM2WI_IFACE_OFFS_BUFUSED, r16
std Y+COM2WI_IFACE_OFFS_BITCOUNTER, r16
pop xh
pop xl
rjmp com2wiEnterStateRWaitForClockHigh
com2wiIrqStateIdle_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wiIrqStateWMsgWaitBusFree
;
; @param Y pointer to interface data in SRAM
; @param r17 current state timer
; @clobbers r16, r18
com2wiIrqStateWMsgWaitBusFree:
inr r16, COM_CLK_INPUT
ldd r18, Y+COM2WI_IFACE_OFFS_PINMASK_CLK
and r16, r18
brne com2wiIrqStateWMsgWaitBusFree_isHi
; CLK line is low, restart wait counter
ldi r16, COM2WI_W_MAX_WAIT_BUSFREE
std Y+COM2WI_IFACE_OFFS_STATETIMER, r16
ret
com2wiIrqStateWMsgWaitBusFree_isHi:
tst r17
brne com2wiIrqStateWMsgWaitBusFree_ret
; CLK still high, time's up, start transmitting
rjmp com2wiEnterStateWByteHoldClockLow
com2wiIrqStateWMsgWaitBusFree_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wiIrqStateWMsgWaitBusFree
;
; @param Y pointer to interface data in SRAM
; @param r17 current state timer
; @clobbers r16
com2wiIrqStateWByteHoldClockLow:
tst r17
brne com2wiIrqStateWByteHoldClockLow_ret
rjmp com2wiEnterStateWBitHoldClockLow ; (r16)
com2wiIrqStateWByteHoldClockLow_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wiIrqStateWMsgWaitBusFree
;
; @param Y pointer to interface data in SRAM
; @param r17 current state timer
; @clobbers r16
com2wiIrqStateWBitHoldClockLow:
tst r17
brne com2wiIrqStateWBitHoldClockLow_ret
rjmp com2wiEnterStateWBitSetData ; (r16)
com2wiIrqStateWBitHoldClockLow_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wiIrqStateWBitSetData
;
; @param Y pointer to interface data in SRAM
; @param r17 current state timer
; @clobbers r16
com2wiIrqStateWBitSetData:
tst r17
brne com2wiIrqStateWBitSetData_ret
rjmp com2wiEnterStateWBitHoldClockHigh
com2wiIrqStateWBitSetData_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wiIrqStateWBitHoldClockHigh
;
; @param Y pointer to interface data in SRAM
; @param r17 current state timer
; @clobbers r16
com2wiIrqStateWBitHoldClockHigh:
tst r17
brne com2wiIrqStateWBitHoldClockHigh_ret
ldd r16, Y+COM2WI_IFACE_OFFS_BITCOUNTER
cpi r16, 8
breq com2wiIrqStateWBitHoldClockHigh_byteFull
rjmp com2wiEnterStateWBitHoldClockLow ; (r16)
com2wiIrqStateWBitHoldClockHigh_byteFull:
ldd r16, Y+COM2WI_IFACE_OFFS_BUFLEFT
tst r16
brne com2wiIrqStateWBitHoldClockHigh_nextByte
rjmp com2wiEnterStateWMsgSent ; (r16)
com2wiIrqStateWBitHoldClockHigh_nextByte:
rjmp com2wiEnterStateWByteHoldClockLow
com2wiIrqStateWBitHoldClockHigh_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wiIrqStateRWaitForClockHigh
;
; @param Y pointer to interface data in SRAM
; @param r17 current state timer
; @clobbers r16
com2wiIrqStateRWaitForClockHigh:
mov r16, r1
; inr r16, COM_CLK_INPUT
ldd r18, Y+COM2WI_IFACE_OFFS_PINMASK_CLK
and r16, r18
brne com2wiIrqStateRWaitForClockHigh_isHi
tst r17
brne com2wiIrqStateRWaitForClockHigh_ret
; time's up, enter skipping mode
rjmp com2wiEnterStateSWaitForClockHigh
com2wiIrqStateRWaitForClockHigh_isHi:
mov r16, r2
; inr r16, COM_DATA_INPUT
ldd r18, Y+COM2WI_IFACE_OFFS_PINMASK_DATA
and r16, r18
clc
breq com2wiIrqStateRWaitForClockHigh_shiftIn
sec
com2wiIrqStateRWaitForClockHigh_shiftIn:
ldd r16, Y+COM2WI_IFACE_OFFS_CURRBYTE
ror r16
std Y+COM2WI_IFACE_OFFS_CURRBYTE, r16
ldd r17, Y+COM2WI_IFACE_OFFS_BITCOUNTER
inc r17
std Y+COM2WI_IFACE_OFFS_BITCOUNTER, r17
cpi r17, 8
brne com2wiIrqStateRWaitForClockHigh_waitForLo
; byte complete, store
ldd r17, Y+COM2WI_IFACE_OFFS_BUFLEFT
dec r17
std Y+COM2WI_IFACE_OFFS_BUFLEFT, r17
clr r18
std Y+COM2WI_IFACE_OFFS_BITCOUNTER, r18
ldd r18, Y+COM2WI_IFACE_OFFS_BUFUSED
inc r18
std Y+COM2WI_IFACE_OFFS_BUFUSED, r18
push xl
push xh
ldd xl, Y+COM2WI_IFACE_OFFS_BUFPOS_LOW
ldd xh, Y+COM2WI_IFACE_OFFS_BUFPOS_HIGH
st X+, r16
std Y+COM2WI_IFACE_OFFS_BUFPOS_LOW, xl
std Y+COM2WI_IFACE_OFFS_BUFPOS_HIGH, xh
pop xh
pop xl
tst r17
breq com2wiIrqStateRWaitForClockHigh_msgRecvd
; check size
cpi r18, 2
brne com2wiIrqStateRWaitForClockHigh_waitForLo
inc r16 ; last byte=remainder of msg, add CRC byte
cp r17, r16
brcs com2wiIrqStateRWaitForClockHigh_badMsgSize
std Y+COM2WI_IFACE_OFFS_BUFLEFT, r16
tst r16
breq com2wiIrqStateRWaitForClockHigh_msgRecvd ; jmp if message complete
com2wiIrqStateRWaitForClockHigh_waitForLo:
rjmp com2wiEnterStateRWaitForClockLow
com2wiIrqStateRWaitForClockHigh_badMsgSize:
ldi r16, NET_IFACE_OFFS_ERR_MSGSIZE_LOW
push r24
push r25
rcall NET_Interface_IncCounter16
pop r25
pop r24
rjmp com2wiEnterStateSWaitForClockHigh
com2wiIrqStateRWaitForClockHigh_msgRecvd:
rjmp com2wiEnterStateRMsgRecvd
com2wiIrqStateRWaitForClockHigh_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wiIrqStateRWaitForClockLow
;
; @param Y pointer to interface data in SRAM
; @param r17 current state timer
; @clobbers r16
com2wiIrqStateRWaitForClockLow:
mov r16, r1
; inr r16, COM_CLK_INPUT
ldd r18, Y+COM2WI_IFACE_OFFS_PINMASK_CLK
and r16, r18
breq com2wiIrqStateRWaitForClockLow_isLo
tst r17
brne com2wiIrqStateRWaitForClockLow_ret
; time's up, enter skipping mode
rjmp com2wiEnterStateSWaitForClockLow
com2wiIrqStateRWaitForClockLow_isLo:
rjmp com2wiEnterStateRWaitForClockHigh
com2wiIrqStateRWaitForClockLow_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wiIrqStateSWaitForClockHigh
;
; @param Y pointer to interface data in SRAM
; @param r17 current state timer
; @clobbers r16
com2wiIrqStateSWaitForClockHigh:
mov r16, r1
; inr r16, COM_CLK_INPUT
ldd r18, Y+COM2WI_IFACE_OFFS_PINMASK_CLK
and r16, r18
breq com2wiIrqStateSWaitForClockHigh_ret ; jmp if still low
rjmp com2wiEnterStateSWaitForClockLow
com2wiIrqStateSWaitForClockHigh_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wiIrqStateSWaitForClockLow
;
; @param Y pointer to interface data in SRAM
; @param r17 current state timer
; @clobbers r16, r18
com2wiIrqStateSWaitForClockLow:
mov r16, r1
; inr r16, COM_CLK_INPUT
ldd r18, Y+COM2WI_IFACE_OFFS_PINMASK_CLK
and r16, r18
brne com2wiIrqStateSWaitForClockLow_isHi
; CLK is low again, restart loop
rjmp com2wiEnterStateSWaitForClockHigh
com2wiIrqStateSWaitForClockLow_isHi:
tst r17
brne com2wiIrqStateSWaitForClockLow_ret
; time's up, line still high, leave skipping mode
rjmp com2wiEnterStateIdle
com2wiIrqStateSWaitForClockLow_ret:
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wiEnterStateIdle
;
; @param Y pointer to interface data in SRAM
; @clobbers r16
com2wiEnterStateIdle:
; setup lines (make sure we don't hold the lines low)
rcall com2wiClkSetHigh ; (none)
rcall com2wiDataSetHigh ; (none)
; setup state
clr r16
std Y+COM2WI_IFACE_OFFS_STATETIMER, r16
ldi r16, COM2WI_STATE_IDLE
std Y+COM2WI_IFACE_OFFS_STATE, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wiEnterStateWMsgWaitBusFree
;
; @param Y pointer to interface data in SRAM
; @clobbers r16
com2wiEnterStateWMsgWaitBusFree:
; setup lines (make sure we don't hold the lines low)
rcall com2wiClkSetHigh ; (none)
rcall com2wiDataSetHigh ; (none)
; setup state
ldi r16, COM2WI_W_MAX_WAIT_BUSFREE
std Y+COM2WI_IFACE_OFFS_STATETIMER, r16
ldi r16, COM2WI_STATE_W_MSGWAITBUSFREE
std Y+COM2WI_IFACE_OFFS_STATE, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wiEnterStateWByteHoldClockLow
;
; @param Y pointer to interface data in SRAM
; @clobbers r16
com2wiEnterStateWByteHoldClockLow:
; setup line
rcall com2wiClkSetLow ; (none)
; setup state
ldi r16, COM2WI_STATETIMER_W_BYTEHOLDCLOCKLOW
std Y+COM2WI_IFACE_OFFS_STATETIMER, r16
ldi r16, COM2WI_STATE_W_BYTEHOLDCLOCKLOW
std Y+COM2WI_IFACE_OFFS_STATE, r16
; setup current byte
push xl
push xh
ldd xl, Y+COM2WI_IFACE_OFFS_BUFPOS_LOW
ldd xh, Y+COM2WI_IFACE_OFFS_BUFPOS_HIGH
ld r16, X+
std Y+COM2WI_IFACE_OFFS_BUFPOS_LOW, xl
std Y+COM2WI_IFACE_OFFS_BUFPOS_HIGH, xh
pop xh
pop xl
std Y+COM2WI_IFACE_OFFS_CURRBYTE, r16
clr r16
std Y+COM2WI_IFACE_OFFS_BITCOUNTER, r16
ldd r16, Y+COM2WI_IFACE_OFFS_BUFLEFT
dec r16
std Y+COM2WI_IFACE_OFFS_BUFLEFT, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wiEnterStateWBitHoldClockLow
;
; @param Y pointer to interface data in SRAM
; @clobbers r16
com2wiEnterStateWBitHoldClockLow:
; setup line
rcall com2wiClkSetLow ; (none)
; setup state
ldi r16, COM2WI_STATETIMER_W_BITHOLDCLOCKLOW
std Y+COM2WI_IFACE_OFFS_STATETIMER, r16
ldi r16, COM2WI_STATE_W_BITHOLDCLOCKLOW
std Y+COM2WI_IFACE_OFFS_STATE, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wiEnterStateWBitSetData
;
; @param Y pointer to interface data in SRAM
; @clobbers r16
com2wiEnterStateWBitSetData:
; setup state
ldi r16, COM2WI_STATETIMER_W_BITSETDATA
std Y+COM2WI_IFACE_OFFS_STATETIMER, r16
ldi r16, COM2WI_STATE_W_BITSETDATA
std Y+COM2WI_IFACE_OFFS_STATE, r16
; setup line
ldd r16, Y+COM2WI_IFACE_OFFS_BITCOUNTER
inc r16
std Y+COM2WI_IFACE_OFFS_BITCOUNTER, r16
ldd r16, Y+COM2WI_IFACE_OFFS_CURRBYTE
lsr r16
std Y+COM2WI_IFACE_OFFS_CURRBYTE, r16
brcc com2wiEnterStateWBitSetData_set0
rcall com2wiDataSetHigh
ret
com2wiEnterStateWBitSetData_set0:
rcall com2wiDataSetLow
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wiEnterStateWBitHoldClockHigh
;
; @param Y pointer to interface data in SRAM
; @clobbers r16
com2wiEnterStateWBitHoldClockHigh:
; setup line
rcall com2wiClkSetHigh ; (none)
; setup state
ldi r16, COM2WI_STATETIMER_W_BITHOLDCLOCKHIGH
std Y+COM2WI_IFACE_OFFS_STATETIMER, r16
ldi r16, COM2WI_STATE_W_BITHOLDCLOCKHIGH
std Y+COM2WI_IFACE_OFFS_STATE, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wiEnterStateWMsgSent
;
; @param Y pointer to interface data in SRAM
; @clobbers r16
com2wiEnterStateWMsgSent:
; setup lines
rcall com2wiClkSetHigh ; (none)
rcall com2wiDataSetHigh ; (none)
; setup state
clr r16 ; wait indefinately
std Y+COM2WI_IFACE_OFFS_STATETIMER, r16
ldi r16, COM2WI_STATE_W_MSGSENT
std Y+COM2WI_IFACE_OFFS_STATE, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wiEnterStateRWaitForClockHigh
;
; @param Y pointer to interface data in SRAM
; @clobbers r16
com2wiEnterStateRWaitForClockHigh:
ldi r16, COM2WI_STATETIMER_R_WAITFORCLOCKHIGH
std Y+COM2WI_IFACE_OFFS_STATETIMER, r16
ldi r16, COM2WI_STATE_R_WAITFORCLOCKHIGH
std Y+COM2WI_IFACE_OFFS_STATE, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wiEnterStateRWaitForClockLow
;
; @param Y pointer to interface data in SRAM
; @clobbers r16
com2wiEnterStateRWaitForClockLow:
ldi r16, COM2WI_STATETIMER_R_WAITFORCLOCKLOW
std Y+COM2WI_IFACE_OFFS_STATETIMER, r16
ldi r16, COM2WI_STATE_R_WAITFORCLOCKLOW
std Y+COM2WI_IFACE_OFFS_STATE, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wiEnterStateSWaitForClockHigh
;
; @param Y pointer to interface data in SRAM
; @clobbers r16
com2wiEnterStateSWaitForClockHigh:
clr r16
std Y+COM2WI_IFACE_OFFS_STATETIMER, r16
ldi r16, COM2WI_STATE_S_WAITFORCLOCKHIGH
std Y+COM2WI_IFACE_OFFS_STATE, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wiEnterStateSWaitForClockLow
;
; @param Y pointer to interface data in SRAM
; @clobbers r16
com2wiEnterStateSWaitForClockLow:
ldi r16, COM2WI_STATETIMER_S_WAITFORCLOCKLOW
std Y+COM2WI_IFACE_OFFS_STATETIMER, r16
ldi r16, COM2WI_STATE_S_WAITFORCLOCKLOW
std Y+COM2WI_IFACE_OFFS_STATE, r16
ret
; @end
com2wiEnterStateRMsgRecvd:
; setup state
clr r16 ; wait indefinately
std Y+COM2WI_IFACE_OFFS_STATETIMER, r16
ldi r16, COM2WI_STATE_R_MSGRECVD
std Y+COM2WI_IFACE_OFFS_STATE, r16
ret
; @end
; ---------------------------------------------------------------------------
; @routine com2wiRun
;
; @param Y pointer to interface data in SRAM
; @clobbers
com2wiRun:
ldi zl, LOW(com2wiRunJumpTable)
ldi zh, HIGH(com2wiRunJumpTable)
ldd r16, Y+COM2WI_IFACE_OFFS_STATE
cpi r16, COM2WI_STATE_COUNT
brcc com2wiRun_ret
add zl, r16
adc zh, r16
sub zh, r16
ijmp
com2wiRun_ret:
ret
com2wiRunJumpTable:
rjmp com2wiRunStateIdle ; 0: COM2WI_STATE_IDLE
ret ; 1: COM2WI_STATE_W_MSGWAITBUSFREE
ret ; 2: COM2WI_STATE_W_BYTEHOLDCLOCKLOW
ret ; 3: COM2WI_STATE_W_BITHOLDCLOCKLOW
ret ; 4: COM2WI_STATE_W_BITSETDATA
ret ; 5: COM2WI_STATE_W_BITHOLDCLOCKHIGH
rjmp com2wiRunStateWMsgSent ; 6: COM2WI_STATE_W_MSGSENT
ret ; 7: COM2WI_STATE_R_WAITFORCLOCKHI
ret ; 8: COM2WI_STATE_R_WAITFORCLOCKLO
rjmp com2wiRunStateRMsgRecvd ; 9: COM2WI_STATE_R_MSGRECVD
ret ; 10: COM2WI_STATE_S_WAITFORCLOCKLO
ret ; 11: COM2WI_STATE_S_WAITFORCLOCKHI
; @end
com2wiRunStateIdle:
; look for outbound message
rcall NET_Interface_PeekNextOutgoingMsgNum ; r16=msgNum
brcc com2wiRunStateIdle_ret
push r15
in r15, SREG
cli
rcall NET_Buffer_Locate ; (R17)
adiw xh:xl, 1
std Y+COM2WI_IFACE_OFFS_BUFPOS_LOW, xl
std Y+COM2WI_IFACE_OFFS_BUFPOS_HIGH, xh
adiw xh:xl, NETMSG_OFFS_MSGLEN
ld r16, X
subi r16, -3
std Y+COM2WI_IFACE_OFFS_BUFUSED, r16
std Y+COM2WI_IFACE_OFFS_BUFLEFT, r16
rcall com2wiEnterStateWMsgWaitBusFree ; (R16)
out SREG, r15
pop r15
com2wiRunStateIdle_ret:
clc ; no need to re-run in this loop
ret
; @end
com2wiRunStateWMsgSent:
rcall NET_Interface_GetNextOutgoingMsgNum ; take current msg off the queue
brcc com2wiRunStateWMsgSent_ret
rcall NET_Buffer_ReleaseByNum ; (R16, X)
push r15
in r15, SREG
cli
rcall com2wiEnterStateIdle
out SREG, r15
pop r15
ldi r16, NET_IFACE_OFFS_PACKETSOUT_LOW
push r24
push r25
rcall NET_Interface_IncCounter16
pop r25
pop r24
rcall LedActivity_Trigger
sec ; did something
com2wiRunStateWMsgSent_ret:
ret
; @end
com2wiRunStateRMsgRecvd:
mov xl, yl
mov xh, yh
adiw xh:xl, COM2WI_IFACE_OFFS_BUFFER
rcall NETMSG_CheckMessageInBuffer ; (R16, R17, R18, R19, R20, X)
brcc com2wiRunStateRMsgRecvd_crcError
#ifndef COM_ACCEPT_ALL_DEST
; check destination addr
mov xl, yl
mov xh, yh
adiw xh:xl, COM2W_IFACE_OFFS_BUFFER
adiw xh:xl, NETMSG_OFFS_DESTADDR
ld r16, X ; read destination address
cpi r16, 0xff
breq com2wiRunStateRMsgRecvd_forMe
ldd r17, Y+NET_IFACE_OFFS_ADDRESS
cp r16, r17
breq com2wiRunStateRMsgRecvd_forMe
; packet not for me, but correctly received, inc counter, but don't light LED
ldi r16, NET_IFACE_OFFS_PACKETSIN_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
rjmp com2wiRunStateRMsgRecvd_goIdle
com2wiRunStateRMsgRecvd_forMe:
#endif
; msg received, alloc buffer for it
rcall NET_Buffer_Alloc ; R16=buffer num (R16, R17, X)
brcc com2wiRunStateRMsgRecvd_noBuf
; set interface number in msg header
mov r19, r16 ; save buffer num
rcall NET_Interface_SetIfaceNumInBuffer ; (R16, R17)
mov r16, r19 ; restore buffer num
; copy into allocated buffer
push zl
push zh
mov zl, yl
mov zh, yh
adiw zh:zl, COM2WI_IFACE_OFFS_BUFFER ; Z=SRC
adiw xh:xl, 1 ; X=DEST
ldd r18, Z+NETMSG_OFFS_MSGLEN
inc r18
inc r18
inc r18
com2wiRunStateRMsgRecvd_copyLoop:
ld r17, Z+
st X+, r17
dec r18
brne com2wiRunStateRMsgRecvd_copyLoop
pop zh
pop zl
; add to incoming msg pool
rcall NET_AddIncomingMsgNum ; (R17, R18, X)
brcc com2wReceiveNextPkg_eMissed
ldi r16, NET_IFACE_OFFS_PACKETSIN_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
#ifdef MODULES_LED_ACTIVITY
rcall LedActivity_Trigger ; (r16)
#endif
; fall-through to enter idle state
com2wiRunStateRMsgRecvd_goIdle:
push r15
in r15, SREG
cli
rcall com2wiEnterStateIdle
out SREG, r15
pop r15
sec
rjmp com2wiRunStateRMsgRecvd_ret
com2wiRunStateRMsgRecvd_noBuf:
ldi r16, NET_IFACE_OFFS_ERR_NOBUF_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
rjmp com2wiRunStateRMsgRecvd_goIdle
com2wiRunStateRMsgRecvd_crcError:
ldi r16, NET_IFACE_OFFS_ERR_CONTENT_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
rjmp com2wiRunStateRMsgRecvd_goIdle
com2wReceiveNextPkg_eMissed:
rcall NET_Buffer_ReleaseByNum ; (R16, X)
ldi r16, NET_IFACE_OFFS_ERR_MISSED_LOW
rcall NET_Interface_IncCounter16 ; (R24, R25)
rjmp com2wiRunStateRMsgRecvd_goIdle
com2wiRunStateRMsgRecvd_ret:
ret
; @end
#endif