306 lines
8.5 KiB
NASM
306 lines
8.5 KiB
NASM
; ***************************************************************************
|
|
; copyright : (C) 2023 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. *
|
|
; ***************************************************************************
|
|
|
|
|
|
|
|
; ***************************************************************************
|
|
; defines
|
|
|
|
.equ COM_MAXWAIT_US = 100 ; maximum wait time in microseconds when waiting for rising/falling clock
|
|
|
|
.equ COM_MAINTENANCE_ADDR = 0xf1
|
|
|
|
.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 = 6
|
|
.equ COM_BUFFER_SIZE = 24 ; 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_MSG_OFFS_CMD = 2 ; first at COM_MSG_OFFS_MSGDATA
|
|
.equ COM_MSG_OFFS_SRCADDR = 3
|
|
.equ COM_MSG_OFFS_PAYLOAD = 4 ; payload for the cmd follows here
|
|
|
|
.equ COM_ERR_NOTFORME = 1
|
|
.equ COM_ERR_CHECKSUM = 2
|
|
.equ COM_ERR_IO = 3
|
|
|
|
|
|
; ***************************************************************************
|
|
; data
|
|
|
|
.dseg
|
|
|
|
|
|
comDataBegin:
|
|
comFlags: .byte 1
|
|
comAddress: .byte 1
|
|
comRepeatCount: .byte 1
|
|
comReserved1: .byte 1
|
|
|
|
comStatsPacketsIn: .byte 2
|
|
comStatsPacketsOut: .byte 2
|
|
|
|
comStatsRecvErrs: .byte 2
|
|
comStatsRecvCrcErrs: .byte 2
|
|
comStatsMissed: .byte 2
|
|
comStatsIgnored: .byte 2
|
|
comStatsHandled: .byte 2
|
|
|
|
comStatsCollisions: .byte 2
|
|
comStatsAborted: .byte 2
|
|
|
|
comStatsSendNoBuffer: .byte 2
|
|
comStatsRecvNoBuffer: .byte 2
|
|
|
|
comRecvBuffersReadPos: .byte 1
|
|
comRecvBuffersWritePos: .byte 1
|
|
comRecvBuffersUsed: .byte 1
|
|
comRecvBuffers: .byte (COM_BUFFER_SIZE*COM_BUFFER_NUM)
|
|
comDataEnd:
|
|
|
|
|
|
|
|
; ***************************************************************************
|
|
; code
|
|
|
|
.cseg
|
|
|
|
COM_BEGIN:
|
|
|
|
|
|
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 r18
|
|
push r19
|
|
push r20
|
|
push r21
|
|
push r22
|
|
push xh
|
|
push xl
|
|
push yh
|
|
push yl
|
|
rcall comReceivePacketHandleBuffer ; (R1, R16, R17, R18, R19, R20, R21, R22, X, Y
|
|
pop yl
|
|
pop yh
|
|
pop xl
|
|
pop xh
|
|
pop r22
|
|
pop r21
|
|
pop r20
|
|
pop r19
|
|
pop r18
|
|
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
|
|
|
|
; set address to 0 (will be updated later)
|
|
clr r16
|
|
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
|
|
|
|
ldi r16, (1<<COM_IRQ_GIFR_ATTN) ; clear pending irq by writing 1 to ATTN bit
|
|
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
|
|
|
|
|
|
|
|
; ---------------------------------------------------------------------------
|
|
; 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
|
|
|
|
|
|
|
|
|
|
.include "com_lowlevel.asm"
|
|
.include "com_buffer.asm"
|
|
.include "com_crc.asm"
|
|
.include "com_send.asm"
|
|
.include "com_recv.asm"
|
|
|
|
|
|
|
|
COM_END:
|
|
.equ MODULE_SIZE_COM = COM_END-COM_BEGIN
|
|
|