avr: started reworking COM module.

- sending and receiving now basically works again, but too often the
  read buffer is in use when trying to receive a message.
This commit is contained in:
Martin Preuss
2023-04-12 15:30:38 +02:00
parent da6b7da501
commit 18d34450e7
21 changed files with 1816 additions and 1926 deletions

View File

@@ -197,8 +197,7 @@ Offset Length Meaning
4 4 UID of the sending node
8 2 packets out
10 2 collisions
12 2 aborted
14 2 no buffer errors
12 2 line busy errors
@@ -214,11 +213,9 @@ Offset Length Meaning
---------------------------------------------------------
4 4 UID of the sending node
8 2 packets in
10 2 crc errors
10 2 content errors (invalid msg length, CRC errors)
12 2 io errors
14 2 no buffer errors
16 2 handled packets
18 2 missed

View File

@@ -61,9 +61,10 @@
#define MODULES_TIMER
#define MODULES_COM
;#define MODULES_COM_WITH_ADDR_PROTO
#define MODULES_LED
#define MODULES_TWI_MASTER
;#define MODULES_LCD
#define MODULES_LCD
#define MODULES_SI7021
@@ -199,7 +200,7 @@
rjmp main ; Reset vector
reti ; EXT_INT0
rjmp comIsrPcint0 ; PCI0
rjmp com2IsrPcint0 ; PCI0
reti ; PCI1
reti ; WATCHDOG
reti ; ICP1
@@ -222,18 +223,14 @@
.include "utils.asm"
.include "timer.asm"
.include "led.asm"
.include "com.asm"
.include "com2.asm"
.include "comproto.asm"
.include "comproto_addr.asm"
.include "comproto_stats.asm"
.include "comproto_device.asm"
.include "comproto_memstats.asm"
.include "comproto_sysstats.asm"
.include "comproto_values.asm"
;.include "comproto_debug.asm"
;.include "comproto_twi.asm"
.include "comproto_recvstats.asm"
.include "comproto_pong.asm"
;.include "comproto_values.asm"
.include "twimaster.asm"
;.include "lcd.asm"
.include "lcd.asm"
.include "si7021.asm"
@@ -250,7 +247,7 @@ sramTimerEnqueueMemStats: .byte 2
sramTimerEnqueueSysStats: .byte 2
sramTimerEnqueueValues: .byte 2
sramTimerSI7021Measure: .byte 2
sramPeriodicalLcdMark: .byte 2
; ***************************************************************************
@@ -271,12 +268,13 @@ blinkPattern: .db 2, 50, 0xff, 0xff ; 1 short blink, 2s pause, restart
timerList:
; SRAM variable/counter routine flags secs (0=don't start or restart)
.dw sramTimerProtocolEverySec, CPRO_OnEverySecond, 0, 1 ; every 1s
.dw sramTimerEnqueueComStats, enqueueComStats, TIMER_FLAGS_IF_ADDR, 300 ; every 5m
.dw sramTimerEnqueueMemStats, enqueueMemStats, TIMER_FLAGS_IF_ADDR, 300 ; every 5m
.dw sramTimerEnqueueSysStats, enqueueSysStats, TIMER_FLAGS_IF_ADDR, 60 ; every 60s
.dw sramTimerSI7021Measure, SI7021_PeriodicMeasurement, 0, 30 ; every 30s
.dw sramTimerEnqueueValues, Main_SendValueMsg, TIMER_FLAGS_IF_ADDR, 60 ; every 1m
#ifdef MODULES_COM_WITH_ADDR_PROTO
; .dw cproAddresModeTimer, CPRO_Address_OnTimer, 0, 0 ; (no restart)
#endif
.dw sramTimerEnqueueComStats, enqueueComStats, TIMER_FLAGS_IF_ADDR, 10 ; every 30s
.dw sramPeriodicalLcdMark, periodicalLcdMark, 0, 1 ; every sec
; .dw sramTimerSI7021Measure, SI7021_PeriodicMeasurement, 0, 30 ; every 30s
; .dw sramTimerEnqueueValues, Main_SendValueMsg, TIMER_FLAGS_IF_ADDR, 60 ; every 1m
.dw 0 ; end of list
@@ -290,33 +288,51 @@ timerList:
; Called on first time run, i.e. on system start. No arguments, no results.
onSystemStart:
; todo: setup once timer to start reclaiming address
rcall CPRO_StartReclaimAddrProcedure
ldi r16, 2 ; DEBUG: set static address
sts com2Address, r16
; rcall printStartSendPackage
; ldi r16, 0xff ; send to everybody
; ldi xl, LOW(com2SendBuffer)
; ldi xh, HIGH(com2SendBuffer)
; rcall CPRO_WriteComRecvStats
; rcall printStartSendPackage
; rcall COM2_SendPacket
; rcall printEndSendPackage
; rcall printSendStats
ret
periodicalLcdMark:
rcall printTimerMark
ret
enqueueComStats:
rcall printSendStats
ldi r16, 0xff ; send to everybody
rcall CPRO_EnqueueComSendStats
ldi r16, 0xff ; send to everybody
rjmp CPRO_EnqueueComRecvStats
ldi xl, LOW(com2SendBuffer)
ldi xh, HIGH(com2SendBuffer)
rcall CPRO_WriteComRecvStats
rjmp COM2_SendPacket
ret
;enqueueMemStats:
; ldi r16, 0xff ; send to everybody
; rcall CPRO_EnqueueMemStats
enqueueMemStats:
ldi r16, 0xff ; send to everybody
rcall CPRO_EnqueueMemStats
ldi r16, 0xff ; send to everybody
rjmp CPRO_EnqueueDevice
; ldi r16, 0xff ; send to everybody
; rjmp CPRO_EnqueueDevice
enqueueSysStats:
ldi r16, 0xff ; send to everybody
rjmp CPRO_EnqueueSysStats
;enqueueSysStats:
; ldi r16, 0xff ; send to everybody
; rjmp CPRO_EnqueueSysStats
@@ -344,15 +360,17 @@ onEvery100ms:
;
; Called after a packet was received via COM module. Add your routine calls here.
;
; The packet will be removed from buffer in any case after return from this call.
; The packet will be released in any case after return from this call.
; IN:
; - Y : pointer to received buffer
; - X : pointer to received buffer
; OUT:
; - CFLAG: set if handled, cleared otherwise
; USED: depending on called routines
onPacketReceived:
rcall CPRO_OnPacketReceived
; rcall CPRO_OnPacketReceived
sbi PINA, PORTA2 ; debug (toggle)
ret

View File

@@ -1,313 +0,0 @@
; ***************************************************************************
; 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
comInterrupts: .byte 2
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
comMaxBuffersUsed: .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
lds xl, comInterrupts
lds xh, comInterrupts+1
adiw xh:xl, 1
sts comInterrupts, xl
sts comInterrupts+1, xh
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

804
avr/com2.asm Normal file
View File

@@ -0,0 +1,804 @@
; ***************************************************************************
; 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 COM2_BUFFER_SIZE = 24
.equ COM2_MAXWAIT_US = 100 ; maximum wait time in microseconds when waiting for rising/falling clock
.equ COM2_MAINTENANCE_ADDR = 0xc1
.equ COM2_CRC_POLYNOMIAL = 0x97
; flags for variable payload enqueue function
.equ COM2_PAYLOAD_FLAGS_SECONDS = 0x01
.equ COM2_PAYLOAD_FLAGS_UID = 0x02
.equ COM2_PAYLOAD_FLAGS_RESERVED1 = 0x04
.equ COM2_PAYLOAD_FLAGS_NUM0 = 0x08
.equ COM2_PAYLOAD_FLAGS_NUM1 = 0x10
.equ COM2_PAYLOAD_FLAGS_NUM2 = 0x20
.equ COM2_PAYLOAD_FLAGS_NUM3 = 0x40
.equ COM2_PAYLOAD_FLAGS_NUM4 = 0x80
.equ COM2_PAYLOAD_FLAGS_SHIFT_NUM = 3
.equ COM2_MSG_OFFS_DESTADDR = 0
.equ COM2_MSG_OFFS_MSGLEN = 1
.equ COM2_MSG_OFFS_MSGDATA = 2
.equ COM2_MSG_OFFS_CMD = 2 ; first at COM2_MSG_OFFS_MSGDATA
.equ COM2_MSG_OFFS_SRCADDR = 3
.equ COM2_MSG_OFFS_PAYLOAD = 4 ; payload for the cmd follows here
; ***************************************************************************
; data
.dseg
com2DataBegin:
com2Address: .byte 1
com2Interrupts: .byte 2
com2StatsPacketsIn: .byte 2
com2StatsPacketsOut: .byte 2
com2StatsIoError: .byte 2
com2StatsContentError: .byte 2
com2StatsNoBufferError: .byte 2
com2StatsBusyError: .byte 2
com2StatsCollisions: .byte 2
com2RecvBuffer: .byte COM2_BUFFER_SIZE
com2SendBuffer: .byte COM2_BUFFER_SIZE
com2DataEnd:
; ***************************************************************************
; code
.cseg
COM2_BEGIN:
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Module interface
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ---------------------------------------------------------------------------
; Com2_Init
;
; IN:
; OUT:
; - CFLAG: set if okay, clear on error
; USED: R16, R17, X, Y
Com2_Init:
; preset SRAM data area
ldi xh, HIGH(com2DataBegin)
ldi xl, LOW(com2DataBegin)
clr r16
ldi r17, (com2DataEnd-com2DataBegin)
rcall Utils_FillSram
; set address to 0 (will be updated later)
clr r16
sts com2Address, 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)
COM2_Run:
lds r16, com2RecvBuffer
tst r16
brne COM2_Run_packetReceived
clc
ret
COM2_Run_packetReceived:
ldi xl, LOW(com2RecvBuffer)
ldi xh, HIGH(com2RecvBuffer)
rcall onPacketReceived
clr r16
sts com2RecvBuffer, r16 ; unlock buffer
sec
ret
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Preparing messages
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ---------------------------------------------------------------------------
; Write a simple packet into the given buffer with payload being only CMD and source address.
;
; IN:
; - R16: destination address
; - R18: command (e.g. CPRO_CMD_PING or CPRO_CMD_PONG)
; - X : pointer to buffer to write to
; OUT:
; - CFLAG: set if okay, clear otherwise
; MODIFIED REGS: R16, R17, X, Y (R3, R4, R15, R16, R17, R18, R19, R20, R21)
COM2_WriteMsgWithCmdAndSrcAddr:
ldi r17, COM2_PAYLOAD_FLAGS_SECONDS
push xh
push xl
rcall COM2_BeginMsgWithVariablePayload ; (R3, R4, R16, R17, R18, R19, R20, R21, X)
pop xl
pop xh
rcall com2CalcAndAddChecksumByte ; (R16, R17, R18, R19, X)
sec
ret
COM2_WriteMsgWithCmdAndSrcAddr_error:
clc
ret
; ---------------------------------------------------------------------------
; begin packet with variable payload.
;
; IN:
; - R16: destination address
; - R17: flags
; - R18: command (e.g. CPRO_CMD_PING)
; - X : pointer to packet buffer
; OUT:
; - X : points to end of packet as it was written so far
; MODIFIED REGS: R3, R16, R17, R18, R19, R20, R21, X (R4)
COM2_BeginMsgWithVariablePayload:
; write header (dest address, msg length)
st X+, r16 ; destination address
mov r16, r17 ; calculate payload size
mov r3, r17
rcall com2CalcPayloadSize ; (R4, R16, R17)
inc r16 ; add CMD byte
inc r16 ; add source address byte
st X+, r16
; write payload
st X+, r18 ; 0: CMD
lds r16, com2Address ; 1: source address
st X+, r16
lsr r3 ; shift out COM2_PAYLOAD_FLAGS_SECONDS
brcc COM2_BeginMsgWithVariablePayload_l1
; write seconds
lds r16, timerModuleCounterSecs ; adding of current seconds counter requested
st X+, r16
lds r16, timerModuleCounterSecs+1
st X+, r16
lds r16, timerModuleCounterSecs+2
st X+, r16
lds r16, timerModuleCounterSecs+3
st X+, r16
COM2_BeginMsgWithVariablePayload_l1:
lsr r3 ; shift out shift out COM2_PAYLOAD_FLAGS_UID
brcc COM2_BeginMsgWithVariablePayload_l2
; write uid
push xh
push xl
rcall Utils_ReadUid ; (R16, X)
pop xl
pop xh
st X+, r18
st X+, r19
st X+, r20
st X+, r21
COM2_BeginMsgWithVariablePayload_l2:
ret
; ---------------------------------------------------------------------------
; com2CalcPayloadSize
;
; Calculate payload size from given flags
;
; IN:
; - R16: flags
; OUT:
; - R16: payload size
; MODIFIED REGS: R4, R16, R17
com2CalcPayloadSize:
clr r4
ldi r17, 4
lsr r16 ; shift out COM2_PAYLOAD_FLAGS_SECONDS
brcc com2CalcPayloadSize_l1
add r4, r17 ; add 4 bytes
com2CalcPayloadSize_l1:
lsr r16 ; shift out COM2_PAYLOAD_FLAGS_UID
brcc com2CalcPayloadSize_l2
add r4, r17 ; add 4 bytes
com2CalcPayloadSize_l2:
lsr r16 ; shift out reserved1, after this R16 contains COM2_PAYLOAD_FLAGS_NUM0-4
add r16, r4 ; add previous bytes to R16
ret
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Sending and receiving messages
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ---------------------------------------------------------------------------
; receive packet.
;
; OUT:
; - CFLAG: set if okay (packet received), cleared on error
; REGS: r16, r17, x (r18, r19, r20, r21, r22)
com2ReceivePacket:
ldi xl, LOW(com2RecvBuffer)
ldi xh, HIGH(com2RecvBuffer)
ld r16, X ; check: buffer in use?
tst r16
breq com2ReceivePacket_bufferAvailable
ldi xl, LOW(com2StatsNoBufferError) ; buffer in use, don't release
ldi xh, HIGH(com2StatsNoBufferError) ; just increment error counter
rcall Utils_IncrementCounter16 ; (r18, r19, 22)
clc
ret
com2ReceivePacket_bufferAvailable:
; read destination address
rcall com2ReceiveByte ; read byte (R16, R17, R20, R21, R22)
brcc com2ReceivePacket_ioError
; compare destination address (accept "FF" and own address)
cpi r16, 0xff
breq com2ReceivePacket_acceptAddr
lds r17, com2Address
cp r16, r17
breq com2ReceivePacket_acceptAddr
clc ; not for me
ret
com2ReceivePacket_acceptAddr:
st X+, r16 ; store dest address, lock buffer
; read msg length
rcall com2ReceiveByte ; read packet length (R16, R17, R20, R21, R22)
brcc com2ReceivePacket_ioError
st X+, r16
cpi r16, (COM2_BUFFER_SIZE-3)
brcc com2ReceivePacket_contentError ; packet too long
inc r16 ; account for checksum byte
mov r17, r16
com2ReceivePacket_loop:
push r17
rcall com2ReceiveByte ; read byte (R16, R17, R20, R21, R22)
pop r17
brcc com2ReceivePacket_ioError
st X+, r16
dec r17
brne com2ReceivePacket_loop
ldi xl, LOW(com2RecvBuffer)
ldi xh, HIGH(com2RecvBuffer)
rcall com2CheckMessageInBuffer ; (R16, R17, R18, R19, R20, X)
brcc com2ReceivePacket_contentError
; done, increment packet counter, set flags
ldi xl, LOW(com2StatsPacketsIn)
ldi xh, HIGH(com2StatsPacketsIn)
rcall Utils_IncrementCounter16 ; (r18, r19, 22)
sec
ret
com2ReceivePacket_ioError:
ldi xl, LOW(com2StatsIoError)
ldi xh, HIGH(com2StatsIoError)
rjmp com2ReceivePacket_incCounter
com2ReceivePacket_contentError:
ldi xl, LOW(com2StatsContentError)
ldi xh, HIGH(com2StatsContentError)
rjmp com2ReceivePacket_incCounter
com2ReceivePacket_incCounter:
rcall Utils_IncrementCounter16 ; (r18, r19, 22)
clr r16
sts com2RecvBuffer, r16 ; unlock buffer
clc
ret
; ---------------------------------------------------------------------------
; send packet from sendBuffer, if line free.
;
; IN:
; - nothing
; OUT:
; - CFLAG: set if okay (packet sent), cleared on error
; REGS: r22, x (r18, r19, r22)
COM2_SendPacket:
ldi xl, LOW(com2SendBuffer)
ldi xh, HIGH(com2SendBuffer)
COM2_SendPacketAtX:
in r15, SREG
push r15
cli
; check for ATTN line: busy?
cbi COM_PORT_ATTN, COM_PINNUM_ATTN ; disable pullup on ATTN
cbi COM_DDR_ATTN, COM_PINNUM_ATTN ; set ATTN as input
nop ; needed to sample current input
sbis COM_PIN_ATTN, COM_PINNUM_ATTN ; ATTN low?
rjmp COM2_SendPacket_lineBusyError ; jump if it is
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
adiw xh:xl, COM2_MSG_OFFS_MSGLEN
ld r16, X
sbiw xh:xl, COM2_MSG_OFFS_MSGLEN
inc r16 ; account for dest addr
inc r16 ; account for msglen byte
inc r16 ; account for crc byte
rcall com2SendPacketRaw
cbi COM_DDR_ATTN, COM_PINNUM_ATTN ; release ATTN line (by setting direction to IN)
brcc COM2_SendPacket_ioError
; packet successfully sent
ldi xl, LOW(com2StatsPacketsOut)
ldi xh, HIGH(com2StatsPacketsOut)
rcall Utils_IncrementCounter16 ; (r18, r19, r22)
pop r15
out SREG, r15
sec
ret
COM2_SendPacket_ioError:
ldi xl, LOW(com2StatsCollisions)
ldi xh, HIGH(com2StatsCollisions)
rjmp COM2_SendPacket_incCounter
COM2_SendPacket_lineBusyError:
ldi xl, LOW(com2StatsBusyError)
ldi xh, HIGH(com2StatsBusyError)
rjmp COM2_SendPacket_incCounter
COM2_SendPacket_incCounter:
rcall Utils_IncrementCounter16 ; (r18, r19, r22)
pop r15
out SREG, r15
clc
ret
; ---------------------------------------------------------------------------
; send packet over wire, expects ATTN to be low.
;
; IN:
; - r16: number of bytes to send
; - x : ptr to buffer to send
; OUT:
; - nothing
; REGS: r16, r17, x (r21, r22)
com2SendPacketRaw:
mov r17, r16
com2SendPacket_loop:
ld r16, X+
rcall com2SendByte ; send byte (R16, R21, R22)
brcc com2SendPacket_ioError
dec r17
brne com2SendPacket_loop
sec
ret
com2SendPacket_ioError:
clc
ret
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ISR
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
com2IsrPcint0:
push r15
in r15, SREG
sbic COM_PIN_ATTN, COM_PINNUM_ATTN
rjmp com2IsrPcint0_end
; low, read packet
push r1
push r16
push r17
push r18
push r19
push r20
push r21
push r22
push xh
push xl
rcall com2ReceivePacket ; (r16, r17, r18, r19, r20, r21, r22, x)
lds xl, com2Interrupts
lds xh, com2Interrupts+1
adiw xh:xl, 1
sts com2Interrupts, xl
sts com2Interrupts+1, xh
pop xl
pop xh
pop r22
pop r21
pop r20
pop r19
pop r18
pop r17
pop r16
pop r1
com2IsrPcint0_end:
pop r15
reti
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Lowlevel IO
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ---------------------------------------------------------------------------
; com2SendByte
;
; 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
com2SendByte:
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 one bit duration
; send data bits
com2SendByte_loop: ; 9 for low bit
lsr r16 ; 1+ bit to send -> CARRY
brcs com2SendByte_setHigh ; HI: +2, LO: +1
com2SendByte_setLow:
sbi COM_DDR_DATA, COM_PINNUM_DATA ; +2 set DATA as output
Utils_WaitNanoSecs COM_BIT_LENGTH, 9, r22
rjmp com2SendByte_loopEnd ; +2
com2SendByte_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)
Utils_WaitNanoSecs COM_BIT_LENGTH/2, 11, r22 ; wait for half a bit length for line to safely settle
sbis COM_PIN_DATA, COM_PINNUM_DATA ; +1 if no skip, +2 if skipped
rjmp com2SendByte_error ; +2 if error (collision: we wanted line to be high but it is low)
Utils_WaitNanoSecs COM_BIT_LENGTH/2, 0, r22
com2SendByte_loopEnd:
dec r21 ; +1
brne com2SendByte_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 ; wait for one bit length
sec
ret
com2SendByte_error:
clc
ret
; ---------------------------------------------------------------------------
; com2ReceiveByte
;
; 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)
com2ReceiveByte:
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 com2WaitForDataLow ; (R17)
brcc com2ReceiveByte_error
Utils_WaitNanoSecs COM_BIT_LENGTH/2, 5, r22 ; goto middle of startbit to maximize sync stability
com2ReceiveByte_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 com2ReceiveByte_shiftIn ; HIGH: +2, rjmp, use set CFLAG
clc ; LOW: +1
com2ReceiveByte_shiftIn:
ror r20 ; +1
dec r21 ; +1
brne com2ReceiveByte_loop ; +2, sum per loop: 8 cycles
rcall com2WaitForDataHigh ; wait for start of stopbit
brcc com2ReceiveByte_error
mov r16, r20
sec
ret
com2ReceiveByte_error:
clc
ret
; ---------------------------------------------------------------------------
; com2WaitForDataLow
;
; Waits up to COM2_MAXWAIT_US loops for low data line
; IN:
; OUT:
; - CFLAG: set if okay, clear otherwise
; MODIFIED REGISTERS: r17, r22
com2WaitForDataLow:
ldi r17, COM2_MAXWAIT_US
com2WaitForDataLow_loop:
sbis COM_PIN_DATA, COM_PINNUM_DATA
rjmp com2WaitForDataLow_done
rcall com2WaitFor1000ns
dec r17
brne com2WaitForDataLow_loop
clc ; timeout
ret
com2WaitForDataLow_done:
sec ; ok
ret
; ---------------------------------------------------------------------------
; com2WaitForDataHigh
;
; Waits up to COM2_MAXWAIT_US loops for high data line
; IN:
; OUT:
; - CFLAG: set if okay, clear otherwise
; MODIFIED REGISTERS: r17, r22, X
com2WaitForDataHigh:
ldi r17, COM2_MAXWAIT_US
com2WaitForDataHigh_loop:
sbic COM_PIN_DATA, COM_PINNUM_DATA
rjmp com2WaitForDataHigh_done
rcall com2WaitFor1000ns
dec r17
brne com2WaitForDataHigh_loop
clc ; timeout
ret
com2WaitForDataHigh_done:
sec ; ok
ret
; ---------------------------------------------------------------------------
; com2WaitForAttnHigh
;
; Waits up to COM2_MAXWAIT_US loops for high ATTN line
; IN:
; OUT:
; - CFLAG: set if okay, clear otherwise
; MODIFIED REGISTERS: r17, r22, X
com2WaitForAttnHigh:
ldi r17, COM2_MAXWAIT_US
com2WaitForAttnHigh_loop:
sbic COM_PIN_ATTN, COM_PINNUM_ATTN
rjmp com2WaitForAttnHigh_done
rcall com2WaitFor1000ns
dec r17
brne com2WaitForAttnHigh_loop
clc ; timeout
ret
com2WaitForAttnHigh_done:
sec ; ok
ret
; ---------------------------------------------------------------------------
; comWaitFor100ns
;
; Waits for 100 nanoseconds.
; IN:
; OUT:
; - CFLAG: set if okay, clear otherwise
; REGS: r17, r22
com2WaitFor1000ns:
Utils_WaitNanoSecs 1000, 7, r22 ; wait for 100 nanosecs (minus 3 cycles for rcall, 4 for ret)
ret
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; CRC code
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ---------------------------------------------------------------------------
; add checksum byte to buffer
;
; IN:
; - X : pointer to packet buffer
; OUT:
; - CFLAG: set if okay, clear otherwise
; MODIFIED REGS: R16, R17, R18, R19, X
com2CalcAndAddChecksumByte:
adiw xh:xl, COM2_MSG_OFFS_MSGLEN
ld r18, X ; read msg len
sbiw xh:xl, COM2_MSG_OFFS_MSGLEN
inc r18 ; account for dest address
inc r18 ; account for msg len byte
ldi r19, COM2_CRC_POLYNOMIAL
rcall com2CalcCrc8 ; (R16, R17, R18, R20, X)
st X, r16 ; add checksum byte
sec
ret
; ---------------------------------------------------------------------------
; check message in buffer
;
; IN:
; - X : pointer to packet buffer
; OUT:
; - CFLAG: set if okay, clear otherwise
; MODIFIED REGS: R16, R17, R18, R19, R20, X
com2CheckMessageInBuffer:
adiw xh:xl, COM2_MSG_OFFS_MSGLEN
ld r18, X ; read msg len
sbiw xh:xl, COM2_MSG_OFFS_MSGLEN
inc r18 ; account for dest address
inc r18 ; account for msg len byte
ldi r19, COM2_CRC_POLYNOMIAL
rcall com2CalcCrc8 ; (R16, R17, R18, R20, X)
ld r17, X
cp r16, r17 ; should be equal
brne com2CheckMessageInBuffer_error
sec
ret
com2CheckMessageInBuffer_error:
clc
ret
; ---------------------------------------------------------------------------
; calc crc8 checksum using given polynomial
;
; IN:
; - X : pointer to data to calc crc8 for
; - r18: number of bytes to calc crc8 for
; - r19: polynomial to use (e.g. 0x97: HD=4 up to 119 bytes, e.g. detects all 1 to 3 bit errors)
; OUT:
; - r16: crc8 checksum
; - X : point directly behind the checked area
; MODIFIED REGS: R16, R17, R18, R20, X
com2CalcCrc8:
ldi r16, 0xff ; crc
com2CalcCrc8_loop1:
ld r17, X+ ; running var
eor r16, r17
ldi r20, 8 ; counter for loop2
com2CalcCrc8_loop2:
lsl r16
brcc com2CalcCrc8_l1
eor r16, r19
com2CalcCrc8_l1:
dec r20
brne com2CalcCrc8_loop2
dec r18
brne com2CalcCrc8_loop1
ret
COM2_END:
.equ MODULE_SIZE_COM2 = COM2_END-COM2_BEGIN

