COM: Transformed to use normal buffers but in kind of a ringbuffer way.

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.
This commit is contained in:
Martin Preuss
2023-01-25 16:28:36 +01:00
parent 31f3e807f0
commit 348d808706
2 changed files with 555 additions and 295 deletions

View File

@@ -10,6 +10,7 @@
.equ COM_BUFFER_FLAGS_DONE = 0x80 .equ COM_BUFFER_FLAGS_DONE = 0x80
.equ COM_BUFFER_FLAGS_RECEIVED = 0x40 .equ COM_BUFFER_FLAGS_RECEIVED = 0x40
.equ COM_BUFFER_FLAGS_TOSEND = 0x20 .equ COM_BUFFER_FLAGS_TOSEND = 0x20
.equ COM_BUFFER_FLAGS_RELEASED = 0x10
.equ COM_BUFFER_FLAGS_PRIO1 = 0x08 .equ COM_BUFFER_FLAGS_PRIO1 = 0x08
.equ COM_BUFFER_FLAGS_PRIO0 = 0x04 .equ COM_BUFFER_FLAGS_PRIO0 = 0x04
.equ COM_BUFFER_FLAGS_IFACE1 = 0x02 .equ COM_BUFFER_FLAGS_IFACE1 = 0x02
@@ -25,6 +26,17 @@
.equ COM_REPEAT_IMPORTANT = 64 .equ COM_REPEAT_IMPORTANT = 64
.equ COM_REPEAT_VITAL = 255 .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 .equ COM_CMD_PING = 1
@@ -35,19 +47,25 @@
comDataBegin: comDataBegin:
comFlags: .byte 1 comFlags: .byte 1
comAddress: .byte 1 comAddress: .byte 1
comRepeatCount: .byte 1 comRepeatCount: .byte 1
comReserved1: .byte 1 comReserved1: .byte 1
comStatsPacketsIn: .byte 2
comStatsPacketsOut: .byte 2 comStatsPacketsIn: .byte 2
comStatsRecvErrs: .byte 2 comStatsPacketsOut: .byte 2
comStatsCollisions: .byte 2
comStatsMissed: .byte 2 comStatsRecvErrs: .byte 2
comStatsAborted: .byte 2 comStatsCollisions: .byte 2
comStatsIgnored: .byte 2 comStatsMissed: .byte 2
comStatsHandled: .byte 2 comStatsAborted: .byte 2
comRingBuffer: .byte RINGBUFFER_OFFS_DATA+COM_RINGBUFFER_SIZE comStatsIgnored: .byte 2
comStatsHandled: .byte 2
comRecvBuffersReadPos: .byte 1
comRecvBuffersWritePos: .byte 1
comRecvBuffersUsed: .byte 1
comRecvBuffers: .byte (COM_BUFFER_SIZE*COM_BUFFER_NUM)
comDataEnd: comDataEnd:
@@ -58,6 +76,39 @@ comDataEnd:
.cseg .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 ; Com_Init
@@ -75,18 +126,15 @@ Com_Init:
ldi r17, (comDataEnd-comDataBegin) ldi r17, (comDataEnd-comDataBegin)
rcall Utils_FillSram rcall Utils_FillSram
; init ringbuffer ldi r16, 1 ; debug: set fixed address "1"
ldi r16, COM_RINGBUFFER_SIZE sts comAddress, r16
ldi yl, LOW(comRingBuffer)
ldi yh, HIGH(comRingBuffer)
rcall RingBuffer_Init
; setup pins and interrupts ; setup pins and interrupts
cbi COM_PORT_DATA, COM_PINNUM_DATA ; disable internal pullup for DATA cbi COM_PORT_DATA, COM_PINNUM_DATA ; disable internal pullup for DATA
sbi COM_DDR_DATA, COM_PINNUM_DATA ; set DATA port as input 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_PORT_ATTN, COM_PINNUM_ATTN ; disable internal pullup for ATTN
sbi COM_DDR_ATTN, COM_PINNUM_ATTN ; set ATTN port as input 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 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 in r16, GIMSK ; enable pin change irq PCIE0 or PCIE1
@@ -111,7 +159,7 @@ Com_Init:
; REGS: (R1, R3, R16, R17, R18, R19, R22, X) ; REGS: (R1, R3, R16, R17, R18, R19, R22, X)
Com_Run: Com_Run:
rcall comHandleNextPacketInRingbuffer ; nothing more than handling packages in ringbuffer rcall comHandleNextPacketInQueue ; nothing more than handling packages in ringbuffer
; clc ; clc
ret ret
@@ -121,75 +169,87 @@ Com_Run:
; Mark a packet as enqueued. ; Mark a packet as enqueued.
; ;
; IN: ; IN:
; - R18: pos pointer inside ring buffer to read from next ; - Y: pointer to buffer containing the enqueued packet
; - R20: priority ; - R20: priority
; OUT: ; OUT:
; - CFLAG: set if okay, clear otherwise ; - CFLAG: set if okay, clear otherwise
; MODIFIED REGS: R10, R11, R12, R15, R16, R20 (R3, R21, R22) ; MODIFIED REGS: R15, R16
COM_EnqueuePacket: COM_EnqueuePacket:
ldi yl, LOW(comRingBuffer)
ldi yh, HIGH(comRingBuffer)
in r15, SREG in r15, SREG
cli cli
ldd r19, y+RINGBUFFER_OFFS_MAXSIZE ldd r16, y+COM_BUFFER_OFFS_FLAGS
; read length
rcall RingBuffer_Read ; (R3, R22)
cpi r16, 3 ; at least 3 bytes?
brcs COM_EnqueuePacket_error ; too few bytes
; read flags
push r18 ; r18 points to flags
rcall RingBuffer_Read ; advances r18 behind flags
pop r18 ; r18 back to flags
; write flags
andi r16, (~(COM_BUFFER_FLAGS_PRIO1 | COM_BUFFER_FLAGS_PRIO0 | COM_BUFFER_FLAGS_RECEIVED | COM_BUFFER_FLAGS_DONE)) & 0xff andi r16, (~(COM_BUFFER_FLAGS_PRIO1 | COM_BUFFER_FLAGS_PRIO0 | COM_BUFFER_FLAGS_RECEIVED | COM_BUFFER_FLAGS_DONE)) & 0xff
or r16, r20 ; add priority or r16, r20 ; add priority
ori r16, COM_BUFFER_FLAGS_TOSEND ori r16, COM_BUFFER_FLAGS_TOSEND
rcall RingBuffer_Write std y+COM_BUFFER_OFFS_FLAGS, r16
out SREG, r15 ; restore IRQ flag out SREG, r15 ; restore IRQ flag
sec sec
ret ret
COM_EnqueuePacket_error:
out SREG, r15 ; restore IRQ flag
; ---------------------------------------------------------------------------
; 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 clc
ret ret
; --------------------------------------------------------------------------- ; ---------------------------------------------------------------------------
; Enqueue a PING packet. ; Enqueue a PING packet.
; ;
; IN: ; IN:
; - R17: destination address ; - R16: destination address
; OUT: ; OUT:
; - CFLAG: set if okay, clear otherwise ; - CFLAG: set if okay, clear otherwise
; MODIFIED REGS: ; MODIFIED REGS: R16, R17, R20, X (R15, Y)
COM_EnqueuePing: COM_EnqueuePing:
ldi yl, LOW(comRingBuffer) push r16
ldi yh, HIGH(comRingBuffer) rcall COM_AllocBufferAndGetXY ; (r16, r17, r21)
ldi r16, 3+2 ; 3 bytes for buffer length, flags and destination address, cmd, source addr pop r16
push r17
rcall RingBuffer_Alloc ; r16: pos of allocated buffer (r16, r17, r18, r19, r20, r21)
pop r17
brcc COM_EnqueuePing_error brcc COM_EnqueuePing_error
; write header stuff clr r17 ; r17: XOR byte
mov r18, r16 ; r18: start of packet in ring buffer ; write header (dest address, msg length)
mov r20, r16 ; r20: start of packet in ring buffer st X+, r16 ; destination address
ldd r19, y+RINGBUFFER_OFFS_MAXSIZE eor r17, r16
ldi r16, 3+2 ldi r16, 2 ; 2 bytes payload
rcall RingBuffer_Write ; write length (r3, r22) st X+, r16
clr r16 eor r17, r16
rcall RingBuffer_Write ; write flags
mov r16, r17
rcall RingBuffer_Write ; write dest addr
; write payload ; write payload
ldi r16, COM_CMD_PING ldi r16, COM_CMD_PING
rcall RingBuffer_Write ; write cmd st X+, r16
eor r17, r16
lds r16, comAddress lds r16, comAddress
rcall RingBuffer_Write ; write source address st X+, r16
mov r18, r20 eor r17, r16
ldi r20, COM_REPEAT_INFO ; store XOR byte
rcall COM_EnqueuePacket 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 brcc COM_EnqueuePing_error
sec sec
ret ret
@@ -200,52 +260,51 @@ COM_EnqueuePing_error:
; --------------------------------------------------------------------------- ; ---------------------------------------------------------------------------
; comHandleNextPacketInRingbuffer ; comHandleNextPacketInQueue
;
; Expects global IRQ disabled.
; ;
; IN: ; IN:
; - nothing ; - nothing
; OUT: ; OUT:
; - CFLAG: set if something done, can be called again immediately (otherwise: wait for timer interrupt and retry) ; - CFLAG: set if something done, can be called again immediately (otherwise: wait for timer interrupt and retry)
; MODIFIED REGS: R1, R16, R17, R18, R19, Y (R1, R3, R16, R17, R18, R19, R22, X) ; MODIFIED REGS: R16, R17, Y (R15, R18, R21, R22, X)
comHandleNextPacketInRingbuffer: comHandleNextPacketInQueue:
; read current packet in ringbuffer (read pointer) lds r16, comRecvBuffersUsed
ldi yl, LOW(comRingBuffer)
ldi yh, HIGH(comRingBuffer)
ldd r16, y+RINGBUFFER_OFFS_USED
tst r16 tst r16
breq comHandleNextPacketInRingbuffer_retNc breq comHandleNextPacketInQueue_retNc ; no buffers in use
ldd r19, y+RINGBUFFER_OFFS_MAXSIZE
ldd r18, y+RINGBUFFER_OFFS_READPOS lds r16, comRecvBuffersReadPos
rcall RingBuffer_Read ; packet length (R3, R22) rcall COM_BufferPosToY ; get current read buffer to Y (R16, R17)
cpi r16, 3 ; at least 3 bytes? ldd r16, y+COM_BUFFER_OFFS_FLAGS ; get flags
brcs comHandleNextPacketInRingbuffer_retNc ; check for released buffer (dealloc)
mov r1, r16 mov r17, r16
rcall RingBuffer_Read ; read flags from packet andi r17, COM_BUFFER_FLAGS_RELEASED ; check for buffer released
ldd r18, y+RINGBUFFER_OFFS_READPOS ; r18 back to read pointer brne comHandleNextPacketInQueue_releaseBuffer
mov r17, r16 ; flags ; check for received packet
andi r17, COM_BUFFER_FLAGS_TOSEND ; check for message to send mov r17, r16
brne comHandleNextPacketInRingbuffer_sendPacket
mov r17, r16 ; check for received message
andi r17, COM_BUFFER_FLAGS_RECEIVED andi r17, COM_BUFFER_FLAGS_RECEIVED
brne comHandleNextPacketInRingbuffer_receivedPacket brne comHandleNextPacketInQueue_receivedPacket
rjmp comHandleNextPacketInRingbuffer_retNc ; check for buffer to send
mov r17, r16
comHandleNextPacketInRingbuffer_sendPacket: andi r17, COM_BUFFER_FLAGS_TOSEND ; check for message to send
rcall comSendPacketHandleRepeat ; (R1, R3, R16, R17, R18, R19, R22, X) brne comHandleNextPacketInQueue_sendPacket
ret ; use CFLAG from subroutine ; nothing to do (e.g. buffer not ready to be sent)
rjmp comHandleNextPacketInQueue_retNc
comHandleNextPacketInRingbuffer_receivedPacket: comHandleNextPacketInQueue_sendPacket:
rcall comSendPacketHandleRepeat ; (R15, R16, R17, R18, R21, R22, X)
ret ; use CFLAG from subroutine
comHandleNextPacketInQueue_receivedPacket:
clr r17 clr r17
sts comRepeatCount, r17 ; set comRepeatCount to zero sts comRepeatCount, r17 ; set comRepeatCount to zero
rcall comHandleReceivedPacket rcall comHandleReceivedPacket ; (r16, r17, r21, X)
sec ; always return with set CFLAG sec ; always return with set CFLAG
ret ret
comHandleNextPacketInQueue_releaseBuffer:
comHandleNextPacketInRingbuffer_retNc: rcall COM_BufferDeallocFront
sec ; always return with set CFLAG
ret
comHandleNextPacketInQueue_retNc:
clc clc
ret ret
@@ -255,17 +314,13 @@ comHandleNextPacketInRingbuffer_retNc:
; comHandleReceivedPacket ; comHandleReceivedPacket
; ;
; IN: ; IN:
; - nothing ; - Y: pointer to current buffer (pointed to by comRecvBuffersReadPos)
; OUT: ; OUT:
; - nothing ; - nothing
; MODIFIED REGS: X, (R3, R22) ; MODIFIED REGS: X (r16, r17, r21)
comHandleReceivedPacket: comHandleReceivedPacket:
ldi yl, LOW(comRingBuffer)
ldi yh, HIGH(comRingBuffer)
ldd r19, y+RINGBUFFER_OFFS_MAXSIZE
ldd r18, y+RINGBUFFER_OFFS_READPOS
rcall onPacketReceived rcall onPacketReceived
brcs comHandleReceivedPacket_l1 brcs comHandleReceivedPacket_l1
ldi xl, LOW(comStatsIgnored) ldi xl, LOW(comStatsIgnored)
@@ -275,11 +330,7 @@ comHandleReceivedPacket_l1:
ldi xl, LOW(comStatsHandled) ldi xl, LOW(comStatsHandled)
ldi xh, HIGH(comStatsHandled) ldi xh, HIGH(comStatsHandled)
comHandleReceivedPacket_l2: comHandleReceivedPacket_l2:
ldi yl, LOW(comRingBuffer) rcall comDeallocReadBufAndIncrCounter ; (r16, r17, r21)
ldi yh, HIGH(comRingBuffer)
ldd r19, y+RINGBUFFER_OFFS_MAXSIZE
ldd r18, y+RINGBUFFER_OFFS_READPOS
rcall comDeallocReadBufAndIncrCounter ; (r16, r17, r18, r19, r20, r21)
ret ret
@@ -288,49 +339,46 @@ comHandleReceivedPacket_l2:
; comSendPacketHandleRepeat ; comSendPacketHandleRepeat
; ;
; IN: ; IN:
; - R18: pos pointer inside ring buffer to read from next ; - Y: pointer to current buffer (pointed to by comRecvBuffersReadPos)
; - R19: maximum size of the ringbuffer (for wrap-around)
; - Y : ringbuffer
; OUT: ; OUT:
; - CFLAG: set if something done, can be called again immediately (otherwise: wait for timer interrupt and retry) ; - CFLAG: set if something done, can be called again immediately (otherwise: wait for timer interrupt and retry)
; MODIFIED REGS: R1, R15, R16, R17, R18, R19, X, (R3, R22) ; MODIFIED REGS: R15, R17, R22, X (R16, R17, R18, R21, R22)
comSendPacketHandleRepeat: comSendPacketHandleRepeat:
in r15, SREG in r15, SREG
cli cli
push r18 ldd r16, y+COM_BUFFER_OFFS_FLAGS
rcall RingBuffer_Read ; packet length (R3, R22)
mov r1, r16 ; r1: ringbuffer packet length
rcall RingBuffer_Read ; flags
pop r18
rcall comSetupRepeat ; setup comRepeatCount if not already done (R16, R17) rcall comSetupRepeat ; setup comRepeatCount if not already done (R16, R17)
; sbis COM_PIN_ATTN, COM_PINNUM_ATTN ; check ATTN: low? cbi COM_PORT_ATTN, COM_PINNUM_ATTN ; set ATTN low
; rjmp comSendPacketHandleRepeat_adjustRepeat ; yes, line is busy, retry later sbi COM_DDR_ATTN, COM_PINNUM_ATTN ; set ATTN as output
push r18 Utils_WaitNanoSecs COM_BIT_LENGTH, 0, r22 ; wait for one bit duration
cbi COM_PORT_ATTN, COM_PINNUM_ATTN ; set ATTN low rcall comSendPacketHandleBuffer ; (R16, R17, R21, R22)
sbi COM_DDR_ATTN, COM_PINNUM_ATTN ; set ATTN as output cbi COM_DDR_ATTN, COM_PINNUM_ATTN ; release ATTN line
Utils_WaitNanoSecs COM_BIT_LENGTH, 0, r22 ; wait for one bit duration
rcall comSendPacketRaw ; (R3, R10, R11, R12, R16, R20 R21, R22)
cbi COM_DDR_ATTN, COM_PINNUM_ATTN ; release ATTN line
pop r18
brcc comSendPacketHandleRepeat_adjustRepeat brcc comSendPacketHandleRepeat_adjustRepeat
; packet sent, adjust stats ; packet sent, adjust stats, release buffer
mov r16, r1
ldi xl, LOW(comStatsPacketsOut) ldi xl, LOW(comStatsPacketsOut)
ldi xh, HIGH(comStatsPacketsOut) ldi xh, HIGH(comStatsPacketsOut)
rcall comDeallocReadBufAndIncrCounter ; (r16, r17, r18) rcall comDeallocReadBufAndIncrCounter ; (r16, r17, r18)
rjmp comSendPacketHandleRepeat_retC rjmp comSendPacketHandleRepeat_retC
comSendPacketHandleRepeat_adjustRepeat: 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 lds r17, comRepeatCount
cpi r17, COM_REPEAT_VITAL cpi r17, COM_REPEAT_VITAL
breq comSendPacketHandleRepeat_retNC ; vital message, repeat forever breq comSendPacketHandleRepeat_retNC ; vital message, repeat forever
dec r17 dec r17
sts comRepeatCount, r17 sts comRepeatCount, r17
brne comSendPacketHandleRepeat_retNC brne comSendPacketHandleRepeat_retNC
; dealloc buffer, inc abort counter
; dealloc buffer, inc dismiss counter
mov r16, r1
ldi xl, LOW(comStatsAborted) ldi xl, LOW(comStatsAborted)
ldi xh, HIGH(comStatsAborted) ldi xh, HIGH(comStatsAborted)
rcall comDeallocReadBufAndIncrCounter rcall comDeallocReadBufAndIncrCounter
@@ -352,8 +400,7 @@ comSendPacketHandleRepeat_retC:
; comSetupRepeat ; comSetupRepeat
; ;
; IN: ; IN:
; - R16: pos pointer inside ring buffer to read from next ; - R16: priority
; - R20: priority
; OUT: ; OUT:
; - CFLAG: set if okay, clear otherwise ; - CFLAG: set if okay, clear otherwise
; MODIFIED REGS: R16, R17 ; MODIFIED REGS: R16, R17
@@ -391,162 +438,194 @@ comSetupRepeat_l99:
; comDeallocReadBufAndIncrCounter ; comDeallocReadBufAndIncrCounter
; ;
; IN: ; IN:
; - r16: num of bytes to dealloc
; - X : pointer to counter ; - X : pointer to counter
; - Y : ring buffer
; OUT: ; OUT:
; - nothing ; - nothing
; REGS: r16, r17, r18 (r19, r20, r21) ; REGS: r16, r17, r21
comDeallocReadBufAndIncrCounter: comDeallocReadBufAndIncrCounter:
rcall RingBuffer_DeallocRead ; (r17, r18, r19, r20, r21) rcall COM_BufferDeallocFront ; (r16, r17, r21)
clr r18 clr r21
ld r16, x+ ld r16, x+
ld r17, x ld r17, x
inc r16 inc r16
adc r17, r18 adc r17, r21
st -x, r17 st -x, r17
st x, r16 st x, r16
sts comRepeatCount, r18 ; set comRepeatCount to zero sts comRepeatCount, r21 ; set comRepeatCount to zero
ret ret
; --------------------------------------------------------------------------- ; ---------------------------------------------------------------------------
; comSendPacketRaw ; comSendPacketHandleBuffer
; ;
; Send a packet. (TODO: input buffer in x, length in r16) ; 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: ; IN:
; - R18: pos pointer inside ring buffer to read from next ; - Y : pointer to current read buffer
; OUT: ; OUT:
; - CFLAG: set if okay, clear otherwise ; - CFLAG: set if okay, clear otherwise
; MODIFIED REGS: R10, R11, R16 (R3, R21, R22) ; MODIFIED REGS: R16, R17 (R21, R22)
comSendPacketRaw: comSendPacketHandleBuffer:
ldi yl, LOW(comRingBuffer) mov xl, yl
ldi yh, HIGH(comRingBuffer) mov xh, yh
ldd r19, y+RINGBUFFER_OFFS_MAXSIZE ldi r16, COM_BUFFER_OFFS_DATA
rcall RingBuffer_Read ; read entry length from buffer (advances r18) (R3, R22) clr r17
cpi r16, 3 ; at least 3 bytes? add xl, r16
brcs comSendPacketRaw_error ; too few bytes adc xh, r17
mov r10, r16 ; r10: number of bytes at current ringbuffer pos ldd r16, y+(COM_BUFFER_OFFS_DATA+COM_MSG_OFFS_MSGLEN) ; get msg payload length
dec r10 ldi r17, 3
dec r10 add r16, r17 ; add dest addr, msg len and XOR byte
dec r10 ; r10: number of bytes in message rcall comSendPacketFromSram ; send all that
clr r11 ; r11: XOR checksum brcc comSendPacketHandleBuffer_error
rcall RingBuffer_Read ; read flags from buffer (ignore) ldd r16, y+COM_BUFFER_OFFS_FLAGS
rcall RingBuffer_Read ; read dest address from buffer ori r16, COM_BUFFER_FLAGS_DONE
eor r11, r16 ; calculate checksum std y+COM_BUFFER_OFFS_FLAGS, r16
rcall comSendByte ; send destination address (R16, R21, R22) sec
brcc comSendPacketRaw_error ret
mov r16, r10 ; send msg length comSendPacketHandleBuffer_error:
eor r11, r16 ; calculate checksum clc
rcall comSendByte ; send msg length ret
brcc comSendPacketRaw_error
tst r10 ; payload?
breq comSendPacketRaw_sendCrc ; no payload, go send checksum ; ---------------------------------------------------------------------------
comSendPacketRaw_loop: ; comSendPacketFromSram
rcall RingBuffer_Read ; read byte from buffer ;
eor r11, r16 ; calculate checksum ; Send a packet from SRAM
rcall comSendByte ; send byte ;
brcc comSendPacketRaw_error ; IN:
dec r10 ; - R16: number of bytes to send
brne comSendPacketRaw_loop ; - X: pointer to buffer to read from
comSendPacketRaw_sendCrc: ; OUT:
mov r16, r11 ; send checksum ; - CFLAG: set if okay, clear otherwise
rcall comSendByte ; send byte ; MODIFIED REGS: R16, R17 (R21, R22)
brcc comSendPacketRaw_error
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 sec
ret ret
comSendPacketRaw_error: comSendPacketFromSram_error:
clc clc
ret ret
; --------------------------------------------------------------------------- ; ---------------------------------------------------------------------------
; comReceivePacket ; comReceivePacketHandleBuffer
;
; Receive a packet. If we are the recipient of the packet then space will be allocated inside the
; given ringbuffer and the received packet will be stored there.
;
; Packages are stored in the buffer like this:
; - 1 byte : buffer size
; - 1 byte: flags (e.g. COM_BUFFER_FLAGS_RECEIVED)
; - 1 byte : destination address
; - n bytes: packet (i.e. buffer size -3 bytes)
; ;
; 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: ; IN:
; - nothing ; - nothing
; OUT: ; OUT:
; - CFLAG: set if okay, clear otherwise ; - CFLAG: set if okay, cleared otherwise
; MODIFIED REGS: R1, R2, R3, R16, R17, R18, R19 (R20, R21, R22, XL, XH) ; MODIFIED REGISTERS: R16, R17, X, Y (R1, R20, R21, R22)
comReceivePacket: comReceivePacketHandleBuffer:
ldi yl, LOW(comRingBuffer) rcall COM_BufferAlloc
ldi yh, HIGH(comRingBuffer) brcc comReceivePacketHandleBuffer_error
clr r1 ; r1: checksum ; get pos of data portion for the allocated buffer
; read destination address mov xl, yl
rcall comReceiveByte ; read byte mov xh, yh
brcc comReceivePacket_error ldi r16, COM_BUFFER_OFFS_DATA
; compare destination address (accept "0" and own address) clr r17
tst r16 add xl, r16
breq comReceivePacket_acceptAddr adc xh, r17
lds r17, comAddress rcall comReceivePacketToSram ; (r1, r16, r17, R20, R21, R22, X)
cp r16, r17 brcc comReceivePacketHandleBuffer_dealloc
breq comReceivePacket_acceptAddr ; handle buffer flags
clc ; not for me ldi r16, COM_BUFFER_FLAGS_RECEIVED
ret std y+COM_BUFFER_OFFS_FLAGS, r16
comReceivePacket_acceptAddr:
mov r3, r16 ; r3: destination address (maybe we need to forward the packet)
eor r1, r16
rcall comReceiveByte ; read packet length (R16, R17, R20, R21, R22)
brcc comReceivePacket_error
; alloc ring buffer
mov r17, r16 ; r17: packet length
inc r16 ; packet length bytes + length byte
inc r16 ; + flags
inc r16 ; + dest addr
mov r2, r16 ; r2: number of bytes allocated in ringbuffer
push r17
rcall RingBuffer_Alloc ; (r16, r17, r18, r19, r20, r21)
pop r17
brcc comReceivePacket_error
mov r18, r16 ; r18: pos in ring buffer
ldd r19, y+RINGBUFFER_OFFS_MAXSIZE ; max size
mov r16, r2 ; write number of bytes allocated to ringbuffer
ori r16, COM_BUFFER_FLAGS_RECEIVED
rcall RingBuffer_Write ; (r3, r22)
ldi r16, COM_BUFFER_FLAGS_RECEIVED ; write flags to ringbuffer
rcall RingBuffer_Write ; (r3, r22)
mov r16, r3 ; write destination address for packet we saved earlier
rcall RingBuffer_Write ; (r3, r22)
; read packet (except XOR byte, that will be read later)
comReceivePacket_loop1:
rcall comReceiveByte ; (R16, R17, R20, R21, R22)
brcc comReceivePacket_error_release_buffer
eor r1, r16
rcall RingBuffer_Write ; (r3, r22)
dec r17
brne comReceivePacket_loop1
; read XOR byte, don't store
rcall comReceiveByte ; (R16, R17, R20, R21, R22)
brcc comReceivePacket_error
eor r1, r16
brne comReceivePacket_error_release_buffer ; XOR should be 0 here, otherwise error
sec sec
ret ret
comReceivePacket_error_release_buffer:
mov r16, r2 ; number of bytes allocated in ringbuffer comReceivePacketHandleBuffer_dealloc:
rcall RingBuffer_DeallocWrite ; (r17, r18, r19, r20, r21) rcall COM_BufferDeallocBack ; (r16, r17, r21)
comReceivePacket_error: comReceivePacketHandleBuffer_error:
clc clc
ret 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 ; comSendByte
@@ -611,12 +690,13 @@ comSendByte_error:
; MODIFIED REGS: R16, R20, R21, R22 (R17) ; MODIFIED REGS: R16, R20, R21, R22 (R17)
comReceiveByte: comReceiveByte:
sbi COM_DDR_DATA, COM_PINNUM_DATA ; set DATA port as input cbi COM_DDR_DATA, COM_PINNUM_DATA ; set DATA port as input
cbi COM_PORT_DATA, COM_PINNUM_DATA ; disable internal pullup for DATA cbi COM_PORT_DATA, COM_PINNUM_DATA ; disable internal pullup for DATA
ldi r21, 8 ; bits left ldi r21, 8 ; bits left
clr r20 ; byte currently receiving clr r20 ; byte currently receiving
; wait for startbit ; wait for startbit
rcall comWaitForDataLow rcall comWaitForDataLow ; (R17)
brcc comReceiveByte_error brcc comReceiveByte_error
Utils_WaitNanoSecs COM_BIT_LENGTH/2, 5, r22 ; goto middle of startbit to maximize sync stability Utils_WaitNanoSecs COM_BIT_LENGTH/2, 5, r22 ; goto middle of startbit to maximize sync stability
comReceiveByte_loop: comReceiveByte_loop:
@@ -630,7 +710,7 @@ comReceiveByte_shiftIn:
dec r21 ; +1 dec r21 ; +1
brne comReceiveByte_loop ; +2, sum per loop: 8 cycles brne comReceiveByte_loop ; +2, sum per loop: 8 cycles
rcall comWaitForDataHigh ; wait for start of stopbit rcall comWaitForDataHigh ; wait for start of stopbit
; brcc comReceiveByte_error brcc comReceiveByte_error
mov r16, r20 mov r16, r20
sec sec
ret ret
@@ -647,7 +727,7 @@ comReceiveByte_error:
; IN: ; IN:
; OUT: ; OUT:
; - CFLAG: set if okay, clear otherwise ; - CFLAG: set if okay, clear otherwise
; MODIFIED REGISTERS: r17, r22, X ; MODIFIED REGISTERS: r17, r22
comWaitForDataLow: comWaitForDataLow:
ldi r17, COM_MAXWAIT ldi r17, COM_MAXWAIT
@@ -655,6 +735,7 @@ comWaitForDataLow:
comWaitForDataLow_loop: comWaitForDataLow_loop:
sbis COM_PIN_DATA, COM_PINNUM_DATA sbis COM_PIN_DATA, COM_PINNUM_DATA
rjmp comWaitForDataLow_done rjmp comWaitForDataLow_done
Utils_WaitNanoSecs 100, 0, r22 ; wait for 100 nanosecs
dec r17 dec r17
brne comWaitForDataLow_loop brne comWaitForDataLow_loop
clc ; timeout clc ; timeout
@@ -681,6 +762,7 @@ comWaitForDataHigh:
comWaitForDataHigh_loop: comWaitForDataHigh_loop:
sbic COM_PIN_DATA, COM_PINNUM_DATA sbic COM_PIN_DATA, COM_PINNUM_DATA
rjmp comWaitForDataHigh_done rjmp comWaitForDataHigh_done
Utils_WaitNanoSecs 100, 0, r22 ; wait for 100 nanosecs
dec r17 dec r17
brne comWaitForDataHigh_loop brne comWaitForDataHigh_loop
clc ; timeout clc ; timeout
@@ -692,8 +774,182 @@ comWaitForDataHigh_done:
; ---------------------------------------------------------------------------
; 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

