There are now fixed buffers which are organized in a ringbuffer. This makes it easier to access data stored in the buffers, also receiving packets is now way faster with reduced risk of sync problems.
956 lines
25 KiB
NASM
956 lines
25 KiB
NASM
|
|
|
|
|
|
; ***************************************************************************
|
|
; defines
|
|
|
|
.equ COM_MAXWAIT = 200 ; maximum loop count when waiting for rising/falling clock (TODO: Make frequency-dependant)
|
|
|
|
|
|
.equ COM_BUFFER_FLAGS_DONE = 0x80
|
|
.equ COM_BUFFER_FLAGS_RECEIVED = 0x40
|
|
.equ COM_BUFFER_FLAGS_TOSEND = 0x20
|
|
.equ COM_BUFFER_FLAGS_RELEASED = 0x10
|
|
.equ COM_BUFFER_FLAGS_PRIO1 = 0x08
|
|
.equ COM_BUFFER_FLAGS_PRIO0 = 0x04
|
|
.equ COM_BUFFER_FLAGS_IFACE1 = 0x02
|
|
.equ COM_BUFFER_FLAGS_IFACE0 = 0x01
|
|
|
|
.equ COM_BUFFER_PRIO_INFO = 0
|
|
.equ COM_BUFFER_PRIO_NORMAL = COM_BUFFER_FLAGS_PRIO0
|
|
.equ COM_BUFFER_PRIO_IMPORTANT = COM_BUFFER_FLAGS_PRIO1
|
|
.equ COM_BUFFER_PRIO_VITAL = (COM_BUFFER_FLAGS_PRIO0 | COM_BUFFER_FLAGS_PRIO1)
|
|
|
|
.equ COM_REPEAT_INFO = 3
|
|
.equ COM_REPEAT_NORMAL = 32
|
|
.equ COM_REPEAT_IMPORTANT = 64
|
|
.equ COM_REPEAT_VITAL = 255
|
|
|
|
.equ COM_BUFFER_NUM = 4
|
|
.equ COM_BUFFER_SIZE = 16 ; CAVE: Need to change routine COM_BufferPosToY when changing this value!!
|
|
|
|
|
|
.equ COM_BUFFER_OFFS_FLAGS = 0 ; first byte in buffer is flags byte
|
|
.equ COM_BUFFER_OFFS_DATA = 1
|
|
|
|
.equ COM_MSG_OFFS_DESTADDR = 0
|
|
.equ COM_MSG_OFFS_MSGLEN = 1
|
|
.equ COM_MSG_OFFS_MSGDATA = 2
|
|
|
|
.equ COM_CMD_PING = 1
|
|
|
|
|
|
; ***************************************************************************
|
|
; data
|
|
|
|
.dseg
|
|
|
|
|
|
comDataBegin:
|
|
comFlags: .byte 1
|
|
comAddress: .byte 1
|
|
comRepeatCount: .byte 1
|
|
comReserved1: .byte 1
|
|
|
|
comStatsPacketsIn: .byte 2
|
|
comStatsPacketsOut: .byte 2
|
|
|
|
comStatsRecvErrs: .byte 2
|
|
comStatsCollisions: .byte 2
|
|
comStatsMissed: .byte 2
|
|
comStatsAborted: .byte 2
|
|
comStatsIgnored: .byte 2
|
|
comStatsHandled: .byte 2
|
|
|
|
comRecvBuffersReadPos: .byte 1
|
|
comRecvBuffersWritePos: .byte 1
|
|
comRecvBuffersUsed: .byte 1
|
|
comRecvBuffers: .byte (COM_BUFFER_SIZE*COM_BUFFER_NUM)
|
|
comDataEnd:
|
|
|
|
|
|
|
|
; ***************************************************************************
|
|
; code
|
|
|
|
.cseg
|
|
|
|
|
|
comIsrPcint0:
|
|
push r15
|
|
in r15, SREG
|
|
sbic COM_PIN_ATTN, COM_PINNUM_ATTN
|
|
rjmp comIsrPcint0_end
|
|
; low, read packet
|
|
push r1
|
|
push r16
|
|
push r17
|
|
push r20
|
|
push r21
|
|
push r22
|
|
push xh
|
|
push xl
|
|
push yh
|
|
push yl
|
|
rcall comReceivePacketHandleBuffer ; (R1, R16, R17, R20, R21, R22, X, Y)
|
|
pop yl
|
|
pop yh
|
|
pop xl
|
|
pop xh
|
|
pop r22
|
|
pop r21
|
|
pop r20
|
|
pop r17
|
|
pop r16
|
|
pop r1
|
|
|
|
comIsrPcint0_end:
|
|
pop r15
|
|
reti
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; Com_Init
|
|
;
|
|
; IN:
|
|
; OUT:
|
|
; - CFLAG: set if okay, clear on error
|
|
; USED: R16, R17, X, Y
|
|
|
|
Com_Init:
|
|
; preset SRAM data area
|
|
ldi xh, HIGH(comDataBegin)
|
|
ldi xl, LOW(comDataBegin)
|
|
clr r16
|
|
ldi r17, (comDataEnd-comDataBegin)
|
|
rcall Utils_FillSram
|
|
|
|
ldi r16, 1 ; debug: set fixed address "1"
|
|
sts comAddress, r16
|
|
|
|
; setup pins and interrupts
|
|
cbi COM_PORT_DATA, COM_PINNUM_DATA ; disable internal pullup for DATA
|
|
cbi COM_DDR_DATA, COM_PINNUM_DATA ; set DATA port as input
|
|
|
|
cbi COM_PORT_ATTN, COM_PINNUM_ATTN ; disable internal pullup for ATTN
|
|
cbi COM_DDR_ATTN, COM_PINNUM_ATTN ; set ATTN port as input
|
|
|
|
sbi COM_IRQ_ADDR_ATTN, COM_IRQ_BIT_ATTN ; enable pin change irq for ATTN line
|
|
in r16, GIMSK ; enable pin change irq PCIE0 or PCIE1
|
|
ori r16, (1<<COM_IRQ_GIMSK_ATTN)
|
|
out GIMSK, R16
|
|
in r16, GIFR ; clear pending irq
|
|
andi r16, ~(1<<COM_IRQ_GIFR_ATTN)
|
|
out GIFR, r16
|
|
|
|
sec
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; Com_Run
|
|
;
|
|
; IN:
|
|
; - nothing
|
|
; OUT:
|
|
; - CFLAG: set if something done, can be called again immediately (otherwise: wait for timer interrupt and retry)
|
|
; REGS: (R1, R3, R16, R17, R18, R19, R22, X)
|
|
|
|
Com_Run:
|
|
rcall comHandleNextPacketInQueue ; nothing more than handling packages in ringbuffer
|
|
; clc
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; Mark a packet as enqueued.
|
|
;
|
|
; IN:
|
|
; - Y: pointer to buffer containing the enqueued packet
|
|
; - R20: priority
|
|
; OUT:
|
|
; - CFLAG: set if okay, clear otherwise
|
|
; MODIFIED REGS: R15, R16
|
|
|
|
COM_EnqueuePacket:
|
|
in r15, SREG
|
|
cli
|
|
ldd r16, y+COM_BUFFER_OFFS_FLAGS
|
|
andi r16, (~(COM_BUFFER_FLAGS_PRIO1 | COM_BUFFER_FLAGS_PRIO0 | COM_BUFFER_FLAGS_RECEIVED | COM_BUFFER_FLAGS_DONE)) & 0xff
|
|
or r16, r20 ; add priority
|
|
ori r16, COM_BUFFER_FLAGS_TOSEND
|
|
std y+COM_BUFFER_OFFS_FLAGS, r16
|
|
out SREG, r15 ; restore IRQ flag
|
|
sec
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; COM_AllocBufferAndGetXY
|
|
;
|
|
; IN:
|
|
; - nothing
|
|
; OUT:
|
|
; - CFLAG: set if okay, clear otherwise
|
|
; - Y: pointer to buffer
|
|
; - X: pointer to data portion of the buffer
|
|
; MODIFIED REGS: R16, R17 (R21)
|
|
|
|
COM_AllocBufferAndGetXY:
|
|
rcall COM_BufferAlloc ; (r16, r17, r21)
|
|
brcc COM_AllocBufferAndGetXY_error
|
|
mov xl, yl
|
|
mov xh, yh
|
|
ldi r16, COM_BUFFER_OFFS_DATA
|
|
clr r17
|
|
add xl, r16
|
|
adc xh, r17
|
|
sec
|
|
ret
|
|
COM_AllocBufferAndGetXY_error:
|
|
clc
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; Enqueue a PING packet.
|
|
;
|
|
; IN:
|
|
; - R16: destination address
|
|
; OUT:
|
|
; - CFLAG: set if okay, clear otherwise
|
|
; MODIFIED REGS: R16, R17, R20, X (R15, Y)
|
|
|
|
COM_EnqueuePing:
|
|
push r16
|
|
rcall COM_AllocBufferAndGetXY ; (r16, r17, r21)
|
|
pop r16
|
|
brcc COM_EnqueuePing_error
|
|
clr r17 ; r17: XOR byte
|
|
; write header (dest address, msg length)
|
|
st X+, r16 ; destination address
|
|
eor r17, r16
|
|
ldi r16, 2 ; 2 bytes payload
|
|
st X+, r16
|
|
eor r17, r16
|
|
; write payload
|
|
ldi r16, COM_CMD_PING
|
|
st X+, r16
|
|
eor r17, r16
|
|
lds r16, comAddress
|
|
st X+, r16
|
|
eor r17, r16
|
|
; store XOR byte
|
|
st X+, r17
|
|
; mark buffer as enqueued with PRIO "info" (limited amount of retries)
|
|
ldi r20, COM_BUFFER_PRIO_INFO
|
|
rcall COM_EnqueuePacket ; (R15, R16)
|
|
brcc COM_EnqueuePing_error
|
|
sec
|
|
ret
|
|
COM_EnqueuePing_error:
|
|
clc
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; comHandleNextPacketInQueue
|
|
;
|
|
; IN:
|
|
; - nothing
|
|
; OUT:
|
|
; - CFLAG: set if something done, can be called again immediately (otherwise: wait for timer interrupt and retry)
|
|
; MODIFIED REGS: R16, R17, Y (R15, R18, R21, R22, X)
|
|
|
|
|
|
comHandleNextPacketInQueue:
|
|
lds r16, comRecvBuffersUsed
|
|
tst r16
|
|
breq comHandleNextPacketInQueue_retNc ; no buffers in use
|
|
|
|
lds r16, comRecvBuffersReadPos
|
|
rcall COM_BufferPosToY ; get current read buffer to Y (R16, R17)
|
|
ldd r16, y+COM_BUFFER_OFFS_FLAGS ; get flags
|
|
; check for released buffer (dealloc)
|
|
mov r17, r16
|
|
andi r17, COM_BUFFER_FLAGS_RELEASED ; check for buffer released
|
|
brne comHandleNextPacketInQueue_releaseBuffer
|
|
; check for received packet
|
|
mov r17, r16
|
|
andi r17, COM_BUFFER_FLAGS_RECEIVED
|
|
brne comHandleNextPacketInQueue_receivedPacket
|
|
; check for buffer to send
|
|
mov r17, r16
|
|
andi r17, COM_BUFFER_FLAGS_TOSEND ; check for message to send
|
|
brne comHandleNextPacketInQueue_sendPacket
|
|
; nothing to do (e.g. buffer not ready to be sent)
|
|
rjmp comHandleNextPacketInQueue_retNc
|
|
comHandleNextPacketInQueue_sendPacket:
|
|
rcall comSendPacketHandleRepeat ; (R15, R16, R17, R18, R21, R22, X)
|
|
ret ; use CFLAG from subroutine
|
|
comHandleNextPacketInQueue_receivedPacket:
|
|
clr r17
|
|
sts comRepeatCount, r17 ; set comRepeatCount to zero
|
|
rcall comHandleReceivedPacket ; (r16, r17, r21, X)
|
|
sec ; always return with set CFLAG
|
|
ret
|
|
comHandleNextPacketInQueue_releaseBuffer:
|
|
rcall COM_BufferDeallocFront
|
|
sec ; always return with set CFLAG
|
|
ret
|
|
comHandleNextPacketInQueue_retNc:
|
|
clc
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; comHandleReceivedPacket
|
|
;
|
|
; IN:
|
|
; - Y: pointer to current buffer (pointed to by comRecvBuffersReadPos)
|
|
; OUT:
|
|
; - nothing
|
|
; MODIFIED REGS: X (r16, r17, r21)
|
|
|
|
|
|
comHandleReceivedPacket:
|
|
rcall onPacketReceived
|
|
brcs comHandleReceivedPacket_l1
|
|
ldi xl, LOW(comStatsIgnored)
|
|
ldi xh, HIGH(comStatsIgnored)
|
|
rjmp comHandleReceivedPacket_l2
|
|
comHandleReceivedPacket_l1:
|
|
ldi xl, LOW(comStatsHandled)
|
|
ldi xh, HIGH(comStatsHandled)
|
|
comHandleReceivedPacket_l2:
|
|
rcall comDeallocReadBufAndIncrCounter ; (r16, r17, r21)
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; comSendPacketHandleRepeat
|
|
;
|
|
; IN:
|
|
; - Y: pointer to current buffer (pointed to by comRecvBuffersReadPos)
|
|
; OUT:
|
|
; - CFLAG: set if something done, can be called again immediately (otherwise: wait for timer interrupt and retry)
|
|
; MODIFIED REGS: R15, R17, R22, X (R16, R17, R18, R21, R22)
|
|
|
|
comSendPacketHandleRepeat:
|
|
in r15, SREG
|
|
cli
|
|
ldd r16, y+COM_BUFFER_OFFS_FLAGS
|
|
rcall comSetupRepeat ; setup comRepeatCount if not already done (R16, R17)
|
|
cbi COM_PORT_ATTN, COM_PINNUM_ATTN ; set ATTN low
|
|
sbi COM_DDR_ATTN, COM_PINNUM_ATTN ; set ATTN as output
|
|
Utils_WaitNanoSecs COM_BIT_LENGTH, 0, r22 ; wait for one bit duration
|
|
rcall comSendPacketHandleBuffer ; (R16, R17, R21, R22)
|
|
cbi COM_DDR_ATTN, COM_PINNUM_ATTN ; release ATTN line
|
|
brcc comSendPacketHandleRepeat_adjustRepeat
|
|
; packet sent, adjust stats, release buffer
|
|
ldi xl, LOW(comStatsPacketsOut)
|
|
ldi xh, HIGH(comStatsPacketsOut)
|
|
rcall comDeallocReadBufAndIncrCounter ; (r16, r17, r18)
|
|
rjmp comSendPacketHandleRepeat_retC
|
|
comSendPacketHandleRepeat_adjustRepeat:
|
|
; increment collisions counter
|
|
ldi xl, LOW(comStatsCollisions)
|
|
ldi xh, HIGH(comStatsCollisions)
|
|
clr r22
|
|
ld r16, x+
|
|
ld r17, x
|
|
inc r16
|
|
adc r17, r22
|
|
st -x, r17
|
|
st x, r16
|
|
; decrement repeat counter (except for vital messages)
|
|
lds r17, comRepeatCount
|
|
cpi r17, COM_REPEAT_VITAL
|
|
breq comSendPacketHandleRepeat_retNC ; vital message, repeat forever
|
|
dec r17
|
|
sts comRepeatCount, r17
|
|
brne comSendPacketHandleRepeat_retNC
|
|
; dealloc buffer, inc abort counter
|
|
ldi xl, LOW(comStatsAborted)
|
|
ldi xh, HIGH(comStatsAborted)
|
|
rcall comDeallocReadBufAndIncrCounter
|
|
rjmp comSendPacketHandleRepeat_retC
|
|
|
|
comSendPacketHandleRepeat_retNC:
|
|
out SREG, r15
|
|
clc
|
|
ret
|
|
|
|
comSendPacketHandleRepeat_retC:
|
|
out SREG, r15
|
|
sec
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; comSetupRepeat
|
|
;
|
|
; IN:
|
|
; - R16: priority
|
|
; OUT:
|
|
; - CFLAG: set if okay, clear otherwise
|
|
; MODIFIED REGS: R16, R17
|
|
|
|
comSetupRepeat:
|
|
lds r17, comRepeatCount
|
|
tst r17
|
|
brne comSetupRepeat_l99 ; comRepeatCount already setup
|
|
; set comRepeatCount according to priority
|
|
andi r16, (COM_BUFFER_FLAGS_PRIO1 | COM_BUFFER_FLAGS_PRIO0) ; r16: flags
|
|
cpi r16, COM_REPEAT_INFO
|
|
brne comSetupRepeat_l1
|
|
ldi r17, COM_REPEAT_INFO
|
|
rjmp comSetupRepeat_l98
|
|
comSetupRepeat_l1:
|
|
cpi r16, COM_REPEAT_NORMAL
|
|
brne comSetupRepeat_l2
|
|
ldi r17, COM_REPEAT_NORMAL
|
|
rjmp comSetupRepeat_l98
|
|
comSetupRepeat_l2:
|
|
cpi r16, COM_REPEAT_IMPORTANT
|
|
brne comSetupRepeat_l3
|
|
ldi r17, COM_REPEAT_IMPORTANT
|
|
rjmp comSetupRepeat_l98
|
|
comSetupRepeat_l3:
|
|
ldi r17, COM_REPEAT_VITAL
|
|
comSetupRepeat_l98:
|
|
sts comRepeatCount, r17
|
|
comSetupRepeat_l99:
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; comDeallocReadBufAndIncrCounter
|
|
;
|
|
; IN:
|
|
; - X : pointer to counter
|
|
; OUT:
|
|
; - nothing
|
|
; REGS: r16, r17, r21
|
|
|
|
comDeallocReadBufAndIncrCounter:
|
|
rcall COM_BufferDeallocFront ; (r16, r17, r21)
|
|
clr r21
|
|
ld r16, x+
|
|
ld r17, x
|
|
inc r16
|
|
adc r17, r21
|
|
st -x, r17
|
|
st x, r16
|
|
sts comRepeatCount, r21 ; set comRepeatCount to zero
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; comSendPacketHandleBuffer
|
|
;
|
|
; Send a packet from the current read buffer (pointed to by comRecvBuffersReadPos).
|
|
; On success the flag COM_BUFFER_FLAGS_DONE is set in the buffer.
|
|
; The buffer is not released.
|
|
;
|
|
; CAVE: Expects interrupts to be disabled!
|
|
;
|
|
; IN:
|
|
; - Y : pointer to current read buffer
|
|
; OUT:
|
|
; - CFLAG: set if okay, clear otherwise
|
|
; MODIFIED REGS: R16, R17 (R21, R22)
|
|
|
|
comSendPacketHandleBuffer:
|
|
mov xl, yl
|
|
mov xh, yh
|
|
ldi r16, COM_BUFFER_OFFS_DATA
|
|
clr r17
|
|
add xl, r16
|
|
adc xh, r17
|
|
ldd r16, y+(COM_BUFFER_OFFS_DATA+COM_MSG_OFFS_MSGLEN) ; get msg payload length
|
|
ldi r17, 3
|
|
add r16, r17 ; add dest addr, msg len and XOR byte
|
|
rcall comSendPacketFromSram ; send all that
|
|
brcc comSendPacketHandleBuffer_error
|
|
ldd r16, y+COM_BUFFER_OFFS_FLAGS
|
|
ori r16, COM_BUFFER_FLAGS_DONE
|
|
std y+COM_BUFFER_OFFS_FLAGS, r16
|
|
sec
|
|
ret
|
|
comSendPacketHandleBuffer_error:
|
|
clc
|
|
ret
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; comSendPacketFromSram
|
|
;
|
|
; Send a packet from SRAM
|
|
;
|
|
; IN:
|
|
; - R16: number of bytes to send
|
|
; - X: pointer to buffer to read from
|
|
; OUT:
|
|
; - CFLAG: set if okay, clear otherwise
|
|
; MODIFIED REGS: R16, R17 (R21, R22)
|
|
|
|
comSendPacketFromSram:
|
|
mov r17, r16
|
|
comSendPacketFromSram_loop:
|
|
ld r16, X+
|
|
rcall comSendByte ; send byte (R16, R21, R22)
|
|
brcc comSendPacketFromSram_error
|
|
dec r17
|
|
brne comSendPacketFromSram_loop
|
|
sec
|
|
ret
|
|
|
|
comSendPacketFromSram_error:
|
|
clc
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; comReceivePacketHandleBuffer
|
|
;
|
|
; Allocate a buffer and receive a packet into it.
|
|
; On success the buffer flags will have COM_BUFFER_FLAGS_RECEIVED set.
|
|
; On error the buffer will be deallocated.
|
|
; IN:
|
|
; - nothing
|
|
; OUT:
|
|
; - CFLAG: set if okay, cleared otherwise
|
|
; MODIFIED REGISTERS: R16, R17, X, Y (R1, R20, R21, R22)
|
|
|
|
comReceivePacketHandleBuffer:
|
|
rcall COM_BufferAlloc
|
|
brcc comReceivePacketHandleBuffer_error
|
|
; get pos of data portion for the allocated buffer
|
|
mov xl, yl
|
|
mov xh, yh
|
|
ldi r16, COM_BUFFER_OFFS_DATA
|
|
clr r17
|
|
add xl, r16
|
|
adc xh, r17
|
|
rcall comReceivePacketToSram ; (r1, r16, r17, R20, R21, R22, X)
|
|
brcc comReceivePacketHandleBuffer_dealloc
|
|
; handle buffer flags
|
|
ldi r16, COM_BUFFER_FLAGS_RECEIVED
|
|
std y+COM_BUFFER_OFFS_FLAGS, r16
|
|
sec
|
|
ret
|
|
|
|
comReceivePacketHandleBuffer_dealloc:
|
|
rcall COM_BufferDeallocBack ; (r16, r17, r21)
|
|
comReceivePacketHandleBuffer_error:
|
|
clc
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; comReceivePacketToSram
|
|
;
|
|
; Receive a packet to the given SRAM position.
|
|
; IN:
|
|
; - X: pointer to start of buffer to receive bytes
|
|
; OUT:
|
|
; - CFLAG: set if okay, clear otherwise
|
|
; MODIFIED REGISTERS: r1, r16, r17, X (R20, R21, R22)
|
|
|
|
comReceivePacketToSram:
|
|
clr r1 ; r1: checksum
|
|
; read destination address
|
|
rcall comReceiveByte ; read byte (R16, R17, R20, R21, R22)
|
|
brcc comReceivePacketToSram_error
|
|
eor r1, r16
|
|
; compare destination address (accept "0" and own address)
|
|
tst r16
|
|
breq comReceivePacketToSram_acceptAddr
|
|
lds r17, comAddress
|
|
cp r16, r17
|
|
breq comReceivePacketToSram_acceptAddr
|
|
clc ; not for me
|
|
ret
|
|
comReceivePacketToSram_acceptAddr:
|
|
st X+, r16
|
|
|
|
; read msg length
|
|
rcall comReceiveByte ; read packet length (R16, R17, R20, R21, R22)
|
|
brcc comReceivePacketToSram_error
|
|
eor r1, r16
|
|
st X+, r16
|
|
tst r16
|
|
breq comReceivePacketToSram_readXOR
|
|
mov r17, r16
|
|
comReceivePacketToSram_loop:
|
|
push r17
|
|
rcall comReceiveByte ; read byte (R16, R17, R20, R21, R22)
|
|
pop r17
|
|
brcc comReceivePacketToSram_error
|
|
st X+, r16
|
|
eor r1, r16
|
|
dec r17
|
|
brne comReceivePacketToSram_loop
|
|
|
|
comReceivePacketToSram_readXOR:
|
|
rcall comReceiveByte ; XOR byte (R16, R17, R20, R21, R22)
|
|
brcc comReceivePacketToSram_error
|
|
st X+, r16
|
|
eor r1, r16
|
|
brne comReceivePacketToSram_error
|
|
sec
|
|
ret
|
|
|
|
comReceivePacketToSram_error:
|
|
clc
|
|
ret
|
|
|
|
|
|
|
|
; ***************************************************************************
|
|
; lowlevel pin functions
|
|
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; comSendByte
|
|
;
|
|
; Send a byte.
|
|
; We only set the data pin to low at the beginning for the startbit. After that
|
|
; we only change the pin direction (e.g. input vs output):
|
|
; - for 0 bit: set DDR to output, forcing the data line low
|
|
; - for 1 bit: set DDR to input, letting the external pullup R pull the data line to HIGH
|
|
; since the output pin is still set to 0 the internal pullup is disabled
|
|
; IN:
|
|
; - R16: byte to send
|
|
; OUT:
|
|
; - CFLAG: set if okay, clear otherwise
|
|
; MODIFIED REGS: R16, R21, R22
|
|
|
|
comSendByte:
|
|
ldi r21, 8 ; +1 bits left
|
|
; send startbit
|
|
cbi COM_PORT_DATA, COM_PINNUM_DATA ; +2 set DATA low
|
|
sbi COM_DDR_DATA, COM_PINNUM_DATA ; +2 set DATA as output
|
|
Utils_WaitNanoSecs COM_BIT_LENGTH, 5, r22 ; wait for on bit duration
|
|
; send remaining bits
|
|
comSendByte_loop:
|
|
lsr r16 ; 1+ bit to send -> CARRY
|
|
brcs comSendByte_setHigh ; HI: +2, LO: +1
|
|
comSendByte_setLow:
|
|
sbi COM_DDR_DATA, COM_PINNUM_DATA ; +2 set DATA as output
|
|
nop
|
|
rjmp comSendByte_waitBit ; +2
|
|
comSendByte_setHigh:
|
|
cbi COM_DDR_DATA, COM_PINNUM_DATA ; +2 set DATA as input, pullup R makes it ONE
|
|
nop ; +1 (to make pin change available)
|
|
sbis COM_PIN_DATA, COM_PINNUM_DATA ; +1 if okay, +2 otherwise
|
|
rjmp comSendByte_error ; +2 if error
|
|
comSendByte_waitBit: ; 7 cycles in this loop until now
|
|
Utils_WaitNanoSecs COM_BIT_LENGTH, 10, r22
|
|
dec r21 ; +1
|
|
brne comSendByte_loop ; +2, sum per loop: 10 cycles
|
|
; send stopbit
|
|
cbi COM_DDR_DATA, COM_PINNUM_DATA ; +2 set DATA as input, pullup R makes it ONE
|
|
Utils_WaitNanoSecs COM_BIT_LENGTH, 4, r22
|
|
sec
|
|
ret
|
|
|
|
comSendByte_error:
|
|
clc
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; comReceiveByte
|
|
;
|
|
; Receive a byte.
|
|
;
|
|
; IN:
|
|
; - nothing
|
|
; OUT:
|
|
; - CFLAG: set if okay, clear otherwise
|
|
; - R16: byte read (if CFLAG set)
|
|
; MODIFIED REGS: R16, R20, R21, R22 (R17)
|
|
|
|
comReceiveByte:
|
|
cbi COM_DDR_DATA, COM_PINNUM_DATA ; set DATA port as input
|
|
cbi COM_PORT_DATA, COM_PINNUM_DATA ; disable internal pullup for DATA
|
|
|
|
ldi r21, 8 ; bits left
|
|
clr r20 ; byte currently receiving
|
|
; wait for startbit
|
|
rcall comWaitForDataLow ; (R17)
|
|
brcc comReceiveByte_error
|
|
Utils_WaitNanoSecs COM_BIT_LENGTH/2, 5, r22 ; goto middle of startbit to maximize sync stability
|
|
comReceiveByte_loop:
|
|
Utils_WaitNanoSecs COM_BIT_LENGTH, 8, r22 ; 8 cycles used in the complete loop between waits
|
|
sec ; +1
|
|
sbic COM_PIN_DATA, COM_PINNUM_DATA ; LOW: +2, HIGH: +1
|
|
rjmp comReceiveByte_shiftIn ; HIGH: +2, rjmp, use set CFLAG
|
|
clc ; LOW: +1
|
|
comReceiveByte_shiftIn:
|
|
ror r20 ; +1
|
|
dec r21 ; +1
|
|
brne comReceiveByte_loop ; +2, sum per loop: 8 cycles
|
|
rcall comWaitForDataHigh ; wait for start of stopbit
|
|
brcc comReceiveByte_error
|
|
mov r16, r20
|
|
sec
|
|
ret
|
|
comReceiveByte_error:
|
|
clc
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; comWaitForDataLow
|
|
;
|
|
; Waits up to COM_MAXWAIT loops for low data line
|
|
; IN:
|
|
; OUT:
|
|
; - CFLAG: set if okay, clear otherwise
|
|
; MODIFIED REGISTERS: r17, r22
|
|
|
|
comWaitForDataLow:
|
|
ldi r17, COM_MAXWAIT
|
|
|
|
comWaitForDataLow_loop:
|
|
sbis COM_PIN_DATA, COM_PINNUM_DATA
|
|
rjmp comWaitForDataLow_done
|
|
Utils_WaitNanoSecs 100, 0, r22 ; wait for 100 nanosecs
|
|
dec r17
|
|
brne comWaitForDataLow_loop
|
|
clc ; timeout
|
|
ret
|
|
|
|
comWaitForDataLow_done:
|
|
sec ; ok
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; comWaitForDataHigh
|
|
;
|
|
; Waits up to COM_MAXWAIT loops for high data line
|
|
; IN:
|
|
; OUT:
|
|
; - CFLAG: set if okay, clear otherwise
|
|
; MODIFIED REGISTERS: r17, r22, X
|
|
|
|
comWaitForDataHigh:
|
|
ldi r17, COM_MAXWAIT
|
|
|
|
comWaitForDataHigh_loop:
|
|
sbic COM_PIN_DATA, COM_PINNUM_DATA
|
|
rjmp comWaitForDataHigh_done
|
|
Utils_WaitNanoSecs 100, 0, r22 ; wait for 100 nanosecs
|
|
dec r17
|
|
brne comWaitForDataHigh_loop
|
|
clc ; timeout
|
|
ret
|
|
|
|
comWaitForDataHigh_done:
|
|
sec ; ok
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; comWaitForAttnHigh
|
|
;
|
|
; Waits up to COM_MAXWAIT loops for high ATTN line
|
|
; IN:
|
|
; OUT:
|
|
; - CFLAG: set if okay, clear otherwise
|
|
; MODIFIED REGISTERS: r17, r22, X
|
|
|
|
comWaitForAttnHigh:
|
|
ldi r17, COM_MAXWAIT
|
|
|
|
comWaitForAttnHigh_loop:
|
|
sbic COM_PIN_ATTN, COM_PINNUM_ATTN
|
|
rjmp comWaitForAttnHigh_done
|
|
Utils_WaitNanoSecs 100, 0, r22 ; wait for 100 nanosecs
|
|
dec r17
|
|
brne comWaitForAttnHigh_loop
|
|
clc ; timeout
|
|
ret
|
|
|
|
comWaitForAttnHigh_done:
|
|
sec ; ok
|
|
ret
|
|
|
|
|
|
|
|
; ***************************************************************************
|
|
; buffer functions
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; COM_BufferAlloc
|
|
;
|
|
; Allocate a transfer buffer.
|
|
; IN:
|
|
; - nothing
|
|
; OUT:
|
|
; - CFLAG: set if okay, clear otherwise
|
|
; - Y: pointer to allocated buffer in SRAM
|
|
; MODIFIED REGISTERS: r16, r17, r21
|
|
|
|
|
|
COM_BufferAlloc:
|
|
in r21, SREG ; save global interrupt enable bit from SREG
|
|
cli
|
|
lds r17, comRecvBuffersUsed
|
|
cpi r17, COM_BUFFER_NUM
|
|
brcc COM_AllocBuffer_error ; no buffer available
|
|
inc r17 ; increment number of buffers used
|
|
sts comRecvBuffersUsed, r17 ; store new value
|
|
lds r16, comRecvBuffersWritePos ; get current write pos
|
|
mov r17, r16 ; increment for next call
|
|
inc r17
|
|
cpi r17, COM_BUFFER_NUM
|
|
brcs COM_AllocBuffer_l1
|
|
clr r17 ; wraparound
|
|
COM_AllocBuffer_l1:
|
|
sts comRecvBuffersWritePos, r17 ; store new writepos for next caller
|
|
rcall COM_BufferPosToY ; (R16, R17)
|
|
clr r17
|
|
std y+COM_BUFFER_OFFS_FLAGS, r17 ; preset flags
|
|
out SREG, r21 ; restore global interrupt enable bit in SREG
|
|
sec
|
|
ret
|
|
COM_AllocBuffer_error:
|
|
out SREG, r21
|
|
clc
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; COM_BufferDeallocBack
|
|
;
|
|
; Release a transfer buffer at the end of the list by decreasing the write pos.
|
|
; This releases the last allocated buffer!
|
|
;
|
|
; IN:
|
|
; - nothing
|
|
; OUT:
|
|
; - CFLAG: set if okay, clear otherwise
|
|
; MODIFIED REGISTERS: r16, r17, r21
|
|
|
|
COM_BufferDeallocBack:
|
|
in r21, SREG ; save global interrupt enable bit from SREG
|
|
cli
|
|
lds r17, comRecvBuffersUsed
|
|
tst r17
|
|
breq COM_BufferDeallocBack_error ; no buffer allocated, nothing to release
|
|
dec r17
|
|
sts comRecvBuffersUsed, r17 ; store new value
|
|
lds r17, comRecvBuffersWritePos
|
|
tst r17
|
|
brne COM_BufferDeallocBack_l1
|
|
ldi r17, COM_BUFFER_NUM ; wrap-around
|
|
COM_BufferDeallocBack_l1:
|
|
dec r17
|
|
sts comRecvBuffersWritePos, r17
|
|
out SREG, r21
|
|
sec
|
|
ret
|
|
COM_BufferDeallocBack_error:
|
|
out SREG, r21
|
|
clc
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; COM_BufferDeallocFront
|
|
;
|
|
; Release a transfer buffer by increasing the read pos.
|
|
;
|
|
; IN:
|
|
; - nothing
|
|
; OUT:
|
|
; - CFLAG: set if okay, clear otherwise
|
|
; MODIFIED REGISTERS: r16, r17, r21
|
|
|
|
COM_BufferDeallocFront:
|
|
in r21, SREG ; save global interrupt enable bit from SREG
|
|
cli
|
|
lds r17, comRecvBuffersUsed
|
|
tst r17
|
|
breq COM_BufferDeallocFront_error ; no buffer allocated, nothing to release
|
|
dec r17
|
|
sts comRecvBuffersUsed, r17 ; store new value
|
|
lds r17, comRecvBuffersReadPos
|
|
inc r17
|
|
cpi r17, COM_BUFFER_NUM
|
|
brcs COM_BufferDeallocFront_l1
|
|
clr r17 ; wrap-around
|
|
COM_BufferDeallocFront_l1:
|
|
sts comRecvBuffersReadPos, r17
|
|
out SREG, r21
|
|
sec
|
|
ret
|
|
COM_BufferDeallocFront_error:
|
|
out SREG, r21
|
|
clc
|
|
ret
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; COM_BufferPosToY
|
|
;
|
|
; Get a pointer to the SRAM position of the given buffer.
|
|
; CAVE: Code must correspond to COM_BUFFER_SIZE!!
|
|
; IN:
|
|
; - R16: buffer number (starting with 0)
|
|
; OUT:
|
|
; - Y: pointer to buffer in SRAM
|
|
; MODIFIED REGISTERS: R16, R17
|
|
|
|
COM_BufferPosToY:
|
|
; calculate offset
|
|
clr r17
|
|
add yl, r16
|
|
adc yh, r17
|
|
|
|
lsl yl
|
|
rol yh ; *2
|
|
lsl yl
|
|
rol yh ; *4
|
|
lsl yl
|
|
rol yh ; *8
|
|
lsl yl
|
|
rol yh ; *16
|
|
; add base position of buffers
|
|
ldi r16, LOW(comRecvBuffers)
|
|
ldi r17, HIGH(comRecvBuffers)
|
|
add yl, r16
|
|
adc yh, r17
|
|
ret
|
|
|
|
|