View File

@@ -1,211 +0,0 @@
; ***************************************************************************
; 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. *
; ***************************************************************************
; ***************************************************************************
; code
.cseg
COM_BUFFER_BEGIN:
; ---------------------------------------------------------------------------
; 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
adiw xh:xl, COM_BUFFER_OFFS_DATA
sec
ret
COM_AllocBufferAndGetXY_error:
ldi xl, LOW(comStatsSendNoBuffer)
ldi xh, HIGH(comStatsSendNoBuffer)
clc
ret
; ---------------------------------------------------------------------------
; 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, comMaxBuffersUsed ; calc max buffers used
cp r16, r17
brcc COM_AllocBuffer_l0
sts comMaxBuffersUsed, r17
COM_AllocBuffer_l0:
lds r16, comRecvBuffersWritePos ; get current write pos
mov r17, r16 ; increment for next call
inc r17
cpi r17, COM_BUFFER_NUM ; CF set if COM_BUFFER_NUM > R17
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 ; 0?
brne COM_BufferDeallocBack_l1 ; nope go directly decrement r17
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
mov yl, r16
clr yh
lsl yl
rol yh ; *2
add yl, r16
adc yh, r17 ; *3
lsl yl
rol yh ; *6
lsl yl
rol yh ; *12
lsl yl
rol yh ; *24
; add base position of buffers
ldi r16, LOW(comRecvBuffers)
ldi r17, HIGH(comRecvBuffers)
add yl, r16
adc yh, r17
ret
COM_BUFFER_END:
.equ MODULE_SIZE_COM_BUFFER = COM_BUFFER_END-COM_BUFFER_BEGIN