View File

@@ -19,8 +19,6 @@
.equ COM_BIT_LENGTH = 52000 ; 104000=9600, 52000=19200, 26000=38400 .equ COM_BIT_LENGTH = 52000 ; 104000=9600, 52000=19200, 26000=38400
.equ COM_RINGBUFFER_SIZE = 32 ; 32 bytes for now
.equ COM_DDR_DATA = DDRA .equ COM_DDR_DATA = DDRA
.equ COM_PORT_DATA = PORTA .equ COM_PORT_DATA = PORTA
.equ COM_PIN_DATA = PINA .equ COM_PIN_DATA = PINA
@@ -52,7 +50,7 @@
rjmp main ; Reset vector rjmp main ; Reset vector
reti ; EXT_INT0 reti ; EXT_INT0
reti ; PCI0 rjmp comIsrPcint0 ; PCI0
reti ; PCI1 reti ; PCI1
reti ; WATCHDOG reti ; WATCHDOG
reti ; ICP1 reti ; ICP1
@@ -74,7 +72,6 @@
; includes ; includes
.include "utils.asm" .include "utils.asm"
.include "ringbuffer.asm"
.include "timer.asm" .include "timer.asm"
.include "led.asm" .include "led.asm"
.include "com.asm" .include "com.asm"
@@ -262,14 +259,13 @@ onEverySecond:
; USED: depending on called routines ; USED: depending on called routines
onEvery10s: onEvery10s:
in r15, SREG ; debug ; in r15, SREG ; debug
cli ; cli
push r15 ; push r15
ldi r17, 219 ; ldi r16, 219
rcall COM_EnqueuePing ; rcall COM_EnqueuePing
; rcall comHandleNextPacketInRingbuffer ; pop r15
pop r15 ; out SREG, r15
out SREG, r15
ret ret
@@ -286,8 +282,6 @@ onEvery10s:
; USED: depending on called routines ; USED: depending on called routines
onEveryMinute: onEveryMinute:
sbi DDRA, PORTA2 ; debug
sbi PINA, PORTA2 ; debug (toggle)
ret ret
@@ -299,13 +293,14 @@ onEveryMinute:
; ;
; The packet will be removed from buffer in any case after return from this call. ; The packet will be removed from buffer in any case after return from this call.
; IN: ; IN:
; - R18: pos of packet in ringbuffer ; - Y : pointer to received buffer
; - Y : pointer to ringbuffer
; OUT: ; OUT:
; - CFLAG: set if handled, cleared otherwise ; - CFLAG: set if handled, cleared otherwise
; USED: depending on called routines ; USED: depending on called routines
onPacketReceived: onPacketReceived:
sbi DDRA, PORTA2 ; debug
sbi PINA, PORTA2 ; debug (toggle)
clc ; not handled clc ; not handled
ret ret
@@ -316,33 +311,42 @@ onPacketReceived:
debugSendByte: debugSendByte:
in r15, SREG ; debug push r15
cli in r15, SREG ; debug
cli
push r17
push r22
ldi r17, 8
sbi DDRA, PORTA2 ; debug
cbi PORTA, PORTA2 ; debug (on)
Utils_WaitNanoSecs 100000, 0, r22 ; start with 2t low
ldi r17, 8 sbi PORTA, PORTA2 ; debug (off)
sbi DDRA, PORTA2 ; debug nop
nop
cbi PORTA, PORTA2 ; debug (on) cbi PORTA, PORTA2 ; debug (on)
Utils_WaitNanoSecs 200000, 0, r22 ; start with 2t low Utils_WaitNanoSecs 100000, 0, r22 ; start with 2t low
debugSendByte_loop: debugSendByte_loop:
lsr r16 lsr r16
brcs debugSendByte_sendLow brcs debugSendByte_sendLow
cbi PORTA, PORTA2 ; debug (on) cbi PORTA, PORTA2 ; debug (on)
rjmp debugSendByte_wait rjmp debugSendByte_wait
debugSendByte_sendLow: debugSendByte_sendLow:
sbi PORTA, PORTA2 ; debug (off) sbi PORTA, PORTA2 ; debug (off)
debugSendByte_wait: debugSendByte_wait:
Utils_WaitNanoSecs 100000, 0, r22 Utils_WaitNanoSecs 100000, 0, r22
dec r17 dec r17
brne debugSendByte_loop brne debugSendByte_loop
cbi PORTA, PORTA2 ; debug (on) cbi PORTA, PORTA2 ; debug (on)
Utils_WaitNanoSecs 200000, 0, r22 ; end with 2t low Utils_WaitNanoSecs 200000, 0, r22 ; end with 2t low
sbi PORTA, PORTA2 ; debug (off) sbi PORTA, PORTA2 ; debug (off)
pop r22
pop r17
out SREG, r15 out SREG, r15
pop r15
ret ret