View File

@@ -1,143 +0,0 @@
; ***************************************************************************
; 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. *
; ***************************************************************************
#define COM_USE_CRC8 1
#define COM_CRC_POLYNOMIAL 0x97
; ***************************************************************************
; code
.cseg
COM_CRC_BEGIN:
; ---------------------------------------------------------------------------
; add checksum byte to buffer
;
; IN:
; - X : pointer to packet buffer
; OUT:
; - CFLAG: set if okay, clear otherwise
; MODIFIED REGS: R16, R17, R18, R19, X
comCalcAndAddChecksumByte:
adiw xh:xl, COM_MSG_OFFS_MSGLEN
ld r18, X ; read msg len
inc r18 ; account for dest address
inc r18 ; account for msg len byte
sbiw xh:xl, COM_MSG_OFFS_MSGLEN
#ifdef COM_USE_CRC8
ldi r19, COM_CRC_POLYNOMIAL
rcall cproCalcCrc8 ; (R16, R17, R18, R20, X)
#else
rcall cproCalcXor ; (R16, R17, R18, X)
#endif
st X, r16 ; add checksum byte
sec
ret
; ---------------------------------------------------------------------------
; check message in buffer
;
; IN:
; - X : pointer to packet buffer
; OUT:
; - CFLAG: set if okay, clear otherwise
; MODIFIED REGS: R16, R17, R18, R19, R20, X
cproCheckMessageInBuffer:
adiw xh:xl, COM_MSG_OFFS_MSGLEN
ld r18, X ; read msg len
inc r18 ; account for dest address
inc r18 ; account for msg len byte
sbiw xh:xl, COM_MSG_OFFS_MSGLEN
#ifdef COM_USE_CRC8
ldi r19, COM_CRC_POLYNOMIAL
rcall cproCalcCrc8 ; (R16, R17, R18, R20, X)
#else
rcall cproCalcXor ; (R16, R17, R18, X)
#endif
ld r17, X
cp r16,r17 ; should be equal
brne cproCheckMessageInBuffer_error
sec
ret
cproCheckMessageInBuffer_error:
clc
ret
; ---------------------------------------------------------------------------
; calc xor checksum
;
; IN:
; - X : pointer to data to calc crc8 for
; - r18: number of bytes to calc crc8 for
; OUT:
; - r16: xor checksum
; - X : point directly behind the checked area
; MODIFIED REGS: R16, R17, R18, X
cproCalcXor:
clr r16
cproCalcXor_loop1:
ld r17, X+
eor r16, r17
dec r18
brne cproCalcXor_loop1
ret
; ---------------------------------------------------------------------------
; calc crc8 checksum using given polynomial
;
; IN:
; - X : pointer to data to calc crc8 for
; - r18: number of bytes to calc crc8 for
; - r19: polynomial to use (e.g. 0x97: HD=4 up to 119 bytes, e.g. detects all 1 to 3 bit errors)
; OUT:
; - r16: crc8 checksum
; - X : point directly behind the checked area
; MODIFIED REGS: R16, R17, R18, R20, X
cproCalcCrc8:
ldi r16, 0xff ; crc
cproCalcCrc8_loop1:
ld r17, X+ ; running var
eor r16, r17
ldi r20, 8 ; counter for loop2
cproCalcCrc8_loop2:
lsl r16
brcc cproCalcCrc8_l1
eor r16, r19
cproCalcCrc8_l1:
dec r20
brne cproCalcCrc8_loop2
dec r18
brne cproCalcCrc8_loop1
ret
COM_CRC_END:
.equ MODULE_SIZE_COM_CRC = COM_CRC_END-COM_CRC_BEGIN

View File

@@ -1,215 +0,0 @@
; ***************************************************************************
; 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. *
; ***************************************************************************
; ***************************************************************************
; code
.cseg
COM_LOWLEVEL_BEGIN:
; ---------------------------------------------------------------------------
; 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 one bit duration
; send data bits
comSendByte_loop: ; 9 for low bit
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
Utils_WaitNanoSecs COM_BIT_LENGTH, 9, r22
rjmp comSendByte_loopEnd ; +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)
Utils_WaitNanoSecs COM_BIT_LENGTH/2, 11, r22 ; wait for half a bit length for line to safely settle
sbis COM_PIN_DATA, COM_PINNUM_DATA ; +1 if no skip, +2 if skipped
rjmp comSendByte_error ; +2 if error (collision: we wanted line to be high but it is low)
Utils_WaitNanoSecs COM_BIT_LENGTH/2, 0, r22
comSendByte_loopEnd:
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 ; wait for one bit length
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_US loops for low data line
; IN:
; OUT:
; - CFLAG: set if okay, clear otherwise
; MODIFIED REGISTERS: r17, r22
comWaitForDataLow:
ldi r17, COM_MAXWAIT_US
comWaitForDataLow_loop:
sbis COM_PIN_DATA, COM_PINNUM_DATA
rjmp comWaitForDataLow_done
rcall comWaitFor1000ns
dec r17
brne comWaitForDataLow_loop
clc ; timeout
ret
comWaitForDataLow_done:
sec ; ok
ret
; ---------------------------------------------------------------------------
; comWaitForDataHigh
;
; Waits up to COM_MAXWAIT_US loops for high data line
; IN:
; OUT:
; - CFLAG: set if okay, clear otherwise
; MODIFIED REGISTERS: r17, r22, X
comWaitForDataHigh:
ldi r17, COM_MAXWAIT_US
comWaitForDataHigh_loop:
sbic COM_PIN_DATA, COM_PINNUM_DATA
rjmp comWaitForDataHigh_done
rcall comWaitFor1000ns
dec r17
brne comWaitForDataHigh_loop
clc ; timeout
ret
comWaitForDataHigh_done:
sec ; ok
ret
; ---------------------------------------------------------------------------
; comWaitForAttnHigh
;
; Waits up to COM_MAXWAIT_US loops for high ATTN line
; IN:
; OUT:
; - CFLAG: set if okay, clear otherwise
; MODIFIED REGISTERS: r17, r22, X
comWaitForAttnHigh:
ldi r17, COM_MAXWAIT_US
comWaitForAttnHigh_loop:
sbic COM_PIN_ATTN, COM_PINNUM_ATTN
rjmp comWaitForAttnHigh_done
rcall comWaitFor1000ns
dec r17
brne comWaitForAttnHigh_loop
clc ; timeout
ret
comWaitForAttnHigh_done:
sec ; ok
ret
; ---------------------------------------------------------------------------
; comWaitFor100ns
;
; Waits for 100 nanoseconds.
; IN:
; OUT:
; - CFLAG: set if okay, clear otherwise
; MODIFIED REGISTERS: r17, r22, X
comWaitFor1000ns:
Utils_WaitNanoSecs 1000, 7, r22 ; wait for 100 nanosecs (minus 3 cycles for rcall, 4 for ret)
ret
COM_LOWLEVEL_END:
.equ MODULE_SIZE_COM_LOWLEVEL = COM_LOWLEVEL_END-COM_LOWLEVEL_BEGIN

View File

@@ -1,161 +0,0 @@
; ***************************************************************************
; 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. *
; ***************************************************************************
; ***************************************************************************
; code
.cseg
COM_RECV_BEGIN:
; ---------------------------------------------------------------------------
; 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, R18, R19, R20, R21, R22)
comReceivePacketHandleBuffer:
rcall COM_BufferAlloc
brcs comReceivePacketHandleBuffer_haveBuffer
ldi xl, LOW(comStatsRecvNoBuffer)
ldi xh, HIGH(comStatsRecvNoBuffer)
rjmp comReceivePacketHandleBuffer_errorWithCounter
comReceivePacketHandleBuffer_haveBuffer:
; get pos of data portion for the allocated buffer
mov xl, yl
mov xh, yh
adiw xh:xl, COM_BUFFER_OFFS_DATA
rcall comReceivePacketToXandCheck ; (r16, r17, r18, r20, r21, r22, X)
brcs comReceivePacketHandleBuffer_haveMessage
push r16
rcall COM_BufferDeallocBack ; (r16, r17, r21)
pop r16
cpi r16, COM_ERR_NOTFORME ; packet just not for me?
breq comReceivePacketHandleBuffer_notforme ; correct, don't count as error
ldi xl, LOW(comStatsRecvCrcErrs)
ldi xh, HIGH(comStatsRecvCrcErrs)
cpi r16, COM_ERR_CHECKSUM
breq comReceivePacketHandleBuffer_errorWithCounter
ldi xl, LOW(comStatsRecvErrs) ; generic error
ldi xh, HIGH(comStatsRecvErrs)
rjmp comReceivePacketHandleBuffer_errorWithCounter
comReceivePacketHandleBuffer_haveMessage:
; handle buffer flags
ldi r16, COM_BUFFER_FLAGS_RECEIVED
std y+COM_BUFFER_OFFS_FLAGS, r16
ldi xl, LOW(comStatsPacketsIn)
ldi xh, HIGH(comStatsPacketsIn)
rcall Utils_IncrementCounter16 ; (r18, r19, 22)
sec
ret
comReceivePacketHandleBuffer_errorWithCounter:
rcall Utils_IncrementCounter16 ; (r18, r19, 22)
comReceivePacketHandleBuffer_notforme:
clc
ret
; ---------------------------------------------------------------------------
; comReceivePacketToXandCheck
;
; 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
; - R16: error code if CFLAG cleared
; MODIFIED REGISTERS: r16, r17, r18, X (r19, r20, r21, r22)
comReceivePacketToXandCheck:
push xh
push xl
rcall comReceivePacketToSram ; (r16, r17, R20, R21, R22, X)
pop xl
pop xh
brcc comReceivePacketToXandCheck_error
rcall cproCheckMessageInBuffer ; (R16, R17, R18, R19, R20, X)
ldi r16, COM_ERR_CHECKSUM
brcc comReceivePacketToXandCheck_error
sec
ret
comReceivePacketToXandCheck_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: r16, r17, X (R20, R21, R22)
comReceivePacketToSram:
; read destination address
rcall comReceiveByte ; read byte (R16, R17, R20, R21, R22)
brcc comReceivePacketToSram_error
; compare destination address (accept "00", "FF" and own address)
tst r16
breq comReceivePacketToSram_acceptAddr
cpi r16, 0xff
breq comReceivePacketToSram_acceptAddr
lds r17, comAddress
cp r16, r17
breq comReceivePacketToSram_acceptAddr
ldi r16, COM_ERR_NOTFORME
clc ; not for me
ret
comReceivePacketToSram_acceptAddr:
st X+, r16 ; store dest address
; read msg length
rcall comReceiveByte ; read packet length (R16, R17, R20, R21, R22)
brcc comReceivePacketToSram_error
st X+, r16
cpi r16, (COM_BUFFER_SIZE-3-COM_BUFFER_OFFS_DATA)+1
brcc comReceivePacketToSram_error ; packet too long (TODO: count overruns)
inc r16 ; account for checksum byte
mov r17, r16
comReceivePacketToSram_loop:
push r17
rcall comReceiveByte ; read byte (R16, R17, R20, R21, R22)
pop r17
brcc comReceivePacketToSram_error
st X+, r16
dec r17
brne comReceivePacketToSram_loop
sec
ret
comReceivePacketToSram_error:
ldi r16, COM_ERR_IO
clc
ret
COM_RECV_END:
.equ MODULE_SIZE_COM_RECV = COM_RECV_END-COM_RECV_BEGIN

View File

@@ -1,214 +0,0 @@
; ***************************************************************************
; 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. *
; ***************************************************************************
; ***************************************************************************
; code
.cseg
COM_SEND_BEGIN:
; ---------------------------------------------------------------------------
; 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
cbi COM_PORT_ATTN, COM_PINNUM_ATTN ; disable pullup on ATTN
cbi COM_DDR_ATTN, COM_PINNUM_ATTN ; set ATTN as input
nop ; needed to sample current input
sbis COM_PIN_ATTN, COM_PINNUM_ATTN ; ATTN low?
rjmp comSendPacketHandleRepeat_adjustRepeat ; jump if it is
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 (by setting direction to IN)
brcc comSendPacketHandleRepeat_collision
; packet sent, adjust stats, release buffer
ldi xl, LOW(comStatsPacketsOut)
ldi xh, HIGH(comStatsPacketsOut)
rcall comDeallocReadBufAndIncrCounter ; (r16, r17, r18)
rjmp comSendPacketHandleRepeat_retC
comSendPacketHandleRepeat_collision:
; increment collisions counter
ldi xl, LOW(comStatsCollisions)
ldi xh, HIGH(comStatsCollisions)
rcall Utils_IncrementCounter16 ; (r18, r19, 22)
comSendPacketHandleRepeat_adjustRepeat:
; 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
; ---------------------------------------------------------------------------
; 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
; ---------------------------------------------------------------------------
; comDeallocReadBufAndIncrCounter
;
; IN:
; - X : pointer to counter
; OUT:
; - nothing
; REGS: r16, r17, r21
comDeallocReadBufAndIncrCounter:
rcall COM_BufferDeallocFront ; (r16, r17, r21)
ldi r21, 1
ld r16, x+
ld r17, x
add r16, r21
dec r21
adc r17, r21
st x, r17
st -x, r16
sts comRepeatCount, r21 ; set comRepeatCount to zero
ret
COM_SEND_END:
.equ MODULE_SIZE_COM_SEND = COM_SEND_END-COM_SEND_BEGIN

View File

@@ -40,37 +40,31 @@
.equ CPRO_CMD_SYSSTATS = 82
; flags for variable payload enqueue function
.equ CPRO_PAYLOAD_FLAGS_SECONDS = 0x01
.equ CPRO_PAYLOAD_FLAGS_UID = 0x02
.equ CPRO_PAYLOAD_FLAGS_RESERVED1 = 0x04
.equ CPRO_PAYLOAD_FLAGS_NUM0 = 0x08
.equ CPRO_PAYLOAD_FLAGS_NUM1 = 0x10
.equ CPRO_PAYLOAD_FLAGS_NUM2 = 0x20
.equ CPRO_PAYLOAD_FLAGS_NUM3 = 0x40
.equ CPRO_PAYLOAD_FLAGS_NUM4 = 0x80
.equ CPRO_PAYLOAD_FLAGS_SHIFT_NUM = 3
.equ CPRO_PACKET_HAVEADDR_OFFS_ADDRESS = COM_MSG_OFFS_PAYLOAD+4
.equ CPRO_PACKET_CLAIMADDR_OFFS_ADDRESS = COM_MSG_OFFS_PAYLOAD+4
.equ CPRO_PACKET_DENYADDR_OFFS_ADDRESS = COM_MSG_OFFS_PAYLOAD+4
.equ CPRO_PACKET_HAVEADDR_OFFS_ADDRESS = COM2_MSG_OFFS_PAYLOAD+4
.equ CPRO_PACKET_CLAIMADDR_OFFS_ADDRESS = COM2_MSG_OFFS_PAYLOAD+4
.equ CPRO_PACKET_DENYADDR_OFFS_ADDRESS = COM2_MSG_OFFS_PAYLOAD+4
.equ CPRO_WAITTIME_INITIAL = 10
.equ CPRO_WAITTIME_GETADDR = 130
.equ CPRO_WAITTIME_CLAIMADDR = 17
.equ CPRO_WAITTIME_RECLAIMADDR = 10
; current mode of operation
.equ CPRO_MODE_NORMAL = 0 ; normal operation
.equ CPRO_MODE_GETADDRSTARTED = 10 ; waiting for HAVE_ADDRESS and ADDRESS_RANGE packets to arrive
.equ CPRO_MODE_CLAIMING_ADDR1 = 20 ; CLAIM_ADDRESS sent, waiting for HAVE_ADDRESS packet to reject the claim
.equ CPRO_MODE_CLAIMING_ADDR2 = 21 ; CLAIM_ADDRESS sent, 2nd try
.equ CPRO_MODE_CLAIMING_ADDR3 = 22 ; CLAIM_ADDRESS sent, 3rd try
.equ CPRO_MODE_SENDING_HAVE_ADDRESS = 30 ; waiting for our turn to send HAVE_ADDRESS packet
.equ CPRO_MODE_RECLAIMING_ADDR = 40 ; CLAIM_ADDRESS with the previously used address sent after bootup
.equ CPRO_MODE_NOADDRESS = 0x00 ; no address, yet
.equ CPRO_MODE_NORMAL = 0x01 ; normal operation
.equ CPRO_MODE_SEND_NEED_ADDR = 0x02 ; wait to send need address
.equ CPRO_MODE_GETADDRSTARTED = 0x03 ; waiting for HAVE_ADDRESS and ADDRESS_RANGE packets to arrive
.equ CPRO_MODE_SEND_CLAIM_ADDR1 = 0x04 ; send CLAIM_ADDRESS as part of reclaiming procedure
.equ CPRO_MODE_CLAIMING_ADDR1 = 0x05 ; CLAIM_ADDRESS sent, waiting for HAVE_ADDRESS packet to reject the claim
.equ CPRO_MODE_CLAIMING_ADDR2 = 0x06 ; CLAIM_ADDRESS sent, 2nd try
.equ CPRO_MODE_CLAIMING_ADDR3 = 0x07 ; CLAIM_ADDRESS sent, 3rd try
.equ CPRO_MODE_SENDING_HAVE_ADDR = 0x08 ; waiting for our turn to send HAVE_ADDRESS packet
.equ CPRO_MODE_SEND_RECLAIM_ADDR = 0x09 ; send CLAIM_ADDRESS as part of reclaiming procedure
.equ CPRO_MODE_RECLAIMING_ADDR = 0x0a ; CLAIM_ADDRESS with the previously used address sent after bootup
.equ CPRO_MODE_SEND_DENY_ADDR = 0x0b ; someone claimed our address, send a DENY_ADDR message
.equ CPRO_MODE_NEXT_FREE = 0x0c ; next free mode
; ***************************************************************************
@@ -80,13 +74,7 @@
cproDataBegin:
#ifndef BASE_SYSTEM
cproMode: .byte 1 ; "normal", "waitForHaveAddress", "samplingAddresses", "claimAddress"
cproAddrRangeBegin: .byte 1
cproAddrRangeEnd: .byte 1
cproAddressWaitCounter: .byte 1 ; counter for seconds to wait for all nodes to respond
cproUsedAddresses: .byte 16 ; one bit per address known to b in use
#endif
cproMode: .byte 1
cproDataEnd:
@@ -107,42 +95,12 @@ CPRO_Init:
clr r16
ldi r17, (cproDataEnd-cproDataBegin)
rcall Utils_FillSram
sec
ret
CPRO_OnEverySecond:
#ifndef BASE_SYSTEM
lds r17, cproMode
cpi r17, CPRO_MODE_NORMAL
breq CPRO_OnEverySecond_done
CPRO_OnEverySecond_l1:
cpi r17, CPRO_MODE_GETADDRSTARTED
brne CPRO_OnEverySecond_l2
rjmp cproHandle1sGetAddrStarted
CPRO_OnEverySecond_l2:
cpi r17, CPRO_MODE_SENDING_HAVE_ADDRESS
brne CPRO_OnEverySecond_l3
rjmp cproHandle1sSendingHaveAddress
CPRO_OnEverySecond_l3:
cpi r17, CPRO_MODE_CLAIMING_ADDR1
brne CPRO_OnEverySecond_l4
rjmp cproHandle1sClaimingAddr12
CPRO_OnEverySecond_l4:
cpi r17, CPRO_MODE_CLAIMING_ADDR2
brne CPRO_OnEverySecond_l5
rjmp cproHandle1sClaimingAddr12
CPRO_OnEverySecond_l5:
cpi r17, CPRO_MODE_CLAIMING_ADDR3
brne CPRO_OnEverySecond_l6
rjmp cproHandle1sClaimingAddr3
CPRO_OnEverySecond_l6:
cpi r17, CPRO_MODE_RECLAIMING_ADDR
brne CPRO_OnEverySecond_done
rjmp cproHandle1sReclaimingAddr
CPRO_OnEverySecond_done:
#ifdef MODULES_COM_WITH_ADDR_PROTO
rcall CPRO_Address_Init
#endif
sec
ret
@@ -153,204 +111,43 @@ CPRO_OnEverySecond_done:
; Try to handle the given packet.
;
; IN:
; - Y : pointer to received buffer
; - X : pointer to received buffer
; OUT:
; - CFLAG: set if handled, cleared otherwise
; USED: depending on called routines
CPRO_OnPacketReceived:
ldd r16, y+(COM_BUFFER_OFFS_DATA+COM_MSG_OFFS_CMD)
adiw xh:xl, COM2_MSG_OFFS_CMD
ld r16, x
sbiw xh:xl, COM2_MSG_OFFS_CMD
cpi r16, CPRO_CMD_PING
brne CPRO_OnPacketReceived_l1
rjmp cproHandlePing
CPRO_OnPacketReceived_l1:
#ifndef BASE_SYSTEM
cpi r16, CPRO_CMD_NEED_ADDRESS
brne CPRO_OnPacketReceived_l2
rjmp cproHandlePckNeedAddr
CPRO_OnPacketReceived_l2:
cpi r16, CPRO_CMD_HAVE_ADDRESS
brne CPRO_OnPacketReceived_l3
rjmp cproHandlePckHaveAddr
CPRO_OnPacketReceived_l3:
cpi r16, CPRO_CMD_ADDRESS_RANGE
brne CPRO_OnPacketReceived_l4
rjmp cproHandleAddrRange
CPRO_OnPacketReceived_l4:
cpi r16, CPRO_CMD_DENY_ADDRESS
brne CPRO_OnPacketReceived_l5
rjmp cproHandleDenyAddr
CPRO_OnPacketReceived_l5:
cpi r16, CPRO_CMD_CLAIM_ADDRESS
brne CPRO_OnPacketReceived_l6
rjmp cproHandlePckClaimAddr
CPRO_OnPacketReceived_l6:
#endif
#ifdef MODULES_COM_WITH_ADDR_PROTO
rjmp CPRO_Address_OnPacketReceived
#else
clc
ret
#endif
cproHandlePing:
ldd r16, y+(COM_BUFFER_OFFS_DATA+COM_MSG_OFFS_SRCADDR)
tst r16
adiw xh:xl, COM2_MSG_OFFS_SRCADDR
ld r16, x
tst r16 ; dont handle src address 0
breq cproHandlePing_notHandled
rcall CPRO_EnqueuePong
ret ; use carry flag from previous call
inc r16
breq cproHandlePing_notHandled ; dont handle src address 255
rcall CPRO_WritePong
rjmp COM2_SendPacket ; use carry flag from this routine
cproHandlePing_notHandled:
clc
ret
; ---------------------------------------------------------------------------
; Enqueue a PING packet.
;
; IN:
; - R16: destination address
; OUT:
; - CFLAG: set if okay, clear otherwise
; MODIFIED REGS: R18, R20 (R15, R16, R17, X, Y)
CPRO_EnqueuePing:
ldi r18, CPRO_CMD_PING
ldi r20, COM_BUFFER_PRIO_INFO
rjmp cproEnqueueMsgWithCmdAndSrcAddr
; ---------------------------------------------------------------------------
; Enqueue a PONG packet.
;
; IN:
; - R16: destination address
; OUT:
; - CFLAG: set if okay, clear otherwise
; MODIFIED REGS: R18, R20 (R15, R16, R17, X, Y)
CPRO_EnqueuePong:
ldi r18, CPRO_CMD_PONG
ldi r20, COM_BUFFER_PRIO_INFO
rjmp cproEnqueueMsgWithCmdAndSrcAddr
; ---------------------------------------------------------------------------
; Enqueue a simple packet with payload only CMD and source address.
;
; IN:
; - R16: destination address
; - R18: command (e.g. CPRO_CMD_PING or CPRO_CMD_PONG)
; - R20: priority of the message
; OUT:
; - CFLAG: set if okay, clear otherwise
; MODIFIED REGS: R16, R17, X, Y (R3, R4, R15, R16, R17, R18, R19, R20, R21)
cproEnqueueMsgWithCmdAndSrcAddr:
push r16
rcall COM_AllocBufferAndGetXY ; (r16, r17, r21)
pop r16
brcc cproEnqueueMsgWithCmdAndSrcAddr_error
ldi r17, CPRO_PAYLOAD_FLAGS_SECONDS
push xh
push xl
push r20
rcall cproBeginMsgWithVariablePayload ; (R3, R4, R16, R17, R18, R19, R20, R21, X)
pop r20
pop xl
pop xh
rcall comCalcAndAddChecksumByte ; (R16, R17, R18, R19, X)
; mark buffer as enqueued with PRIO given in R20
rcall COM_EnqueuePacket ; (R15, R16)
brcc cproEnqueueMsgWithCmdAndSrcAddr_error
sec
ret
cproEnqueueMsgWithCmdAndSrcAddr_error:
clc
ret
; ---------------------------------------------------------------------------
; begin packet with variable payload.
;
; IN:
; - R16: destination address
; - R17: flags
; - R18: command (e.g. CPRO_CMD_PING)
; - X : pointer to packet buffer
; OUT:
; - X : points to end of packet as it was written so far
; MODIFIED REGS: R3, R16, R17, R18, R19, R20, R21, X (R4)
cproBeginMsgWithVariablePayload:
; write header (dest address, msg length)
st X+, r16 ; destination address
mov r16, r17 ; calculate payload size
mov r3, r17
rcall cproCalcPayloadSize ; (R4, R16, R17)
inc r16 ; add CMD byte
inc r16 ; add source address byte
st X+, r16
; write payload
st X+, r18 ; 0: CMD
lds r16, comAddress ; 1: source address
st X+, r16
lsr r3 ; shift out CPRO_PAYLOAD_FLAGS_SECONDS
brcc cproBeginMsgWithVariablePayload_l1
lds r16, timerModuleCounterSecs ; adding of current seconds counter requested
st X+, r16
lds r16, timerModuleCounterSecs+1
st X+, r16
lds r16, timerModuleCounterSecs+2
st X+, r16
lds r16, timerModuleCounterSecs+3
st X+, r16
cproBeginMsgWithVariablePayload_l1:
lsr r3 ; shift out shift out CPRO_PAYLOAD_FLAGS_UID
brcc cproBeginMsgWithVariablePayload_l2
push xh
push xl
rcall Utils_ReadUid ; (R16, X)
pop xl
pop xh
st X+, r18
st X+, r19
st X+, r20
st X+, r21
cproBeginMsgWithVariablePayload_l2:
ret
; ---------------------------------------------------------------------------
; cproCalcPayloadSize
;
; Calculate payload size from given flags
;
; IN:
; - R16: flags
; OUT:
; - R16: payload size
; MODIFIED REGS: R4, R16, R17
cproCalcPayloadSize:
clr r4
ldi r17, 4
lsr r16 ; shift out CPRO_PAYLOAD_FLAGS_SECONDS
brcc cproCalcPayloadSize_l1
add r4, r17 ; add 4 bytes
cproCalcPayloadSize_l1:
lsr r16 ; shift out CPRO_PAYLOAD_FLAGS_UID
brcc cproCalcPayloadSize_l2
add r4, r17 ; add 4 bytes
cproCalcPayloadSize_l2:
lsr r16 ; shift out reserved1, after this R16 contains CPRO_PAYLOAD_FLAGS_NUM0-4
add r16, r4 ; add previous bytes to R16
ret
CPRO_END:
.equ MODULE_SIZE_CPRO = CPRO_END-CPRO_BEGIN

View File

@@ -53,6 +53,32 @@
; 4) Otherwise the node changes into protocol A (see above).
#ifdef MODULES_COM_WITH_ADDR_PROTO
; ***************************************************************************
; defs
; ***************************************************************************
; data
.dseg
cproAddressDataBegin:
cproAddressFlags: .byte 1
cproAddresModeTimer: .byte 2
cproAddrRangeBegin: .byte 1
cproAddrRangeEnd: .byte 1
cproAddressWaitCounter: .byte 1 ; counter for seconds to wait for all nodes to respond
cproUsedAddresses: .byte 16 ; one bit per address known to b in use
cproAddressDataEnd:
; ***************************************************************************
@@ -62,6 +88,23 @@
CPRO_Address_Init:
ldi xh, HIGH(cproAddressDataBegin)
ldi xl, LOW(cproAddressDataBegin)
clr r16
ldi r17, (cproAddressDataEnd-cproAddressDataBegin)
rcall Utils_FillSram
; setup timer for address setup (after 10s)
ldi r16, CPRO_MODE_NOADDRESS
sts cproMode, r16
ldi r18, 10
ldi r19, 0
rcall cproAddressSetTimer
ret
CPRO_StartReclaimAddrProcedure:
ldi xl, LOW(EEPROM_OFFS_COMADDR)
ldi xh, HIGH(EEPROM_OFFS_COMADDR)
@@ -73,12 +116,9 @@ CPRO_StartReclaimAddrProcedure:
cpi r16, 0xff
breq CPRO_StartReclaimAddrProcedure_l1
sts cproAddrRangeBegin, r16 ; currently claimed address
mov r19, r16
rcall CPRO_EnqueueClaimAddress
ldi r16, CPRO_WAITTIME_RECLAIMADDR
sts cproAddressWaitCounter, r16
ldi r16, CPRO_MODE_RECLAIMING_ADDR
ldi r16, CPRO_MODE_SEND_RECLAIM_ADDR
sts cproMode, r16
rcall cproAddressSetTimer1s ; use singleshot timer, send after 1s
sec
ret
CPRO_StartReclaimAddrProcedure_l1:
@@ -99,197 +139,10 @@ CPRO_StartGetAddrProcedure:
sts cproAddrRangeBegin, r16
ldi r16, 126
sts cproAddrRangeEnd, r16
; send "NEED_ADDRESS" packet
rcall CPRO_EnqueueNeedAddress
brcc CPRO_StartGetAddrProcedure_error
; set waittimer for sampling of "HAVE_ADDRESS" packets
ldi r16, CPRO_WAITTIME_GETADDR
sts cproAddressWaitCounter, r16
ldi r16, CPRO_MODE_GETADDRSTARTED
; setup singleshot timer to later send "NEED_ADDRESS" packet
ldi r16, CPRO_MODE_SEND_NEED_ADDR
sts cproMode, r16
sec
ret
CPRO_StartGetAddrProcedure_error:
clc
ret
; ***************************************************************************
; onEverySecond handlers
cproHandle1sSendingHaveAddress:
; waiting for counter to reach zero to send a HAVE_ADDRESS packet
lds r16, cproAddressWaitCounter
dec r16
sts cproAddressWaitCounter, r16
brne cproHandle1sSendingHaveAddress_done ; counter not 0, done for now
rcall CPRO_EnqueueHaveAddress ; counter is 0, send HAVE_ADDRESS
ldi r16, CPRO_MODE_NORMAL
sts cproMode, r16
cproHandle1sSendingHaveAddress_done:
ret
cproHandle1sGetAddrStarted:
lds r16, cproAddressWaitCounter
dec r16
sts cproAddressWaitCounter, r16
brne cproHandle1sGetAddrStarted_done ; counter not 0, done for now
rcall cproClaimFirstFreeAddr ; counter 0, find first free address and claim it
brcs cproHandle1sGetAddrStarted_done
; no free address, abort TODO: send an error message to bus ("bus full")
ldi r16, CPRO_MODE_NORMAL
sts cproMode, r16
cproHandle1sGetAddrStarted_done:
ret
cproHandle1sClaimingAddr12:
lds r16, cproAddressWaitCounter
dec r16
sts cproAddressWaitCounter, r16
brne cproHandle1sClaimingAddr12_done ; counter not 0, done for now
push r17
lds r19, cproAddrRangeBegin ; currently claimed address
rcall CPRO_EnqueueClaimAddress
pop r17
ldi r16, CPRO_WAITTIME_CLAIMADDR
sts cproAddressWaitCounter, r16
inc r17 ; next mode (CPRO_MODE_CLAIMING_ADDR1 and 2)
sts cproMode, r17
cproHandle1sClaimingAddr12_done:
ret
cproHandle1sClaimingAddr3:
lds r16, cproAddressWaitCounter
dec r16
sts cproAddressWaitCounter, r16
brne cproHandle1sClaimingAddr3_done ; counter not 0, done for now
; claimed given address 3rd time, set address and enter "normal" mode
lds r16, cproAddrRangeBegin ; currently sent address is in cproAddrRangeBegin
in r15, SREG
cli
sts comAddress, r16 ; write address into eeprom
ldi xl, LOW(EEPROM_OFFS_COMADDR)
ldi xh, HIGH(EEPROM_OFFS_COMADDR)
rcall Utils_WriteEepromIncr ; write address to EEPROM
ldi r16, CPRO_MODE_NORMAL ; set mode to "normal"
sts cproMode, r16
rcall CPRO_EnqueueHaveAddress
out SREG, r15
cproHandle1sClaimingAddr3_done:
ret
cproHandle1sReclaimingAddr:
lds r16, cproAddressWaitCounter
dec r16
sts cproAddressWaitCounter, r16
brne cproHandle1sReclaimingAddr_done ; counter not 0, done for now
; successfully claimed given address, set address and enter "normal" mode
lds r16, cproAddrRangeBegin ; currently sent address is in cproAddrRangeBegin
sts comAddress, r16 ; write address into eeprom
ldi r16, CPRO_MODE_NORMAL ; set mode to "normal"
sts cproMode, r16
rcall CPRO_EnqueueHaveAddress
cproHandle1sReclaimingAddr_done:
ret
; ***************************************************************************
; onPacketReceived handlers
cproHandlePckNeedAddr:
lds r17, cproMode
cpi r17, CPRO_MODE_NORMAL
brne cproHandlePckNeedAddr_done
; enter CPRO_MODE_SENDING_HAVE_ADDRESS mode
lds r16, comAddress
tst r16
breq cproHandlePckNeedAddr_done ; we have no address, don't handle
rcall cproEnterSendingHaveAddressMode
cproHandlePckNeedAddr_done:
sec
ret
cproHandlePckHaveAddr:
lds r17, cproMode
cpi r17, CPRO_MODE_GETADDRSTARTED
brne cproHandlePckHaveAddr_done
; validate address
ldd r16, y+(COM_BUFFER_OFFS_DATA+CPRO_PACKET_HAVEADDR_OFFS_ADDRESS)
tst r16
breq cproHandlePckHaveAddr_done ; invalid address, ignore
cpi r16, 127
brcc cproHandlePckHaveAddr_done ; invalid address, ignore
; set bit corresponding to given address in bitfield of used addresses
dec r16
rcall cproSetBitInBitfield
cproHandlePckHaveAddr_done:
sec
ret
cproHandlePckClaimAddr:
ldd r16, y+(COM_BUFFER_OFFS_DATA+CPRO_PACKET_CLAIMADDR_OFFS_ADDRESS)
tst r16
breq cproHandlePckClaimAddr_done
cpi r16, 0xff
breq cproHandlePckClaimAddr_done
lds r17, comAddress
cp r16, r17
brne cproHandlePckClaimAddr_done
rcall CPRO_EnqueueDenyAddress
cproHandlePckClaimAddr_done:
sec
ret
cproHandleDenyAddr:
; first check address
ldd r16, y+(COM_BUFFER_OFFS_DATA+CPRO_PACKET_DENYADDR_OFFS_ADDRESS)
lds r17, cproAddrRangeBegin
cp r16, r17
brne cproHandleDenyAddr_done ; not our currently claimed address, ignore
; then check mode
lds r17, cproMode
cpi r17, CPRO_MODE_CLAIMING_ADDR1
brcs cproHandleDenyAddr_l1
cpi r17, CPRO_MODE_CLAIMING_ADDR3+1
brcc cproHandleDenyAddr_l1
; we are in one of the three CLAIM_ADDRESS modes
rcall cproClaimNextFreeAddr ; claim next free address
brcs cproHandleDenyAddr_done
; no free address, abort TODO: send an error message to bus ("bus full")
ldi r16, CPRO_MODE_NORMAL
sts cproMode, r16
rjmp cproHandleDenyAddr_done
cproHandleDenyAddr_l1:
lds r17, cproMode
cpi r17, CPRO_MODE_RECLAIMING_ADDR
brne cproHandleDenyAddr_done
; reclaiming went wrong, go through full address assignment protocol
rcall CPRO_StartGetAddrProcedure
rjmp cproHandleDenyAddr_done
cproHandleDenyAddr_done:
rcall cproAddressSetTimer1s
sec
ret
@@ -297,40 +150,57 @@ cproHandleDenyAddr_done:
; REGS: r18, r19
;
cproAddressSetTimer1s:
ldi r18, 1
ldi r19, 0
rjmp cproAddressSetTimer
cproClaimFirstFreeAddr:
rjmp cproFindAndClaimFreeAddr
cproClaimNextFreeAddr:
lds r16, cproAddrRangeBegin
inc r16
sts cproAddrRangeBegin, r16
rjmp cproFindAndClaimFreeAddr
; IN:
; - R16: address to claim
; - r18: timer value (low)
; - r19: timer value (high)
; REGS: none
cproFindAndClaimFreeAddr:
cproAddressSetTimer:
push r15
in r15, SREG
cli
sts cproAddresModeTimer, r18
sts cproAddresModeTimer+1, r19
out SREG, r15
pop r15
ret
cproGetFirstFreeAddr:
rjmp cproGetFreeAddr
cproGetNextFreeAddr:
lds r16, cproAddrRangeBegin
inc r16
sts cproAddrRangeBegin, r16
rjmp cproGetFreeAddr
cproGetFreeAddr:
lds r16, cproAddrRangeBegin
lds r17, cproAddrRangeEnd
cp r16, r17
brge cproFindAndClaimFreeAddr_error
brge cproGetFreeAddr_error
rcall cproFindFreeAddr
brcc cproFindAndClaimFreeAddr_error
lds r19, cproAddrRangeBegin ; currently claimed address
rcall CPRO_EnqueueClaimAddress
ldi r16, CPRO_WAITTIME_CLAIMADDR
sts cproAddressWaitCounter, r16
ldi r16, CPRO_MODE_CLAIMING_ADDR1
sts cproMode, r16
brcc cproGetFreeAddr_error
sec
ret
cproFindAndClaimFreeAddr_error:
cproGetFreeAddr_error:
clc
ret
@@ -347,16 +217,6 @@ cproHandleAddrRange: ; not handled for now
cproEnterSendingHaveAddressMode:
ldi r17, 3
add r16, r17
sts cproAddressWaitCounter, r16 ; set counter to own address
ldi r16, CPRO_MODE_SENDING_HAVE_ADDRESS
sts cproMode, r16
ret
; ---------------------------------------------------------------------------
; cproFindFreeAddr
;
@@ -374,7 +234,7 @@ cproFindFreeAddr:
ldi xh, HIGH(cproUsedAddresses)
lds r16, cproAddrRangeBegin
dec r16
rcall CPRO_GetPosAndMaskInBitField ; r1=bit pos, r2=mask (r1, r2, r17, Z)
rcall cproGetPosAndMaskInBitField ; r1=bit pos, r2=mask (r1, r2, r17, Z)
clr r17
add xl, r1
adc xh, r17 ; X: pointer to byte
@@ -427,7 +287,7 @@ cproFindFreeAddr_allFull:
cproSetBitInBitfield:
; set bit corresponding to given address in bitfield of used addresses
rcall CPRO_GetPosAndMaskInBitField ; get offset into R1, mask into R2 (r1, r2, r17, Z)
rcall cproGetPosAndMaskInBitField ; get offset into R1, mask into R2 (r1, r2, r17, Z)
ldi xl, LOW(cproUsedAddresses)
ldi xh, HIGH(cproUsedAddresses)
clr r17
@@ -440,105 +300,6 @@ cproSetBitInBitfield:
; ---------------------------------------------------------------------------
; Enqueue a NEEDADDRESS packet.
;
; IN:
; - nothing
; OUT:
; - CFLAG: set if okay, clear otherwise
; MODIFIED REGS: R18 (R3, R4, R15, R16, R17, R20, R21, X, Y (R18, R19)
CPRO_EnqueueNeedAddress:
ldi r18, CPRO_CMD_NEED_ADDRESS
rjmp cproEnqueueAddressPacket
; ---------------------------------------------------------------------------
; Enqueue a HAVE_ADDRESS packet.
;
; IN:
; - nothing
; OUT:
; - CFLAG: set if okay, clear otherwise
; MODIFIED REGS: R18 (R3, R4, R15, R16, R17, R18, R19, R20, R21, X, Y)
CPRO_EnqueueHaveAddress:
ldi r18, CPRO_CMD_HAVE_ADDRESS
lds r19, comAddress
rjmp cproEnqueueAddressPacket
; ---------------------------------------------------------------------------
; Enqueue a CLAIM_ADDRESS packet.
;
; IN:
; - R19: claimed address
; OUT:
; - CFLAG: set if okay, clear otherwise
; MODIFIED REGS: R18 (R3, R4, R15, R16, R17, R18, R19, R20, R21, X, Y)
CPRO_EnqueueClaimAddress:
ldi r18, CPRO_CMD_CLAIM_ADDRESS
rjmp cproEnqueueAddressPacket
; ---------------------------------------------------------------------------
; Enqueue a DENY_ADDRESS packet.
;
; IN:
; - nothing
; OUT:
; - CFLAG: set if okay, clear otherwise
; MODIFIED REGS: R18, R19 (R3, R4, R15, R16, R17, R20, R21, X, Y)
CPRO_EnqueueDenyAddress:
ldi r18, CPRO_CMD_DENY_ADDRESS
lds r19, comAddress
rjmp cproEnqueueAddressPacket
; ---------------------------------------------------------------------------
; cproEnqueueAddressPacket
; Enqueue a NEED/HAVE/CLAIM ADDRESS packet.
;
; IN:
; - R18: command (either CPRO_CMD_NEED_ADDRESS, CPRO_CMD_HAVE_ADDRESS or CPRO_CMD_CLAIM_ADDRESS)
; - R19: address to send (claim, have)
; OUT:
; - CFLAG: set if okay, clear otherwise
; MODIFIED REGS: R16, R17, R20, R21, X, Y (R3, R4, R15, R16, R17, R18, R19, R21, X)
cproEnqueueAddressPacket:
mov r6, r19
rcall COM_AllocBufferAndGetXY ; (r16, r17, r21)
brcc cproEnqueueAddressPacket_error
ldi r16, 0xff
ldi r17, CPRO_PAYLOAD_FLAGS_UID | (1<<CPRO_PAYLOAD_FLAGS_SHIFT_NUM)
push xh
push xl
rcall cproBeginMsgWithVariablePayload ; (R3, R4, R16, R17, R18, R19, R20, R21, X)
st X+, r6 ; 5: value id
pop xl
pop xh
rcall comCalcAndAddChecksumByte ; (R16, R17, R18, R19, X)
; mark buffer as enqueued with PRIO "important" (higher retry count)
ldi r20, COM_BUFFER_PRIO_IMPORTANT
rcall COM_EnqueuePacket ; (R15, R16)
brcc cproEnqueueAddressPacket_error
sec
ret
cproEnqueueAddressPacket_error:
clc
ret
; ---------------------------------------------------------------------------
; Get offset and mask for a given bit in a bitfield
; IN:
@@ -548,7 +309,7 @@ cproEnqueueAddressPacket_error:
; - R2: mask for given id (apply to r1)
; USED REGISTERS: r1, r2, r17, Z
CPRO_GetPosAndMaskInBitField:
cproGetPosAndMaskInBitField:
mov r1, r16 ; divide by 8 to get the offset to the byte containing the given module id
lsr r1
lsr r1
@@ -559,9 +320,9 @@ CPRO_GetPosAndMaskInBitField:
ldi zh, HIGH(cproModuleBitNumToMaskMap*2)
ldi zl, LOW(cproModuleBitNumToMaskMap*2)
add zl, r2
brcc CPRO_GetPosAndMaskInBitField_noOverflow
brcc cproGetPosAndMaskInBitField_noOverflow
inc zh
CPRO_GetPosAndMaskInBitField_noOverflow:
cproGetPosAndMaskInBitField_noOverflow:
lpm r2, z ; r2=mask for bit in byte from bitfield
ret
@@ -570,3 +331,100 @@ cproModuleBitNumToMaskMap:
.db 1, 2, 4, 8, 16, 32, 64, 128
; ---------------------------------------------------------------------------
; Send a NEEDADDRESS packet.
;
; IN:
; - nothing
; OUT:
; - CFLAG: set if okay, clear otherwise
; MODIFIED REGS: R18 (R3, R4, R15, R16, R17, R20, R21, X, Y (R18, R19)
CPRO_SendNeedAddress:
ldi r18, CPRO_CMD_NEED_ADDRESS
rjmp cproSendAddressPacket
; ---------------------------------------------------------------------------
; Send a HAVE_ADDRESS packet.
;
; IN:
; - nothing
; OUT:
; - CFLAG: set if okay, clear otherwise
; MODIFIED REGS: R18 (R3, R4, R15, R16, R17, R18, R19, R20, R21, X, Y)
CPRO_SendHaveAddress:
ldi r18, CPRO_CMD_HAVE_ADDRESS
lds r19, com2Address
rjmp cproSendAddressPacket
; ---------------------------------------------------------------------------
; Send a CLAIM_ADDRESS packet.
;
; IN:
; - R19: claimed address
; OUT:
; - CFLAG: set if okay, clear otherwise
; MODIFIED REGS: R18 (R3, R4, R15, R16, R17, R18, R19, R20, R21, X, Y)
CPRO_SendClaimAddress:
ldi r18, CPRO_CMD_CLAIM_ADDRESS
rjmp cproSendAddressPacket
; ---------------------------------------------------------------------------
; Send a DENY_ADDRESS packet.
;
; IN:
; - nothing
; OUT:
; - CFLAG: set if okay, clear otherwise
; MODIFIED REGS: R18, R19 (R3, R4, R15, R16, R17, R20, R21, X, Y)
CPRO_SendDenyAddress:
ldi r18, CPRO_CMD_DENY_ADDRESS
lds r19, com2Address
rjmp cproSendAddressPacket
; ---------------------------------------------------------------------------
; cproSendAddressPacket
; Send a NEED/HAVE/CLAIM ADDRESS packet.
;
; IN:
; - R18: command (either CPRO_CMD_NEED_ADDRESS, CPRO_CMD_HAVE_ADDRESS or CPRO_CMD_CLAIM_ADDRESS)
; - R19: address to send (claim, have)
; OUT:
; - CFLAG: set if okay, clear otherwise
; MODIFIED REGS: R16, R17, R20, R21, X, Y (R3, R4, R15, R16, R17, R18, R19, R21, X)
cproSendAddressPacket:
ldi xl, LOW(com2SendBuffer)
ldi xh, HIGH(com2SendBuffer)
mov r6, r19
ldi r16, 0xff
ldi r17, COM2_PAYLOAD_FLAGS_UID | (1<<COM2_PAYLOAD_FLAGS_SHIFT_NUM)
rcall COM2_BeginMsgWithVariablePayload ; (R3, R4, R16, R17, R18, R19, R20, R21, X)
st X+, r6 ; address
ldi xl, LOW(com2SendBuffer)
ldi xh, HIGH(com2SendBuffer)
rcall com2CalcAndAddChecksumByte ; (R16, R17, R18, R19, X)
rjmp COM2_SendPacket
.include "comproto_addr1.asm"
.include "comproto_addr2.asm"
#endif ; MODULES_COM_WITH_ADDR_PROTO

163
avr/comproto_addr1.asm Normal file
View File

@@ -0,0 +1,163 @@
; ***************************************************************************
; 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. *
; ***************************************************************************
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; This file contains timer handlers for the address protocol
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; ***************************************************************************
; code
.cseg
CPRO_Address_OnTimer:
lds r16, cproMode
ldi r17, CPRO_MODE_NEXT_FREE
ldi zl, LOW(cproAddressOnTimerTable)
ldi zh, HIGH(cproAddressOnTimerTable)
rjmp Utils_TableJump
cproAddressOnTimerTable:
.dw CPRO_StartReclaimAddrProcedure ; CPRO_MODE_NOADDRESS
.dw 0 ; CPRO_MODE_NORMAL
.dw cproHandle1sNeedAddr ; CPRO_MODE_SEND_NEED_ADDR
.dw cproHandle1sGetAddrStarted ; CPRO_MODE_GETADDRSTARTED
.dw cproHandle1sSendClaimAddr1 ; CPRO_MODE_SEND_CLAIM_ADDR1
.dw cproHandle1sClaimingAddr12 ; CPRO_MODE_CLAIMING_ADDR1
.dw cproHandle1sClaimingAddr12 ; CPRO_MODE_CLAIMING_ADDR2
.dw cproHandle1sClaimingAddr3 ; CPRO_MODE_CLAIMING_ADDR3
.dw cproHandle1sSendingHaveAddress ; CPRO_MODE_SENDING_HAVE_ADDR
.dw cproHandle1sSendReclaimAddr ; CPRO_MODE_SEND_RECLAIM_ADDR
.dw cproHandle1sReclaimingAddr ; CPRO_MODE_RECLAIMING_ADDR
.dw cproHandle1sSendDenyAddr ; CPRO_MODE_SEND_DENY_ADDR
cproHandle1sSendingHaveAddress:
rcall CPRO_SendHaveAddress
brcs cproHandle1sSendingHaveAddress_okay
rcall cproAddressSetTimer1s ; could not send, restart timer 1s and retry later
ret
cproHandle1sSendingHaveAddress_okay:
ldi r16, CPRO_MODE_NORMAL
sts cproMode, r16
ret
cproHandle1sNeedAddr:
rcall CPRO_SendNeedAddress
brcs cproHandle1sNeedAddr_okay
rjmp cproAddressSetTimer1s ; could not send, restart timer 1s and retry later
cproHandle1sNeedAddr_okay:
ldi r16, CPRO_MODE_GETADDRSTARTED ; wait for incoming messages
sts cproMode, r16
ldi r18, CPRO_WAITTIME_GETADDR ; set timeout
clr r19
rjmp cproAddressSetTimer
cproHandle1sSendDenyAddr:
rcall CPRO_SendDenyAddress
brcs cproHandle1sSendDenyAddr_okay
rjmp cproAddressSetTimer1s ; could not send, restart timer 1s and retry later
cproHandle1sSendDenyAddr_okay:
ldi r16, CPRO_MODE_NORMAL ; DENY_ADDR sent, back to normal
sts cproMode, r16
ret
cproHandle1sSendReclaimAddr:
lds r19, cproAddrRangeBegin
rcall CPRO_SendClaimAddress
brcs cproHandle1sSendReclaimAddr_okay
rjmp cproAddressSetTimer1s ; could not send, restart timer 1s and retry later
cproHandle1sSendReclaimAddr_okay:
ldi r16, CPRO_MODE_RECLAIMING_ADDR
sts cproMode, r16
ldi r18, CPRO_WAITTIME_RECLAIMADDR
clr r19
rjmp cproAddressSetTimer ; prepare time for next stage
cproHandle1sGetAddrStarted:
rcall cproGetFirstFreeAddr
brcs cproHandle1sGetAddrStarted_gotAddr
; no free address, abort TODO: send an error message to bus ("bus full")
ldi r16, CPRO_MODE_NOADDRESS
sts cproMode, r16
ret
cproHandle1sGetAddrStarted_gotAddr:
ldi r16, CPRO_MODE_SEND_CLAIM_ADDR1
sts cproMode, r16
rjmp cproAddressSetTimer1s ; start
cproHandle1sSendClaimAddr1:
lds r19, cproAddrRangeBegin
rcall CPRO_SendClaimAddress
brcs cproHandle1sClaimSend_okay
rjmp cproAddressSetTimer1s ; could not send, restart timer 1s and retry later
cproHandle1sClaimSend_okay: ; goto nex stage
ldi r16, CPRO_MODE_CLAIMING_ADDR1
sts cproMode, r16
ldi r18, CPRO_WAITTIME_CLAIMADDR
clr r19
rjmp cproAddressSetTimer ; prepare timer for next stage
cproHandle1sClaimingAddr12:
lds r19, cproAddrRangeBegin ; currently claimed address
rcall CPRO_SendClaimAddress
brcs cproHandle1sClaimingAddr12_okay
rjmp cproAddressSetTimer1s ; could not send, restart timer 1s and retry later
cproHandle1sClaimingAddr12_okay:
lds r16, cproMode
inc r16
sts cproMode, r16
ldi r18, CPRO_WAITTIME_CLAIMADDR
clr r19
rjmp cproAddressSetTimer ; prepare time for next stage
cproHandle1sClaimingAddr3:
cproHandle1sReclaimingAddr:
; claimed given address 3rd time or addr reclaimed, set address and enter "normal" mode
lds r19, cproAddrRangeBegin ; currently claimed address
rcall CPRO_SendHaveAddress
brcs cproHandle1sClaimingAddr3_okay
rjmp cproAddressSetTimer1s ; could not send, restart timer 1s and retry later
cproHandle1sClaimingAddr3_okay:
in r15, SREG
cli
lds r16, cproAddrRangeBegin ; currently sent address is in cproAddrRangeBegin
sts com2Address, r16 ; write address into eeprom
ldi xl, LOW(EEPROM_OFFS_COMADDR)
ldi xh, HIGH(EEPROM_OFFS_COMADDR)
rcall Utils_WriteEepromIncr ; write address to EEPROM
out SREG, r15
ldi r16, CPRO_MODE_NORMAL ; set mode to "normal"
sts cproMode, r16
ret

167
avr/comproto_addr2.asm Normal file
View File

@@ -0,0 +1,167 @@
; ***************************************************************************
; 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. *
; ***************************************************************************
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; This file contains packet receiption handlers for the address protocol
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; ***************************************************************************
; code
.cseg
; ---------------------------------------------------------------------------
; CPRO_Address_OnPacketReceived:
;
; Try to handle the given packet.
;
; IN:
; - X : pointer to received buffer
; OUT:
; - CFLAG: set if handled, cleared otherwise
; USED: depending on called routines
CPRO_Address_OnPacketReceived:
adiw xh:xl, COM2_MSG_OFFS_CMD
ld r16, x
sbiw xh:xl, COM2_MSG_OFFS_CMD
ldi r17, (cproPacketTypeTransTableEnd-cproPacketTypeTransTableBegin) & 0xff
ldi zl, LOW(cproPacketTypeTransTableBegin)
ldi zh, HIGH(cproPacketTypeTransTableBegin)
rcall Utils_FindBytePositionInTable
brcc CPRO_Address_OnPacketReceived_nc
ldi r17, (cproPacketTypeTransTableEnd-cproPacketTypeTransTableBegin) & 0xff
ldi zl, LOW(cproPacketTypeHandleTable)
ldi zh, HIGH(cproPacketTypeHandleTable)
rcall Utils_TableJump
sec
ret
CPRO_Address_OnPacketReceived_nc:
clc
ret
cproPacketTypeTransTableBegin:
.db CPRO_CMD_PING, CPRO_CMD_NEED_ADDRESS, CPRO_CMD_HAVE_ADDRESS, CPRO_CMD_ADDRESS_RANGE, CPRO_CMD_DENY_ADDRESS, CPRO_CMD_CLAIM_ADDRESS
cproPacketTypeTransTableEnd:
; position within table must be in same order as in table above!
cproPacketTypeHandleTable:
.dw cproHandlePing, cproHandleNeedAddr, cproHandlePckHaveAddr, cproHandleAddrRange, cproHandleDenyAddr, cproHandleClaimAddr
cproHandleNeedAddr:
lds r17, cproMode
cpi r17, CPRO_MODE_NORMAL
brne cproHandleNeedAddr_done
; enter CPRO_MODE_SENDING_HAVE_ADDR mode
lds r16, com2Address
tst r16
breq cproHandleNeedAddr_done ; we have no address, don't handle
ldi r24, CPRO_MODE_SENDING_HAVE_ADDR ; start singleshot timer for sending HAVE_ADDRESS
sts cproMode, r24
lds r24, com2Address
clr r25
adiw r25:r24, 3
rjmp cproAddressSetTimer
cproHandleNeedAddr_done:
sec
ret
cproHandlePckHaveAddr:
lds r17, cproMode
cpi r17, CPRO_MODE_GETADDRSTARTED
brne cproHandlePckHaveAddr_done
; validate address
adiw xh:xl, CPRO_PACKET_HAVEADDR_OFFS_ADDRESS
ld r16, x
tst r16
breq cproHandlePckHaveAddr_done ; invalid address, ignore
cpi r16, 127
brcc cproHandlePckHaveAddr_done ; invalid address, ignore
; set bit corresponding to given address in bitfield of used addresses
dec r16
rcall cproSetBitInBitfield
cproHandlePckHaveAddr_done:
sec
ret
cproHandleClaimAddr:
adiw xh:xl, CPRO_PACKET_CLAIMADDR_OFFS_ADDRESS
ld r16, x
tst r16
breq cproHandleClaimAddr_done
cpi r16, 0xff
breq cproHandleClaimAddr_done
lds r17, com2Address
tst r17
breq cproHandleClaimAddr_done
cp r16, r17
brne cproHandleClaimAddr_done
ldi r16, CPRO_MODE_SEND_DENY_ADDR
sts cproMode, r16
rcall cproAddressSetTimer1s
cproHandleClaimAddr_done:
sec
ret
cproHandleDenyAddr:
; check mode
lds r17, cproMode
cpi r17, CPRO_MODE_CLAIMING_ADDR1
brcs cproHandleDenyAddr_notInClaimAddr13Mode
cpi r17, CPRO_MODE_CLAIMING_ADDR3+1
brcc cproHandleDenyAddr_notInClaimAddr13Mode
; we are in one of the three CLAIM_ADDRESS modes and received a DENY_ADDR, check address
adiw xh:xl, CPRO_PACKET_CLAIMADDR_OFFS_ADDRESS
ld r16, x
sbiw xh:xl, CPRO_PACKET_CLAIMADDR_OFFS_ADDRESS
lds r17, cproAddrRangeBegin
cp r16, r17
brne cproHandleDenyAddr_done ; not our currently claimed address, ignore
; someone denied us our claimed address, try next
rcall cproGetNextFreeAddr
brcs cproHandleDenyAddr_gotFreeAddr
; no free address, abort TODO: send an error message to bus ("bus full")
ldi r16, CPRO_MODE_NOADDRESS
sts cproMode, r16
ret
cproHandleDenyAddr_gotFreeAddr: ; claim next address
ldi r16, CPRO_MODE_SEND_CLAIM_ADDR1
sts cproMode, r16
rcall cproAddressSetTimer1s ; start timer
rjmp cproHandleDenyAddr_done
cproHandleDenyAddr_notInClaimAddr13Mode: ; reclaim mode?
lds r17, cproMode
cpi r17, CPRO_MODE_RECLAIMING_ADDR
brne cproHandleDenyAddr_done
; reclaiming went wrong, go through full address assignment protocol
rcall CPRO_StartGetAddrProcedure
cproHandleDenyAddr_done:
sec
ret

33
avr/comproto_ping.asm Normal file
View File

@@ -0,0 +1,33 @@
; ***************************************************************************
; 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. *
; ***************************************************************************
; ***************************************************************************
; code
.cseg
; ---------------------------------------------------------------------------
; Write a PING packet.
;
; IN:
; - R16: destination address
; - X : buffer to write to
; OUT:
; - nothing
; REGS: R3, R4, R16, R17, R18, X (R19, R20, R21)
CPRO_WritePing:
ldi r18, CPRO_CMD_PING
rjmp COM2_WriteMsgWithCmdAndSrcAddr

33
avr/comproto_pong.asm Normal file
View File

@@ -0,0 +1,33 @@
; ***************************************************************************
; 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. *
; ***************************************************************************
; ***************************************************************************
; code
.cseg
; ---------------------------------------------------------------------------
; Write a PONG packet.
;
; IN:
; - R16: destination address
; - X : buffer to write to
; OUT:
; - nothing
; REGS: R3, R4, R16, R17, R18, X (R19, R20, R21)
CPRO_WritePong:
ldi r18, CPRO_CMD_PONG
rjmp COM2_WriteMsgWithCmdAndSrcAddr

View File

@@ -0,0 +1,58 @@
; ***************************************************************************
; 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. *
; ***************************************************************************
; ***************************************************************************
; code
.cseg
; ---------------------------------------------------------------------------
; Write a COM reception stats packet.
;
; IN:
; - R16: destination address
; - X : buffer to write to
; OUT:
; - nothing
; REGS: R3, R4, R16, R17, R18, X (R19, R20, R21)
CPRO_WriteComRecvStats:
ldi r17, COM2_PAYLOAD_FLAGS_UID | (8<<COM2_PAYLOAD_FLAGS_SHIFT_NUM) ; seconds + 8 bytes payload
ldi r18, CPRO_CMD_COMRECVSTATS
push xh
push xl
rcall COM2_BeginMsgWithVariablePayload ; (R3, R4, R16, R17, R18, R19, R20, R21, X)
lds r16, com2StatsPacketsIn ; packets in
st X+, r16
lds r16, com2StatsPacketsIn+1
st X+, r16
lds r16, com2StatsContentError ; CRC errors
st X+, r16
lds r16, com2StatsContentError+1
st X+, r16
lds r16, com2StatsIoError ; IO errors
st X+, r16
lds r16, com2StatsIoError+1
st X+, r16
lds r16, com2StatsNoBufferError ; no buffer
st X+, r16
lds r16, com2StatsNoBufferError+1
st X+, r16
pop xl
pop xh
rcall com2CalcAndAddChecksumByte ; (R16, R17, R18, R19, X)
ret

View File

@@ -0,0 +1,53 @@
; ***************************************************************************
; 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. *
; ***************************************************************************
; ***************************************************************************
; code
.cseg
; ---------------------------------------------------------------------------
; Write a ComSendStats packet.
;
; IN:
; - R16: destination address
; - X : buffer to write to
; OUT:
; - nothing
; REGS: R3, R4, R16, R17, R18, X (R19, R20, R21)
CPRO_WriteComSendStats:
ldi r17, COM2_PAYLOAD_FLAGS_UID | (6<<COM2_PAYLOAD_FLAGS_SHIFT_NUM) ; UID + 6 bytes payload
ldi r18, CPRO_CMD_COMSENDSTATS
push xh
push xl
rcall COM2_BeginMsgWithVariablePayload ; (R3, R4, R16, R17, R18, R19, R20, R21, X)
lds r16, com2StatsPacketsOut ; packets out
st X+, r16
lds r16, com2StatsPacketsOut+1
st X+, r16
lds r16, com2StatsCollisions ; collisions
st X+, r16
lds r16, com2StatsCollisions+1
st X+, r16
lds r16, com2StatsBusyError ; busy
st X+, r16
lds r16, com2StatsBusyError+1
st X+, r16
pop xl
pop xh
rcall comCalcAndAddChecksumByte ; (R16, R17, R18, R19, X)
ret

View File

@@ -134,39 +134,42 @@ LCD_Fini:
LCD_SetCursor:
in r15, SREG
cli
mov r1, r18
mov r2, r19
rcall twiStart ; (R22)
ldi r16, (LCD_TWI_ADDRESS*2)
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_SetCursor_error
ldi r16, LCD_CMD_MODE
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_SetCursor_error
mov r16, r2
andi r16, 0x07
ori r16, 0xb0 ; Set Page Start Address for Page Addressing Mode
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_SetCursor_error
mov r16, r1
andi r16, 0x0f ; Set Lower Column Start Address
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_SetCursor_error
mov r16, r1
swap r16
andi r16, 0x0f
ori r16, 0x10 ; Set Higher Column Start Address
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_SetCursor_error
rcall twiStop ; (R22)
push r15
cli
mov r1, r18
mov r2, r19
rcall twiStart ; (R22)
ldi r16, (LCD_TWI_ADDRESS*2)
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_SetCursor_error
ldi r16, LCD_CMD_MODE
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_SetCursor_error
mov r16, r2
andi r16, 0x07
ori r16, 0xb0 ; Set Page Start Address for Page Addressing Mode
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_SetCursor_error
mov r16, r1
andi r16, 0x0f ; Set Lower Column Start Address
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_SetCursor_error
mov r16, r1
swap r16
andi r16, 0x0f
ori r16, 0x10 ; Set Higher Column Start Address
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_SetCursor_error
rcall twiStop ; (R22)
pop r15
out SREG, r15
sec
ret
LCD_SetCursor_error:
rcall twiStop ; (R22)
rcall twiStop ; (R22)
pop r15
out SREG, r15
clc
ret
@@ -295,23 +298,26 @@ LCD_PrintFromFlash_error:
LCD_PrintChar:
in r15, SREG
cli
rcall twiStart
ldi r16, (LCD_TWI_ADDRESS*2)
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_PrintChar_error
ldi r16, LCD_DATA_MODE
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_PrintChar_error
rcall lcdPrintOneChar
brcc LCD_PrintChar_error
rcall twiStop
push r15
cli
rcall twiStart
ldi r16, (LCD_TWI_ADDRESS*2)
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_PrintChar_error
ldi r16, LCD_DATA_MODE
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
brcc LCD_PrintChar_error
rcall lcdPrintOneChar
brcc LCD_PrintChar_error
rcall twiStop
pop r15
out SREG, r15
sec
ret
LCD_PrintChar_error:
rcall twiStop
rcall twiStop
pop r15
out SREG, r15
clc
ret

View File

@@ -66,7 +66,7 @@ main:
main_loop:
rcall runModulesUntilIdle
; sbi DDRA, PORTA2 ; debug
sbi DDRA, PORTA2 ; debug
; sbi PINA, PORTA2 ; debug (toggle)
; cbi PORTA, PORTA2 ; debug (on)
; sbi PORTA, PORTA2 ; debug (off)
@@ -111,8 +111,8 @@ initModules:
#endif
#ifdef MODULES_COM
rcall Com_Init ; init COM module
rcall CPRO_Init ; init COM protocol module
rcall Com2_Init ; init COM module
rcall CPRO_Init ; init COM protocol module
#endif
#ifdef MODULES_TWI_MASTER
rcall TWI_Master_Init
@@ -152,16 +152,17 @@ runModulesUntilIdle:
#endif
#ifdef MODULES_COM
; COM module (call until carry flag cleared but at most 10 times to not starve other modules)
; COM module (call until carry flag cleared but at most 10 times to not starve other modules)
ldi r16, 10
runModulesUntilIdle_Com:
push r16
rcall Com_Run
rcall Com2_Run
pop r16
brcc runModulesUntilIdle_ComEnd
dec r16
brne runModulesUntilIdle_Com
runModulesUntilIdle_ComEnd:
runModulesUntilIdle_ComEnd:
#endif
; add more modules here
@@ -206,9 +207,94 @@ initialWait_l2: ; wait for 10ms
#ifdef MODULES_LCD
printSendStats:
printStartSendPackage:
in r15, SREG ; debug
push r15
cli
ldi r18, 1
ldi r19, 3
rcall LCD_SetCursor
ldi r16, 'S'
rcall LCD_PrintChar
ldi r16, ' '
rcall LCD_PrintChar
pop r15
out SREG, r15
ret
printEndSendPackage:
in r15, SREG ; debug
push r15
cli
ldi r18, 2
ldi r19, 3
rcall LCD_SetCursor
ldi r16, 'E'
rcall LCD_PrintChar
pop r15
out SREG, r15
ret
printTimerMark:
in r15, SREG ; debug
push r15
cli
ldi r18, 1
ldi r19, 1
rcall LCD_SetCursor
lds r16, timerModuleCounterSecs
rcall LCD_PrintHexByte
pop r15
out SREG, r15
ret
printSendStats:
in r15, SREG ; debug
push r15
cli
ldi r18, 1
ldi r19, 5
rcall LCD_SetCursor
ldi zl, LOW(textStatsPacketsIn)
ldi zh, HIGH(textStatsPacketsIn)
rcall LCD_PrintFromFlash
lds r18, com2StatsPacketsIn
lds r19, com2StatsPacketsIn+1
rcall LCD_PrintHexWord
ldi r18, 1
ldi r19, 6
rcall LCD_SetCursor
ldi zl, LOW(textStatsPacketsOut)
ldi zh, HIGH(textStatsPacketsOut)
rcall LCD_PrintFromFlash
lds r18, com2StatsPacketsOut
lds r19, com2StatsPacketsOut+1
rcall LCD_PrintHexWord
ldi r18, 1
ldi r19, 7
rcall LCD_SetCursor
ldi zl, LOW(textStatsPacketsRecvErr)
ldi zh, HIGH(textStatsPacketsRecvErr)
rcall LCD_PrintFromFlash
lds r18, com2StatsBusyError
lds r19, com2StatsBusyError+1
rcall LCD_PrintHexWord
pop r15
out SREG, r15
ret
#if 0
printSendStats:
in r15, SREG ; debug
push r15
in r15, SREG ; debug
cli
ldi r18, 0
@@ -290,6 +376,7 @@ printSendStats:
pop r15
out SREG, r15
ret
#endif ; if 0
#endif
@@ -297,11 +384,12 @@ printSendStats:
#ifdef MODULES_SI7021
#ifdef MODULES_COM
#if 0
Main_SendValueMsg:
in r15, SREG
push r15
cli
lds r16, comAddress ; do we have an address assigned?
lds r16, com2Address ; do we have an address assigned?
tst r16
breq sendValueMsg_done ; no, do nothing
; send message for current temp
@@ -337,6 +425,7 @@ sendValueMsg_done:
pop r15
out SREG, r15
ret
#endif
#ifdef MODULES_LCD

View File

@@ -158,9 +158,12 @@ timerInitTimers_loop:
mov r18, xl
or r18, xh
breq timerInitTimers_end
mov r18, r20
or r18, r21
breq timerInitTimers_writeInitial
add r20, r16 ; add counter pos in table so that not all timers elapse at the same time
adc r21, r17
timerInitTimers_writeInitial:
st X+, r20
st X, r21
inc r16
@@ -173,7 +176,6 @@ timerInitTimers_end:
timerRunTimers:
; TODO: incremenent uptime counter
ldi xl, LOW(timerModuleCounterSecs)
ldi xh, HIGH(timerModuleCounterSecs)
rcall Utils_IncrementCounter32
@@ -187,7 +189,7 @@ timerRunTimers_loop:
mov r16, r22
andi r16, TIMER_FLAGS_IF_ADDR
breq timerRunTimers_l1 ; no need to check address
lds r16, comAddress ; check address
lds r16, com2Address ; check address
tst r16
breq timerRunTimers_loop ; no address, ignore counter
timerRunTimers_l1:

View File

@@ -529,6 +529,75 @@ Utils_WriteSeed:
; ---------------------------------------------------------------------------
; Utils_TableJump
;
; Jump to a routine using a jump table.
; IN:
; - r16: position to jump to
; - r17: number of entries in table
; - Z : pointer to table
; OUT:
; - depends on called function
; REGS: depends on called function
Utils_TableJump:
lds r16, cproMode
cp r16, r17
brcc Utils_TableJump_ret
clr r17
add zl, r16
adc zh, r17
lsl zl ; shift z left for LPM instruction
rol zh
lpm r16, z+ ; read pointer from table
lpm r17, z
tst r16
brne Utils_TableJump_jmp
tst r17
brne Utils_TableJump_jmp
Utils_TableJump_ret:
ret
Utils_TableJump_jmp:
push r16 ; jump via stack
push r17
ret
; ---------------------------------------------------------------------------
; Find position of a given code in a table.
;
; IN:
; - r16: value to translate
; - r17: number of entries
; - Z : pointer to table
; OUT:
; - CFLAG: set if translation found, cleared otherwise
; - r16: translated value
Utils_FindBytePositionInTable:
lsl zl ; shift z left for LPM instruction
rol zh
clr r19
Utils_TranslateByTable_loop:
lpm r18, z+
cp r18, r16
breq Utils_TranslateByTable_found
inc r19
dec r17
brne Utils_TranslateByTable_loop
clc
ret
Utils_TranslateByTable_found:
mov r16, r19
sec
ret
UTILS_END:
.equ MODULE_SIZE_UTILS = UTILS_END-UTILS_BEGIN