started reorganizing code into subfolders.
This commit is contained in:
180
avr/modules/bmp280/bmp280.asm
Normal file
180
avr/modules/bmp280/bmp280.asm
Normal file
@@ -0,0 +1,180 @@
|
||||
; ***************************************************************************
|
||||
; 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
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; data
|
||||
|
||||
.dseg
|
||||
|
||||
bmp280DataBegin:
|
||||
bmp280Id: .byte 1
|
||||
bmp280DataEnd:
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; code
|
||||
|
||||
.cseg
|
||||
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; BMP280_Init
|
||||
;
|
||||
; IN:
|
||||
; - nothing
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, clear on error
|
||||
; USED:
|
||||
|
||||
BMP280_Init:
|
||||
ldi xh, HIGH(bmp280DataBegin)
|
||||
ldi xl, LOW(bmp280DataBegin)
|
||||
clr r16
|
||||
ldi r17, (bmp280DataEnd-bmp280DataBegin)
|
||||
rcall Utils_FillSram
|
||||
|
||||
rcall bmp280ReadId
|
||||
brcc BMP280_Init_error
|
||||
sts bmp280Id, r16 ; store id
|
||||
sec
|
||||
ret
|
||||
BMP280_Init_error:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; BMP280_Fini
|
||||
;
|
||||
; IN:
|
||||
; - nothing
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, clear on error
|
||||
; USED:
|
||||
|
||||
BMP280_Fini:
|
||||
sec
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; bmp280ReadId
|
||||
;
|
||||
; IN:
|
||||
; - nothing
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, clear on error
|
||||
; - R16 : id (most probably 0x60)
|
||||
; USED: R15, R16 (R17, R18, R22)
|
||||
|
||||
bmp280ReadId:
|
||||
ldi r16, 0xd0
|
||||
rjmp bmp280ReadSingleReg
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; bmp280ReadSingleReg
|
||||
;
|
||||
; IN:
|
||||
; - R16: register id
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, clear on error
|
||||
; - R16 : register content
|
||||
; USED: R1, R15, R16 (R17, R18, R22)
|
||||
|
||||
bmp280ReadSingleReg:
|
||||
in r15, SREG
|
||||
cli
|
||||
mov r1, r16
|
||||
rcall twiStart ; (R22)
|
||||
ldi r16, (BMP280_ADDR*2) ; start in write mode
|
||||
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
|
||||
brcc bmp280ReadSingleReg_error
|
||||
mov r16, r1 ; register num
|
||||
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
|
||||
brcc bmp280ReadSingleReg_error
|
||||
rcall twiRestart ; (R22)
|
||||
ldi r16, (BMP280_ADDR*2)+1 ; restart in read mode
|
||||
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
|
||||
brcc bmp280ReadSingleReg_error
|
||||
|
||||
rcall twiReceiveByteSendAck ; read ID
|
||||
brcc bmp280ReadSingleReg_error
|
||||
rcall twiStop ; (R22)
|
||||
out SREG, r15
|
||||
sec
|
||||
ret
|
||||
bmp280ReadSingleReg_error:
|
||||
rcall twiStop ; (R22)
|
||||
out SREG, r15
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; bmp280ReadRegsToSram
|
||||
;
|
||||
; IN:
|
||||
; - X: pointer to buffer to read data in
|
||||
; - R18: first register to read from
|
||||
; - R19: number of registers to read
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, clear on error
|
||||
; - R16 : id (most probably 0x60)
|
||||
; USED: R15, R16 (R17, R18, R22)
|
||||
|
||||
bmp280ReadRegsToSram:
|
||||
in r15, SREG
|
||||
cli
|
||||
mov r1, r18
|
||||
mov r2, r19
|
||||
rcall twiStart ; (R22)
|
||||
ldi r16, (BMP280_ADDR*2) ; start in write mode
|
||||
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
|
||||
brcc bmp280ReadRegsToSram_error
|
||||
|
||||
mov r16, r1 ; first register to read
|
||||
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
|
||||
brcc bmp280ReadRegsToSram_error
|
||||
rcall twiRestart ; (R22)
|
||||
ldi r16, (BMP280_ADDR*2)+1 ; restart in read mode
|
||||
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
|
||||
brcc bmp280ReadRegsToSram_error
|
||||
bmp280ReadRegsToSram_loop:
|
||||
rcall twiReceiveByteSendAck ; read register content
|
||||
brcc bmp280ReadRegsToSram
|
||||
st x+, r16 ; store register content
|
||||
dec r2
|
||||
brne bmp280ReadRegsToSram_loop
|
||||
rcall twiStop ; (R22)
|
||||
out SREG, r15
|
||||
sec
|
||||
ret
|
||||
bmp280ReadRegsToSram_error:
|
||||
rcall twiStop ; (R22)
|
||||
out SREG, r15
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
432
avr/modules/com2/com2.asm
Normal file
432
avr/modules/com2/com2.asm
Normal file
@@ -0,0 +1,432 @@
|
||||
; ***************************************************************************
|
||||
; 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. *
|
||||
; ***************************************************************************
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; data
|
||||
|
||||
.dseg
|
||||
|
||||
|
||||
com2DataBegin:
|
||||
com2Address: .byte 1
|
||||
|
||||
com2Interrupts: .byte 2
|
||||
|
||||
com2StatsPacketsIn: .byte 2
|
||||
|
||||
com2StatsIoError: .byte 2
|
||||
com2StatsContentError: .byte 2
|
||||
com2StatsNoBufferError: .byte 2
|
||||
com2StatsIgnored: .byte 2
|
||||
com2StatsHandled: .byte 2
|
||||
com2StatsMissed: .byte 2 ; currently not used
|
||||
|
||||
com2StatsPacketsOut: .byte 2
|
||||
com2StatsBusyError: .byte 2
|
||||
com2StatsCollisions: .byte 2
|
||||
|
||||
|
||||
com2RecvBuffersUsed: .byte 1
|
||||
com2MaxBuffersUsed: .byte 1
|
||||
com2RecvBuffersWritePos: .byte 1
|
||||
com2RecvBuffersReadPos: .byte 1
|
||||
|
||||
com2RecvBuffers: .byte COM2_BUFFER_SIZE*COM2_BUFFER_NUM
|
||||
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:
|
||||
rjmp com2HandleNextPacketInQueue
|
||||
|
||||
|
||||
|
||||
com2HandleNextPacketInQueue:
|
||||
lds r16, com2RecvBuffersUsed
|
||||
tst r16
|
||||
breq com2HandleNextPacketInQueue_retNc ; no buffers in use
|
||||
|
||||
lds r16, com2RecvBuffersReadPos
|
||||
rcall COM2_BufferPosToX ; get current read buffer to X (R16, R17)
|
||||
rcall onPacketReceived
|
||||
brcs com2HandleNextPacketInQueue_handled
|
||||
ldi xl, LOW(com2StatsIgnored)
|
||||
ldi xh, HIGH(com2StatsIgnored)
|
||||
rjmp com2HandleNextPacketInQueue_incCounterDeallocBuffer
|
||||
com2HandleNextPacketInQueue_handled:
|
||||
ldi xl, LOW(com2StatsHandled)
|
||||
ldi xh, HIGH(com2StatsHandled)
|
||||
com2HandleNextPacketInQueue_incCounterDeallocBuffer:
|
||||
rcall Utils_IncrementCounter16 ; (r18, r19, r22)
|
||||
rcall COM2_BufferDeallocFront ; (r16, r17, r21)
|
||||
sec ; always return with set CFLAG
|
||||
ret
|
||||
com2HandleNextPacketInQueue_retNc:
|
||||
clc
|
||||
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
|
||||
; 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:
|
||||
rcall COM2_BufferAlloc ; (r16, r17, r21)
|
||||
brcs 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:
|
||||
push xl
|
||||
push xh
|
||||
lds r16, com2Address
|
||||
ldi r17, (COM2_BUFFER_SIZE-3)
|
||||
rcall com2ReceivePacketRaw
|
||||
pop xh
|
||||
pop xl
|
||||
brcc com2ReceivePacket_error
|
||||
|
||||
rcall com2CheckMessageInBuffer ; (R16, R17, R18, R19, R20, X)
|
||||
brcc com2ReceivePacket_dataError
|
||||
|
||||
; everything okay
|
||||
ldi xl, LOW(com2StatsPacketsIn)
|
||||
ldi xh, HIGH(com2StatsPacketsIn)
|
||||
rcall Utils_IncrementCounter16 ; (r18, r19, 22)
|
||||
sec
|
||||
ret
|
||||
|
||||
com2ReceivePacket_error:
|
||||
cpi r16, COM2_ERROR_IOERROR
|
||||
breq com2ReceivePacket_ioError
|
||||
cpi r16, COM2_ERROR_DATAERROR
|
||||
breq com2ReceivePacket_dataError
|
||||
rjmp com2ReceivePacket_retnc
|
||||
com2ReceivePacket_ioError:
|
||||
ldi xl, LOW(com2StatsIoError)
|
||||
ldi xh, HIGH(com2StatsIoError)
|
||||
rjmp com2ReceivePacket_incCounterDeallocNc
|
||||
com2ReceivePacket_dataError:
|
||||
ldi xl, LOW(com2StatsContentError)
|
||||
ldi xh, HIGH(com2StatsContentError)
|
||||
rjmp com2ReceivePacket_incCounterDeallocNc
|
||||
com2ReceivePacket_incCounterDeallocNc:
|
||||
rcall Utils_IncrementCounter16 ; (r18, r19, 22)
|
||||
com2ReceivePacket_deallocRetnc:
|
||||
rcall COM2_BufferDeallocBack
|
||||
com2ReceivePacket_retnc:
|
||||
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:
|
||||
rcall COM2_SendPacketWithAttn
|
||||
brcs COM2_SendPacket_okay
|
||||
|
||||
cpi r16, COM2_ERROR_BUSY
|
||||
breq COM2_SendPacket_busyError
|
||||
cpi r16, COM2_ERROR_COLLISION
|
||||
breq COM2_SendPacket_collError
|
||||
|
||||
COM2_SendPacket_busyError:
|
||||
ldi xl, LOW(com2StatsBusyError)
|
||||
ldi xh, HIGH(com2StatsBusyError)
|
||||
rjmp COM2_SendPacket_incCounterRetNc
|
||||
COM2_SendPacket_collError:
|
||||
ldi xl, LOW(com2StatsCollisions)
|
||||
ldi xh, HIGH(com2StatsCollisions)
|
||||
COM2_SendPacket_incCounterRetNc:
|
||||
rcall Utils_IncrementCounter16 ; (r18, r19, r22)
|
||||
clc
|
||||
ret
|
||||
COM2_SendPacket_okay:
|
||||
ldi xl, LOW(com2StatsPacketsOut)
|
||||
ldi xh, HIGH(com2StatsPacketsOut)
|
||||
rcall Utils_IncrementCounter16 ; (r18, r19, r22)
|
||||
sec
|
||||
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
|
||||
push r15
|
||||
rcall com2ReceivePacket ; (r16, r17, r18, r19, r20, r21, r22, x)
|
||||
pop r15
|
||||
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:
|
||||
out SREG, r15
|
||||
pop r15
|
||||
reti
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.include "modules/com2/com2_packets.asm"
|
||||
.include "modules/com2/com2_lowlevel.asm"
|
||||
.include "modules/com2/com2_buffer.asm"
|
||||
.include "modules/com2/com2_crc.asm"
|
||||
|
||||
|
||||
|
||||
COM2_END:
|
||||
.equ MODULE_SIZE_COM2 = COM2_END-COM2_BEGIN
|
||||
|
||||
170
avr/modules/com2/com2_buffer.asm
Normal file
170
avr/modules/com2/com2_buffer.asm
Normal file
@@ -0,0 +1,170 @@
|
||||
; ***************************************************************************
|
||||
; 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. *
|
||||
; ***************************************************************************
|
||||
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; COM_BufferAlloc
|
||||
;
|
||||
; Allocate a transfer buffer.
|
||||
; IN:
|
||||
; - nothing
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, clear otherwise
|
||||
; - X: pointer to allocated buffer in SRAM
|
||||
; MODIFIED REGISTERS: r16, r17, r21
|
||||
|
||||
|
||||
COM2_BufferAlloc:
|
||||
in r21, SREG ; save global interrupt enable bit from SREG
|
||||
cli
|
||||
lds r17, com2RecvBuffersUsed
|
||||
cpi r17, COM2_BUFFER_NUM
|
||||
brcc COM2_AllocBuffer_error ; no buffer available
|
||||
inc r17 ; increment number of buffers used
|
||||
sts com2RecvBuffersUsed, r17 ; store new value
|
||||
lds r16, com2MaxBuffersUsed ; calc max buffers used
|
||||
cp r16, r17
|
||||
brcc COM2_AllocBuffer_l0
|
||||
sts com2MaxBuffersUsed, r17
|
||||
COM2_AllocBuffer_l0:
|
||||
lds r16, com2RecvBuffersWritePos ; get current write pos
|
||||
mov r17, r16 ; increment for next call
|
||||
inc r17
|
||||
cpi r17, COM2_BUFFER_NUM ; CF set if COM_BUFFER_NUM > R17
|
||||
brcs COM2_AllocBuffer_l1
|
||||
clr r17 ; wraparound
|
||||
COM2_AllocBuffer_l1:
|
||||
sts com2RecvBuffersWritePos, r17 ; store new writepos for next caller
|
||||
rcall COM2_BufferPosToX ; (R16, R17)
|
||||
out SREG, r21 ; restore global interrupt enable bit in SREG
|
||||
sec
|
||||
ret
|
||||
COM2_AllocBuffer_error:
|
||||
out SREG, r21
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; COM2_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
|
||||
|
||||
COM2_BufferDeallocBack:
|
||||
in r21, SREG ; save global interrupt enable bit from SREG
|
||||
cli
|
||||
lds r17, com2RecvBuffersUsed
|
||||
tst r17
|
||||
breq COM2_BufferDeallocBack_error ; no buffer allocated, nothing to release
|
||||
dec r17
|
||||
sts com2RecvBuffersUsed, r17 ; store new value
|
||||
lds r17, com2RecvBuffersWritePos
|
||||
tst r17 ; 0?
|
||||
brne COM2_BufferDeallocBack_l1 ; nope go directly decrement r17
|
||||
ldi r17, COM2_BUFFER_NUM ; wrap-around
|
||||
COM2_BufferDeallocBack_l1:
|
||||
dec r17
|
||||
sts com2RecvBuffersWritePos, r17
|
||||
out SREG, r21
|
||||
sec
|
||||
ret
|
||||
COM2_BufferDeallocBack_error:
|
||||
out SREG, r21
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; COM2_BufferDeallocFront
|
||||
;
|
||||
; Release a transfer buffer by increasing the read pos.
|
||||
;
|
||||
; IN:
|
||||
; - nothing
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, clear otherwise
|
||||
; MODIFIED REGISTERS: r16, r17, r21
|
||||
|
||||
COM2_BufferDeallocFront:
|
||||
in r21, SREG ; save global interrupt enable bit from SREG
|
||||
cli
|
||||
lds r17, com2RecvBuffersUsed
|
||||
tst r17
|
||||
breq COM2_BufferDeallocFront_error ; no buffer allocated, nothing to release
|
||||
dec r17
|
||||
sts com2RecvBuffersUsed, r17 ; store new value
|
||||
lds r17, com2RecvBuffersReadPos
|
||||
inc r17
|
||||
cpi r17, COM2_BUFFER_NUM
|
||||
brcs COM2_BufferDeallocFront_l1
|
||||
clr r17 ; wrap-around
|
||||
COM2_BufferDeallocFront_l1:
|
||||
sts com2RecvBuffersReadPos, r17
|
||||
out SREG, r21
|
||||
sec
|
||||
ret
|
||||
COM2_BufferDeallocFront_error:
|
||||
out SREG, r21
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; COM2_BufferPosToX
|
||||
;
|
||||
; Get a pointer to the SRAM position of the given buffer.
|
||||
; CAVE: Code must correspond to COM2_BUFFER_SIZE!!
|
||||
; IN:
|
||||
; - R16: buffer number (starting with 0)
|
||||
; OUT:
|
||||
; - X: pointer to buffer in SRAM
|
||||
; MODIFIED REGISTERS: R16, R17
|
||||
|
||||
COM2_BufferPosToX:
|
||||
; calculate offset
|
||||
clr r17
|
||||
mov xl, r16
|
||||
clr xh
|
||||
|
||||
lsl xl
|
||||
rol xh ; *2
|
||||
|
||||
add xl, r16
|
||||
adc xh, r17 ; *3
|
||||
|
||||
lsl xl
|
||||
rol xh ; *6
|
||||
|
||||
lsl xl
|
||||
rol xh ; *12
|
||||
|
||||
lsl xl
|
||||
rol xh ; *24
|
||||
|
||||
; add base position of buffers
|
||||
ldi r16, LOW(com2RecvBuffers)
|
||||
ldi r17, HIGH(com2RecvBuffers)
|
||||
add xl, r16
|
||||
adc xh, r17
|
||||
ret
|
||||
|
||||
|
||||
|
||||
60
avr/modules/com2/com2_crc.asm
Normal file
60
avr/modules/com2/com2_crc.asm
Normal file
@@ -0,0 +1,60 @@
|
||||
; ***************************************************************************
|
||||
; 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. *
|
||||
; ***************************************************************************
|
||||
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; 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
|
||||
rcall crc8Calc ; (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
|
||||
rcall crc8Calc ; (R16, R17, R18, R20, X)
|
||||
ld r17, X
|
||||
cp r16, r17 ; should be equal
|
||||
brne com2CheckMessageInBuffer_error
|
||||
sec
|
||||
ret
|
||||
com2CheckMessageInBuffer_error:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
48
avr/modules/com2/com2_defs.asm
Normal file
48
avr/modules/com2/com2_defs.asm
Normal file
@@ -0,0 +1,48 @@
|
||||
; ***************************************************************************
|
||||
; 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. *
|
||||
; ***************************************************************************
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.equ COM2_BUFFER_SIZE = 24 ; CAVE: must change code in COM2_BufferPosToX when changing this!
|
||||
.equ COM2_BUFFER_NUM = 4
|
||||
|
||||
.equ COM2_MAXWAIT_US = 100 ; maximum wait time in microseconds when waiting for rising/falling clock
|
||||
.equ COM2_MAINTENANCE_ADDR = 0xc1
|
||||
|
||||
|
||||
; 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
|
||||
|
||||
|
||||
.equ COM2_ERROR_NOTFORME = 1 ; receiption errors
|
||||
.equ COM2_ERROR_IOERROR = 2
|
||||
.equ COM2_ERROR_DATAERROR = 3
|
||||
.equ COM2_ERROR_BUSY = 4 ; send errors
|
||||
.equ COM2_ERROR_COLLISION = 5
|
||||
|
||||
|
||||
233
avr/modules/com2/com2_lowlevel.asm
Normal file
233
avr/modules/com2/com2_lowlevel.asm
Normal file
@@ -0,0 +1,233 @@
|
||||
; ***************************************************************************
|
||||
; 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. *
|
||||
; ***************************************************************************
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; 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
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; com2WaitForDataState1ms
|
||||
;
|
||||
; Waits up to COM2_MAXWAIT_US loops for high ATTN line
|
||||
; IN:
|
||||
; OUT:
|
||||
; - CFLAG: set if state reached, cleared otherwise
|
||||
; REGS: R24 (R22)
|
||||
|
||||
com2WaitForDataState1ms:
|
||||
ldi r24, 100
|
||||
com2WaitForDataState1ms_loop:
|
||||
push r17
|
||||
in r17, COM_PIN_DATA
|
||||
eor r17, r16
|
||||
andi r17, (1<<COM_PINNUM_DATA)
|
||||
pop r17
|
||||
breq com2WaitForDataState1ms_stateReached
|
||||
Utils_WaitNanoSecs 10000, 0, r22 ; wait for 10us
|
||||
dec r24
|
||||
brne com2WaitForDataState1ms_loop
|
||||
clc
|
||||
ret
|
||||
com2WaitForDataState1ms_stateReached:
|
||||
sec
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; comWaitFor1000ns
|
||||
;
|
||||
; Waits for 1000 nanoseconds.
|
||||
; IN:
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, clear otherwise
|
||||
; REGS: r22
|
||||
|
||||
com2WaitFor1000ns:
|
||||
Utils_WaitNanoSecs 1000, 7, r22 ; wait for 1000 nanosecs (minus 3 cycles for rcall, 4 for ret)
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
150
avr/modules/com2/com2_packets.asm
Normal file
150
avr/modules/com2/com2_packets.asm
Normal file
@@ -0,0 +1,150 @@
|
||||
; ***************************************************************************
|
||||
; 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. *
|
||||
; ***************************************************************************
|
||||
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; receive packet into buffer pointed to by X.
|
||||
;
|
||||
; IN:
|
||||
; - R16: COM address to listen to
|
||||
; - R17: maximum value for accepted msg data (i.e. buffersize minus 3)
|
||||
; - X : buffer to receive to
|
||||
; OUT:
|
||||
; - CFLAG: set if okay (packet received), cleared on error
|
||||
; - R16: error code if CFLAG is cleared
|
||||
; REGS: r16, r17, r18, X (r19, r20, r21, r22)
|
||||
com2ReceivePacketRaw:
|
||||
mov r18, r17
|
||||
push r16
|
||||
; read destination address
|
||||
rcall com2ReceiveByte ; read byte (R16, R17, R20, R21, R22)
|
||||
pop r17 ; pop from R16 to R17
|
||||
brcc com2ReceivePacketRaw_ioError
|
||||
; compare destination address (accept "FF" and own address)
|
||||
cp r16, r17
|
||||
breq com2ReceivePacketRaw_acceptAddr
|
||||
cpi r16, 0xff
|
||||
breq com2ReceivePacketRaw_acceptAddr
|
||||
ldi r16, COM2_ERROR_NOTFORME
|
||||
clc ; not for me
|
||||
ret
|
||||
com2ReceivePacketRaw_acceptAddr:
|
||||
st X+, r16 ; store dest address, lock buffer
|
||||
; read msg length
|
||||
rcall com2ReceiveByte ; read packet length (R16, R17, R20, R21, R22)
|
||||
brcc com2ReceivePacketRaw_ioError
|
||||
st X+, r16
|
||||
cp r16, r18 ; (COM2_BUFFER_SIZE-3)
|
||||
brcc com2ReceivePacketRaw_contentError ; packet too long
|
||||
inc r16 ; account for checksum byte
|
||||
mov r17, r16
|
||||
com2ReceivePacketRaw_loop:
|
||||
push r17
|
||||
rcall com2ReceiveByte ; read byte (R16, R17, R20, R21, R22)
|
||||
pop r17
|
||||
brcc com2ReceivePacketRaw_ioError
|
||||
st X+, r16
|
||||
dec r17
|
||||
brne com2ReceivePacketRaw_loop
|
||||
sec
|
||||
ret
|
||||
com2ReceivePacketRaw_ioError:
|
||||
ldi r16, COM2_ERROR_IOERROR
|
||||
rjmp com2ReceivePacketRaw_error
|
||||
com2ReceivePacketRaw_contentError:
|
||||
ldi r16, COM2_ERROR_DATAERROR
|
||||
com2ReceivePacketRaw_error:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; send packet over wire, handle ATTN line.
|
||||
;
|
||||
; IN:
|
||||
; - x : ptr to buffer to send
|
||||
; OUT:
|
||||
; - CFLAGS: set if okay, cleared otherwise (errorcode in R16)
|
||||
; REGS: R15, R16, R22 (R17, R21, X)
|
||||
|
||||
COM2_SendPacketWithAttn:
|
||||
in r15, SREG
|
||||
push r15
|
||||
cli
|
||||
Utils_WaitNanoSecs COM_BIT_LENGTH, 0, r22 ; wait for one bit duration
|
||||
; 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_SendPacketWithAttn_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 ; (r16, r17, r21, r22, X)
|
||||
|
||||
cbi COM_DDR_ATTN, COM_PINNUM_ATTN ; release ATTN line (by setting direction to IN)
|
||||
brcc COM2_SendPacketWithAttn_ioError
|
||||
; packet successfully sent
|
||||
pop r15
|
||||
out SREG, r15
|
||||
sec
|
||||
ret
|
||||
|
||||
COM2_SendPacketWithAttn_ioError:
|
||||
ldi r16,COM2_ERROR_COLLISION
|
||||
rjmp COM2_SendPacketWithAttn_retNc
|
||||
|
||||
COM2_SendPacketWithAttn_lineBusyError:
|
||||
ldi r16,COM2_ERROR_BUSY
|
||||
COM2_SendPacketWithAttn_retNc:
|
||||
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
|
||||
|
||||
|
||||
|
||||
142
avr/modules/comproto/comproto.asm
Normal file
142
avr/modules/comproto/comproto.asm
Normal file
@@ -0,0 +1,142 @@
|
||||
; ***************************************************************************
|
||||
; 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. *
|
||||
; ***************************************************************************
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; data
|
||||
|
||||
.dseg
|
||||
|
||||
|
||||
cproDataBegin:
|
||||
cproMode: .byte 1
|
||||
cproDataEnd:
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; code
|
||||
|
||||
.cseg
|
||||
|
||||
|
||||
CPRO_BEGIN:
|
||||
|
||||
|
||||
CPRO_Init:
|
||||
; preset SRAM data area
|
||||
ldi xh, HIGH(cproDataBegin)
|
||||
ldi xl, LOW(cproDataBegin)
|
||||
clr r16
|
||||
ldi r17, (cproDataEnd-cproDataBegin)
|
||||
rcall Utils_FillSram
|
||||
|
||||
#ifdef MODULES_COM_WITH_ADDR_PROTO
|
||||
rcall CPRO_Address_Init
|
||||
#endif
|
||||
|
||||
sec
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; CPRO_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_OnPacketReceived:
|
||||
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_REBOOT_REQUEST
|
||||
brne CPRO_OnPacketReceived_l2
|
||||
rjmp cproHandleReboot
|
||||
#endif
|
||||
CPRO_OnPacketReceived_l2:
|
||||
#ifdef MODULES_COM_WITH_ADDR_PROTO
|
||||
rjmp CPRO_Address_OnPacketReceived
|
||||
#else
|
||||
clc
|
||||
ret
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
cproHandlePing:
|
||||
adiw xh:xl, COM2_MSG_OFFS_SRCADDR
|
||||
ld r16, x
|
||||
tst r16 ; dont handle src address 0
|
||||
breq cproHandlePing_notHandled
|
||||
inc r16
|
||||
breq cproHandlePing_notHandled ; dont handle src address 255
|
||||
dec r16
|
||||
ldi xl, LOW(com2SendBuffer)
|
||||
ldi xh, HIGH(com2SendBuffer)
|
||||
rcall CPRO_WritePong
|
||||
rjmp COM2_SendPacket ; use carry flag from this routine
|
||||
cproHandlePing_notHandled:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Compare the UID from a message against out own UID.
|
||||
;
|
||||
;IN:
|
||||
; - X: pointer to UID in a message to compare against out own uid
|
||||
; OUT:
|
||||
; - CFLAG set if matches, cleared otherwise
|
||||
; REGS: r16, r18, r19, r20, r21, X
|
||||
|
||||
cproCheckUidInMsg:
|
||||
push xl
|
||||
push xh
|
||||
rcall Utils_ReadUid
|
||||
pop xh
|
||||
pop xl
|
||||
ld r16, X+
|
||||
cp r16, r18
|
||||
brne cproCheckUidInMsg_notMe
|
||||
ld r16, X+
|
||||
cp r16, r19
|
||||
brne cproCheckUidInMsg_notMe
|
||||
ld r16, X+
|
||||
cp r16, r20
|
||||
brne cproCheckUidInMsg_notMe
|
||||
ld r16, X+
|
||||
cp r16, r21
|
||||
brne cproCheckUidInMsg_notMe
|
||||
sec
|
||||
ret
|
||||
cproCheckUidInMsg_notMe:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
CPRO_END:
|
||||
.equ MODULE_SIZE_CPRO = CPRO_END-CPRO_BEGIN
|
||||
|
||||
|
||||
|
||||
434
avr/modules/comproto/comproto_addr.asm
Normal file
434
avr/modules/comproto/comproto_addr.asm
Normal file
@@ -0,0 +1,434 @@
|
||||
; ***************************************************************************
|
||||
; 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 sub-module contains code for cooperative address management.
|
||||
; Because the network of nodes doen't have a central control unit the nodes
|
||||
; need to assign addresses to themselves with help from the community of existing
|
||||
; nodes.
|
||||
;
|
||||
; Protocol A: Full Address Assignment Protocol
|
||||
; --------------------------------------------
|
||||
; This protocol is used when a node has no currently or previously assigned address.
|
||||
; In this case we need to find a free address which no other node uses.
|
||||
;
|
||||
; 1) a node needs an address. It sends the packet "NEED_ADDRESS"
|
||||
; 2) every node which already has an address sees this message and answers with
|
||||
; a "HAVE_ADDRESS" packet. The nodes must not answer all at once to avoid
|
||||
; congestions. Instead, the time it takes for a node to respond depends on
|
||||
; its own address (e.g. a node with address 10 will wait for 10+3s before answering)
|
||||
; 3) the initial node collects all "HAVE_ADDRESS" packets and puts the addresses
|
||||
; received this way into a bitfield in which for every address received a bit is
|
||||
; set
|
||||
; 4) after about 130s all nodes in the address range 1-127 should have answered.
|
||||
; So after this time the initial node looks at the bitfield of received addresses
|
||||
; and selects the first unused address (corresponding bit cleared in bitfield).
|
||||
; For this address the initial node sends a "CLAIM_ADDRESS" packet, three times
|
||||
; with about 30s between the packets.
|
||||
; 5) if the to-be-claimed address is already in use by another node, that node will
|
||||
; send a "DENY_ADDRESS" packet. This is the second line of defense against address
|
||||
; collisions and should very rarely occur.
|
||||
; 6) after no node denied the to-be-claimed address the initial node finally takes the
|
||||
; address and sends a "HAVE_ADDRESS" packet.
|
||||
; 7) this concludes the address assignemt protocol
|
||||
;
|
||||
; Protocol B: Shortened Address Assignment Protocol
|
||||
; -------------------------------------------------
|
||||
; This protocol is used upon boot when a node previously got an address assigned to it.
|
||||
; In this case the address is probably not used by an other node so we can shorten the
|
||||
; procedure.
|
||||
;
|
||||
; 1) a node sends the packet CLAIM_ADDRESS with the previously assigned address
|
||||
; 2) is any other node objects to this node using that address (e.g. because the other
|
||||
; node now uses that address) that node will send a DENY_ADDRESS packet.
|
||||
; 3) if no DENY_ADDRESS has been received within 10s the address can be used.
|
||||
; 4) Otherwise the node changes into protocol A (see above).
|
||||
|
||||
|
||||
#ifdef MODULES_COM_WITH_ADDR_PROTO
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; defs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; data
|
||||
|
||||
.dseg
|
||||
|
||||
|
||||
cproAddressDataBegin:
|
||||
cproAddrRangeBegin: .byte 1
|
||||
cproAddrRangeEnd: .byte 1
|
||||
cproUsedAddresses: .byte 16 ; one bit per address known to b in use
|
||||
cproAddressDataEnd:
|
||||
|
||||
cproAddresModeTimer: .byte 2 ; timer must not be zeroed, this is done by the timer module!!
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; code
|
||||
|
||||
.cseg
|
||||
|
||||
|
||||
|
||||
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)
|
||||
in r15, SREG
|
||||
push r15
|
||||
cli
|
||||
rcall Utils_ReadEepromIncr ; (R16)
|
||||
tst r16
|
||||
breq CPRO_StartReclaimAddrProcedure_l1
|
||||
cpi r16, 0xff
|
||||
breq CPRO_StartReclaimAddrProcedure_l1
|
||||
sts cproAddrRangeBegin, r16 ; currently claimed address
|
||||
ldi r16, CPRO_MODE_SEND_RECLAIM_ADDR
|
||||
sts cproMode, r16
|
||||
rcall cproAddressSetTimer1s ; use singleshot timer, send after 1s
|
||||
pop r15
|
||||
out SREG, r15
|
||||
sec
|
||||
ret
|
||||
CPRO_StartReclaimAddrProcedure_l1:
|
||||
rcall CPRO_StartGetAddrProcedure
|
||||
pop r15
|
||||
out SREG, r15
|
||||
ret
|
||||
|
||||
|
||||
|
||||
CPRO_StartGetAddrProcedure:
|
||||
; reset bitfield of used addresses
|
||||
ldi xh, HIGH(cproUsedAddresses)
|
||||
ldi xl, LOW(cproUsedAddresses)
|
||||
clr r16
|
||||
ldi r17, 16
|
||||
rcall Utils_FillSram
|
||||
; preset range
|
||||
ldi r16, 1
|
||||
sts cproAddrRangeBegin, r16
|
||||
ldi r16, 126
|
||||
sts cproAddrRangeEnd, r16
|
||||
; setup singleshot timer to later send "NEED_ADDRESS" packet
|
||||
ldi r16, CPRO_MODE_SEND_NEED_ADDR
|
||||
sts cproMode, r16
|
||||
rcall cproAddressSetTimer1s
|
||||
sec
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
; REGS: r18, r19
|
||||
;
|
||||
cproAddressSetTimer1s:
|
||||
ldi r18, 1
|
||||
ldi r19, 0
|
||||
rjmp cproAddressSetTimer
|
||||
|
||||
|
||||
|
||||
; IN:
|
||||
; - r18: timer value (low)
|
||||
; - r19: timer value (high)
|
||||
; REGS: none
|
||||
|
||||
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 cproGetFreeAddr_error
|
||||
rcall cproFindFreeAddr
|
||||
brcc cproGetFreeAddr_error
|
||||
sec
|
||||
ret
|
||||
cproGetFreeAddr_error:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
cproHandleAddrRange: ; not handled for now
|
||||
; TODO
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; cproFindFreeAddr
|
||||
;
|
||||
; find a free address in the bitfield cproUsedAddresses
|
||||
;
|
||||
; IN:
|
||||
; - nothing
|
||||
; OUT:
|
||||
; - CFLAG: set if handled, cleared otherwise
|
||||
; - R16: free address (if CFLAG set)
|
||||
; USED: R16, R17, R18, R19, R20, R21 X, (R1, R2, Z)
|
||||
|
||||
cproFindFreeAddr:
|
||||
ldi xl, LOW(cproUsedAddresses)
|
||||
ldi xh, HIGH(cproUsedAddresses)
|
||||
lds r16, cproAddrRangeBegin
|
||||
dec r16
|
||||
rcall cproGetPosAndMaskInBitField ; r1=bit pos, r2=mask (r1, r2, r17, Z)
|
||||
clr r17
|
||||
add xl, r1
|
||||
adc xh, r17 ; X: pointer to byte
|
||||
mov r17, r2 ; mask
|
||||
lds r18, cproAddrRangeBegin
|
||||
dec r18
|
||||
lds r19, cproAddrRangeEnd
|
||||
inc r19 ; to make comparision easier
|
||||
ldi r20, 8
|
||||
cproFindFreeAddr_byteLoop:
|
||||
ld r16, X+
|
||||
cpi r16, 0xff
|
||||
breq cproFindFreeAddr_nextByte ; byte full, skip
|
||||
cproFindFreeAddr_bitLoop:
|
||||
mov r21, r16
|
||||
and r21, r17
|
||||
brne cproFindFreeAddr_nextBit
|
||||
; found a clear bit, return
|
||||
inc r18
|
||||
sts cproAddrRangeBegin, r18
|
||||
mov r16, r18
|
||||
sec
|
||||
ret
|
||||
cproFindFreeAddr_nextBit:
|
||||
inc r18 ; next address
|
||||
lsl r17 ; shift mask to the left
|
||||
brcc cproFindFreeAddr_bitLoop
|
||||
dec r18 ; take back inc
|
||||
cproFindFreeAddr_nextByte:
|
||||
add r18, r20
|
||||
andi r18, 0xf8 ; clear lower 3 bits
|
||||
cp r18, r19 ; compare to end address+1
|
||||
brcc cproFindFreeAddr_allFull
|
||||
ldi r17, 0x01 ; mask
|
||||
rjmp cproFindFreeAddr_byteLoop
|
||||
cproFindFreeAddr_allFull:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; cproSetBitInBitfield
|
||||
;
|
||||
; IN:
|
||||
; - R16 : bit number to set (0-127)
|
||||
; OUT:
|
||||
; - nothing
|
||||
; USED: R16, R17, X (r1, r2, Z)
|
||||
|
||||
cproSetBitInBitfield:
|
||||
; set bit corresponding to given address in bitfield of used addresses
|
||||
rcall cproGetPosAndMaskInBitField ; get offset into R1, mask into R2 (r1, r2, r17, Z)
|
||||
ldi xl, LOW(cproUsedAddresses)
|
||||
ldi xh, HIGH(cproUsedAddresses)
|
||||
clr r17
|
||||
add xl, r1
|
||||
adc xh, r17
|
||||
ld r16, X
|
||||
or r16, r2
|
||||
st X, r16
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Get offset and mask for a given bit in a bitfield
|
||||
; IN:
|
||||
; - R16: bit to request position for
|
||||
; OUT:
|
||||
; - R1: offset into the bitfield to the byte containing the given bit
|
||||
; - R2: mask for given id (apply to r1)
|
||||
; USED REGISTERS: r1, r2, r17, Z
|
||||
|
||||
cproGetPosAndMaskInBitField:
|
||||
mov r1, r16 ; divide by 8 to get the offset to the byte containing the given module id
|
||||
lsr r1
|
||||
lsr r1
|
||||
lsr r1 ; r1=offset of the byte holding the given bit
|
||||
mov r2, r16 ; get bit mask for bit position in table byte
|
||||
ldi r17, 7 ; keep lower 3 bits
|
||||
and r2, r17
|
||||
ldi zh, HIGH(cproModuleBitNumToMaskMap*2)
|
||||
ldi zl, LOW(cproModuleBitNumToMaskMap*2)
|
||||
add zl, r2
|
||||
brcc cproGetPosAndMaskInBitField_noOverflow
|
||||
inc zh
|
||||
cproGetPosAndMaskInBitField_noOverflow:
|
||||
lpm r2, z ; r2=mask for bit in byte from bitfield
|
||||
ret
|
||||
|
||||
|
||||
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
|
||||
; - R19: address to send
|
||||
; 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
|
||||
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 "modules/comproto/comproto_addr1.asm"
|
||||
.include "modules/comproto/comproto_addr2.asm"
|
||||
|
||||
|
||||
#endif ; MODULES_COM_WITH_ADDR_PROTO
|
||||
|
||||
|
||||
166
avr/modules/comproto/comproto_addr1.asm
Normal file
166
avr/modules/comproto/comproto_addr1.asm
Normal file
@@ -0,0 +1,166 @@
|
||||
; ***************************************************************************
|
||||
; 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:
|
||||
lds r19, com2Address
|
||||
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
|
||||
sts com2Address, r19
|
||||
rcall CPRO_SendHaveAddress
|
||||
brcs cproHandle1sClaimingAddr3_okay
|
||||
rjmp cproAddressSetTimer1s ; could not send, restart timer 1s and retry later
|
||||
cproHandle1sClaimingAddr3_okay:
|
||||
in r15, SREG
|
||||
push r15
|
||||
cli
|
||||
lds r16, com2Address ; currently sent address is in cproAddrRangeBegin
|
||||
ldi xl, LOW(EEPROM_OFFS_COMADDR) ; write address into eeprom
|
||||
ldi xh, HIGH(EEPROM_OFFS_COMADDR)
|
||||
rcall Utils_WriteEepromIncr ; write address to EEPROM
|
||||
pop r15
|
||||
out SREG, r15
|
||||
ldi r16, CPRO_MODE_NORMAL ; set mode to "normal"
|
||||
sts cproMode, r16
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
168
avr/modules/comproto/comproto_addr2.asm
Normal file
168
avr/modules/comproto/comproto_addr2.asm
Normal file
@@ -0,0 +1,168 @@
|
||||
; ***************************************************************************
|
||||
; 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, cproHandleHaveAddr, 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
|
||||
|
||||
|
||||
|
||||
cproHandleHaveAddr:
|
||||
lds r17, cproMode
|
||||
cpi r17, CPRO_MODE_GETADDRSTARTED
|
||||
brne cproHandleHaveAddr_done
|
||||
; validate address
|
||||
adiw xh:xl, CPRO_PACKET_HAVEADDR_OFFS_ADDRESS
|
||||
ld r16, x
|
||||
sbiw xh:xl, CPRO_PACKET_HAVEADDR_OFFS_ADDRESS
|
||||
tst r16
|
||||
breq cproHandleHaveAddr_done ; invalid address, ignore
|
||||
cpi r16, 127
|
||||
brcc cproHandleHaveAddr_done ; invalid address, ignore
|
||||
; set bit corresponding to given address in bitfield of used addresses
|
||||
dec r16
|
||||
rcall cproSetBitInBitfield
|
||||
cproHandleHaveAddr_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_DENYADDR_OFFS_ADDRESS
|
||||
ld r16, x
|
||||
sbiw xh:xl, CPRO_PACKET_DENYADDR_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
|
||||
|
||||
|
||||
67
avr/modules/comproto/comproto_debug.asm
Normal file
67
avr/modules/comproto/comproto_debug.asm
Normal file
@@ -0,0 +1,67 @@
|
||||
; ***************************************************************************
|
||||
; 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
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Enqueue a DEBUG packet.
|
||||
;
|
||||
; IN:
|
||||
; - R16: destination address
|
||||
; - R1: debug value 1
|
||||
; - R2: debug value 2
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, clear otherwise
|
||||
; MODIFIED REGS: R16, R17, R20, X (R15, Y)
|
||||
|
||||
CPRO_EnqueueDebug:
|
||||
push r16
|
||||
rcall COM_AllocBufferAndGetXY ; (r16, r17, r21)
|
||||
pop r16
|
||||
brcc CPRO_EnqueueDebug_error
|
||||
clr r17 ; r17: XOR byte
|
||||
; write header (dest address, msg length)
|
||||
st X+, r16 ; destination address
|
||||
eor r17, r16
|
||||
ldi r16, 4 ; 2 bytes payload
|
||||
st X+, r16
|
||||
eor r17, r16
|
||||
; write payload
|
||||
ldi r16, CPRO_CMD_DEBUG
|
||||
st X+, r16
|
||||
eor r17, r16
|
||||
lds r16, comAddress
|
||||
st X+, r16
|
||||
eor r17, r16
|
||||
mov r16, r1 ; debug 1
|
||||
st X+, r16
|
||||
eor r17, r16
|
||||
mov r16, r2 ; debug 2
|
||||
st X+, r16
|
||||
eor r17, r16
|
||||
; store XOR byte
|
||||
st X+, r17
|
||||
; mark buffer as enqueued with PRIO "info" (limited amount of retries)
|
||||
ldi r20, COM_BUFFER_PRIO_INFO
|
||||
rcall COM_EnqueuePacket ; (R15, R16)
|
||||
brcc CPRO_EnqueueDebug_error
|
||||
sec
|
||||
ret
|
||||
CPRO_EnqueueDebug_error:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
74
avr/modules/comproto/comproto_defs.asm
Normal file
74
avr/modules/comproto/comproto_defs.asm
Normal file
@@ -0,0 +1,74 @@
|
||||
; ***************************************************************************
|
||||
; 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 CPRO_CMD_PING = 10
|
||||
.equ CPRO_CMD_PONG = 11
|
||||
.equ CPRO_CMD_COMSENDSTATS = 20
|
||||
.equ CPRO_CMD_COMRECVSTATS = 21
|
||||
.equ CPRO_CMD_TWIBUSMEMBER = 30
|
||||
.equ CPRO_CMD_DEBUG = 40
|
||||
.equ CPRO_CMD_VALUE = 51 ; was 50 when sending timestamp instead of uid
|
||||
.equ CPRO_CMD_NEED_ADDRESS = 60
|
||||
.equ CPRO_CMD_HAVE_ADDRESS = 61
|
||||
.equ CPRO_CMD_CLAIM_ADDRESS = 62
|
||||
.equ CPRO_CMD_DENY_ADDRESS = 63
|
||||
.equ CPRO_CMD_ADDRESS_RANGE = 64
|
||||
|
||||
.equ CPRO_CMD_FLASH_START = 70
|
||||
.equ CPRO_CMD_FLASH_END = 71
|
||||
.equ CPRO_CMD_FLASH_READY = 72
|
||||
.equ CPRO_CMD_FLASH_DATA = 73
|
||||
.equ CPRO_CMD_FLASH_RSP = 74
|
||||
|
||||
.equ CPRO_CMD_DEVICE = 80
|
||||
.equ CPRO_CMD_MEMSTATS = 81
|
||||
.equ CPRO_CMD_SYSSTATS = 82
|
||||
|
||||
.equ CPRO_CMD_REBOOT_REQUEST = 90
|
||||
.equ CPRO_CMD_REBOOT_RESPONSE = 91
|
||||
|
||||
|
||||
.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_PACKET_REBOOTREQ_OFFS_UID = COM2_MSG_OFFS_PAYLOAD+0
|
||||
|
||||
.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_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
|
||||
|
||||
|
||||
|
||||
|
||||
53
avr/modules/comproto/comproto_device.asm
Normal file
53
avr/modules/comproto/comproto_device.asm
Normal 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
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Enqueue a DEVICE packet.
|
||||
;
|
||||
; IN:
|
||||
; - R16: destination address
|
||||
; - X : buffer to write to
|
||||
; OUT:
|
||||
; - nothing
|
||||
; REGS: R3, R4, R16, R17, R18, X (R19, R20, R21)
|
||||
|
||||
CPRO_WriteDevice:
|
||||
ldi r17, COM2_PAYLOAD_FLAGS_UID | (6<<COM2_PAYLOAD_FLAGS_SHIFT_NUM)
|
||||
ldi r18, CPRO_CMD_DEVICE
|
||||
push xh
|
||||
push xl
|
||||
rcall COM2_BeginMsgWithVariablePayload ; (R3, R4, R16, R17, R18, R19, R20, R21, X)
|
||||
lds r17, firmwareType
|
||||
st X+, r17 ; 6: firmware type low
|
||||
lds r17, firmwareType+1
|
||||
st X+, r17 ; 7: firmware type high
|
||||
lds r17, firmwareVersion
|
||||
st X+, r17 ; 8: version low
|
||||
lds r17, firmwareVersion+1
|
||||
st X+, r17 ; 9: version high
|
||||
lds r17, firmwareModules
|
||||
st X+, r17 ; 10: modules mask low
|
||||
lds r17, firmwareModules+1
|
||||
st X+, r17 ; 11: modules mask low
|
||||
pop xl
|
||||
pop xh
|
||||
rcall com2CalcAndAddChecksumByte ; (R16, R17, R18, R19, X)
|
||||
ret
|
||||
|
||||
|
||||
|
||||
57
avr/modules/comproto/comproto_memstats.asm
Normal file
57
avr/modules/comproto/comproto_memstats.asm
Normal file
@@ -0,0 +1,57 @@
|
||||
; ***************************************************************************
|
||||
; 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
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Enqueue a MEMSTATS packet.
|
||||
;
|
||||
; IN:
|
||||
; - R16: destination address
|
||||
; OUT:
|
||||
; - nothing
|
||||
; REGS: R3, R4, R16, R17, R18, X (R19, R20, R21)
|
||||
|
||||
CPRO_WriteMemStats:
|
||||
ldi r17, COM2_PAYLOAD_FLAGS_UID | COM2_PAYLOAD_FLAGS_SECONDS | (6<<COM2_PAYLOAD_FLAGS_SHIFT_NUM)
|
||||
ldi r18, CPRO_CMD_MEMSTATS
|
||||
push xh
|
||||
push xl
|
||||
rcall COM2_BeginMsgWithVariablePayload ; (R3, R4, R16, R17, R18, R19, R20, R21, X)
|
||||
; payload
|
||||
ldi r20, LOW(RAMEND)
|
||||
ldi r21, HIGH(RAMEND)
|
||||
in r17, SPL
|
||||
sub r20, r17
|
||||
st X+, r20 ; stack used
|
||||
in r17, SPH
|
||||
sbc r21, r17
|
||||
st X+, r21
|
||||
lds r17, com2RecvBuffersUsed
|
||||
st X+, r17 ; used buffers
|
||||
lds r17, com2MaxBuffersUsed
|
||||
st X+, r17 ; max used buffers
|
||||
lds r17, com2StatsNoBufferError
|
||||
st X+, r17 ; recvNoBuffer
|
||||
lds r17, com2StatsNoBufferError+1
|
||||
st X+, r17
|
||||
pop xl
|
||||
pop xh
|
||||
rcall com2CalcAndAddChecksumByte ; (R16, R17, R18, R19, X)
|
||||
ret
|
||||
|
||||
|
||||
|
||||
33
avr/modules/comproto/comproto_ping.asm
Normal file
33
avr/modules/comproto/comproto_ping.asm
Normal 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/modules/comproto/comproto_pong.asm
Normal file
33
avr/modules/comproto/comproto_pong.asm
Normal 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
|
||||
|
||||
|
||||
71
avr/modules/comproto/comproto_reboot.asm
Normal file
71
avr/modules/comproto/comproto_reboot.asm
Normal file
@@ -0,0 +1,71 @@
|
||||
; ***************************************************************************
|
||||
; 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
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Handle reboot request
|
||||
;
|
||||
; IN:
|
||||
; - X : buffer containing the received packet
|
||||
; OUT:
|
||||
; - nothing
|
||||
; REGS:
|
||||
|
||||
cproHandleReboot:
|
||||
adiw xh:xl, CPRO_PACKET_REBOOTREQ_OFFS_UID
|
||||
rcall cproCheckUidInMsg
|
||||
brcc cproHandleReboot_notHandled
|
||||
sbiw xh:xl, CPRO_PACKET_REBOOTREQ_OFFS_UID+4
|
||||
adiw xh:xl, COM2_MSG_OFFS_SRCADDR
|
||||
ld r16, x
|
||||
cpi r16, 0xff
|
||||
breq cproHandleReboot_notHandled ; dont handle src address 255
|
||||
cproHandleReboot_loop1:
|
||||
push r16
|
||||
ldi xl, LOW(com2SendBuffer)
|
||||
ldi xh, HIGH(com2SendBuffer)
|
||||
rcall CPRO_WriteRebootResponse
|
||||
rcall COM2_SendPacket
|
||||
pop r16
|
||||
brcc cproHandleReboot_loop1
|
||||
|
||||
; directly call bootloader
|
||||
cli
|
||||
rjmp AQHOME_BOOTLOADER_ADDR
|
||||
cproHandleReboot_notHandled:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Write a Reboot Response packet.
|
||||
;
|
||||
; IN:
|
||||
; - R16: destination address
|
||||
; - X : buffer to write to
|
||||
; OUT:
|
||||
; - nothing
|
||||
; REGS: R3, R4, R16, R17, R18, X (R19, R20, R21)
|
||||
|
||||
CPRO_WriteRebootResponse:
|
||||
ldi r18, CPRO_CMD_REBOOT_RESPONSE
|
||||
rjmp COM2_WriteMsgWithCmdAndSrcAddr ; R3, R4, R15, R16, R17, R18, R19, R20, R21, X
|
||||
|
||||
|
||||
|
||||
66
avr/modules/comproto/comproto_recvstats.asm
Normal file
66
avr/modules/comproto/comproto_recvstats.asm
Normal file
@@ -0,0 +1,66 @@
|
||||
; ***************************************************************************
|
||||
; 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 | (12<<COM2_PAYLOAD_FLAGS_SHIFT_NUM) ; seconds + 12 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
|
||||
lds r16, com2StatsHandled
|
||||
st X+, r16
|
||||
lds r16, com2StatsHandled+1
|
||||
st X+, r16
|
||||
lds r16, com2StatsMissed
|
||||
st X+, r16
|
||||
lds r16, com2StatsMissed+1
|
||||
st X+, r16
|
||||
pop xl
|
||||
pop xh
|
||||
rcall com2CalcAndAddChecksumByte ; (R16, R17, R18, R19, X)
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
53
avr/modules/comproto/comproto_sendstats.asm
Normal file
53
avr/modules/comproto/comproto_sendstats.asm
Normal 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 com2CalcAndAddChecksumByte ; (R16, R17, R18, R19, X)
|
||||
ret
|
||||
|
||||
|
||||
|
||||
50
avr/modules/comproto/comproto_sysstats.asm
Normal file
50
avr/modules/comproto/comproto_sysstats.asm
Normal file
@@ -0,0 +1,50 @@
|
||||
; ***************************************************************************
|
||||
; 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 SYSSTATS packet.
|
||||
;
|
||||
; IN:
|
||||
; - R16: destination address
|
||||
; - X : buffer to write to
|
||||
; OUT:
|
||||
; - nothing
|
||||
; REGS: R3, R4, R16, R17, R18, X (R19, R20, R21)
|
||||
|
||||
CPRO_WriteSysStats:
|
||||
ldi r17, COM2_PAYLOAD_FLAGS_UID | COM2_PAYLOAD_FLAGS_SECONDS | (4<<COM2_PAYLOAD_FLAGS_SHIFT_NUM)
|
||||
ldi r18, CPRO_CMD_SYSSTATS
|
||||
push xh
|
||||
push xl
|
||||
rcall COM2_BeginMsgWithVariablePayload ; (R3, R4, R16, R17, R18, R19, R20, R21, X)
|
||||
; payload
|
||||
lds r17, com2Interrupts
|
||||
st X+, r17 ; com interrupts
|
||||
lds r17, com2Interrupts+1
|
||||
st X+, r17
|
||||
|
||||
lds r17, timerInterrupts
|
||||
st X+, r17 ; timer interrupts
|
||||
lds r17, timerInterrupts+1
|
||||
st X+, r17
|
||||
pop xl
|
||||
pop xh
|
||||
rcall com2CalcAndAddChecksumByte ; (R16, R17, R18, R19, X)
|
||||
ret
|
||||
|
||||
|
||||
67
avr/modules/comproto/comproto_twi.asm
Normal file
67
avr/modules/comproto/comproto_twi.asm
Normal file
@@ -0,0 +1,67 @@
|
||||
; ***************************************************************************
|
||||
; 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
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Enqueue a TWI Bus Member packet.
|
||||
;
|
||||
; IN:
|
||||
; - R16: destination address
|
||||
; - R1 : Address of the bus member
|
||||
; - R2 : availability (0=not available, 1=available)
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, clear otherwise
|
||||
; MODIFIED REGS: R16, R17, R20, X (R15, Y)
|
||||
|
||||
CPRO_EnqueueTwiBusMember:
|
||||
push r16
|
||||
rcall COM_AllocBufferAndGetXY ; (r16, r17, r21)
|
||||
pop r16
|
||||
brcc CPRO_EnqueueTwiBusMember_error
|
||||
clr r17 ; r17: XOR byte
|
||||
; write header (dest address, msg length)
|
||||
st X+, r16 ; destination address
|
||||
eor r17, r16
|
||||
ldi r16, 4 ; 4 bytes payload
|
||||
st X+, r16
|
||||
eor r17, r16
|
||||
; write payload
|
||||
ldi r16, CPRO_CMD_TWIBUSMEMBER ; send command
|
||||
st X+, r16
|
||||
eor r17, r16
|
||||
lds r16, comAddress ; send source address
|
||||
st X+, r16
|
||||
eor r17, r16
|
||||
mov r16, r1 ; send i2c bus member address
|
||||
st X+, r16
|
||||
eor r17, r16
|
||||
mov r16, r2 ; send i2c bus member availability
|
||||
st X+, r16
|
||||
eor r17, r16
|
||||
; store XOR byte
|
||||
st X+, r17
|
||||
; mark buffer as enqueued with PRIO "info" (limited amount of retries)
|
||||
ldi r20, COM_BUFFER_PRIO_INFO
|
||||
rcall COM_EnqueuePacket ; (R15, R16)
|
||||
brcc CPRO_EnqueueTwiBusMember_error
|
||||
sec
|
||||
ret
|
||||
CPRO_EnqueueTwiBusMember_error:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
58
avr/modules/comproto/comproto_values.asm
Normal file
58
avr/modules/comproto/comproto_values.asm
Normal 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 VALUE packet.
|
||||
;
|
||||
; IN:
|
||||
; - R16: destination address
|
||||
; - R17: value id
|
||||
; - R19:R18: value
|
||||
; - R21:R20: denom (e.g. 100, meaning value must be divided by 100)
|
||||
; - R22: value type
|
||||
; - X : buffer to write to
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, clear otherwise
|
||||
; MODIFIED REGS: R6, R7, R8, R9, R10, R11, R12, R16, R17, X, Y (R3, R4, R15, R16, R17, R18, R19, R20, R21)
|
||||
|
||||
CPRO_WriteValue:
|
||||
mov r7, r17
|
||||
mov r8, r18
|
||||
mov r9, r19
|
||||
mov r10, r20
|
||||
mov r11, r21
|
||||
mov r12, r22
|
||||
|
||||
ldi r17, COM2_PAYLOAD_FLAGS_UID | (6<<COM2_PAYLOAD_FLAGS_SHIFT_NUM)
|
||||
ldi r18, CPRO_CMD_VALUE
|
||||
push xh
|
||||
push xl
|
||||
rcall COM2_BeginMsgWithVariablePayload ; R3, R4, R16, R17, R18, R19, R20, R21, X
|
||||
st X+, r7 ; 6: value id
|
||||
st X+, r12 ; 7: value type
|
||||
st X+, r8 ; 8: low value
|
||||
st X+, r9 ; 9: high value
|
||||
st X+, r10 ; 10: low denom
|
||||
st X+, r11 ; 11: high denom
|
||||
pop xl
|
||||
pop xh
|
||||
rcall com2CalcAndAddChecksumByte ; (R16, R17, R18, R19, X)
|
||||
ret
|
||||
|
||||
|
||||
|
||||
236
avr/modules/flash/flash.asm
Normal file
236
avr/modules/flash/flash.asm
Normal file
@@ -0,0 +1,236 @@
|
||||
; ***************************************************************************
|
||||
; 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
|
||||
|
||||
|
||||
FLASH_BEGIN:
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; start flashing a page
|
||||
;
|
||||
; Interrupts must be disabled!
|
||||
;
|
||||
; IN:
|
||||
; - Z: Address to work on (byte address as for LPM!)
|
||||
; OUT:
|
||||
; - nothing
|
||||
; REGS: R16 (R0, R1, R16, R20, R24, R25)
|
||||
|
||||
Flash_StartPage:
|
||||
push zh
|
||||
push zl
|
||||
ldi r16, ~((PAGESIZE*2)-1)
|
||||
and zl, r16
|
||||
rcall Flash_ReadPageIntoPageBuffer ; (R0, R1, R16, R20, R24, R25, Z)
|
||||
pop zl
|
||||
pop zh
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; finish flashing a page
|
||||
;
|
||||
; Interrupts must be disabled!
|
||||
;
|
||||
; IN:
|
||||
; - Z: Address to work on (byte address as for LPM!)
|
||||
; OUT:
|
||||
; - nothing
|
||||
; REGS: R16 (R15, R20)
|
||||
|
||||
Flash_FinishPage:
|
||||
ldi r16, ~((PAGESIZE*2)-1)
|
||||
and zl, r16
|
||||
rcall Flash_ErasePage ; (R15, R16, R20)
|
||||
rcall Flash_WritePage ; (R15, R16, R20)
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Flash_ReadPageIntoPageBuffer
|
||||
;
|
||||
; Interrupts must be disabled!
|
||||
;
|
||||
; IN:
|
||||
; - Z: Address to read from (byte address as for LPM!)
|
||||
; OUT:
|
||||
; - nothing
|
||||
; REGS: R0, R1, R16, R20, R24, R25, Z
|
||||
|
||||
Flash_ReadPageIntoPageBuffer:
|
||||
ldi r24, LOW(PAGESIZE*2)
|
||||
ldi r25, HIGH(PAGESIZE*2)
|
||||
Flash_ReadPageIntoPageBuffer_loop:
|
||||
lpm r0, Z+ ; read source data from FLASH (low)
|
||||
lpm r1, Z ; read source data from FLASH (high)
|
||||
sbiw ZH:ZL, 1 ; rewind Z address for following SPM
|
||||
ldi r20, (1<<SPMEN) ; enable next SPM, write into temp page buffer
|
||||
rcall flashDoSpm ; (R16)
|
||||
adiw ZH:ZL, 2
|
||||
sbiw r25:r24, 2 ; use subi for PAGESIZEB<=256
|
||||
brne Flash_ReadPageIntoPageBuffer_loop
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Flash_WriteIntoPage
|
||||
;
|
||||
; Interrupts must be disabled!
|
||||
;
|
||||
; IN:
|
||||
; - Z: Address to write to (byte address as for LPM!)
|
||||
; - R1:R0: Word to write into page
|
||||
; OUT:
|
||||
; - Z: address for next write
|
||||
; REGS: R16
|
||||
|
||||
Flash_WriteIntoPage:
|
||||
ldi r20, (1<<SPMEN) ; enable next SPM, write into temp page buffer
|
||||
rcall flashDoSpm ; (R16)
|
||||
adiw zh:zl, 2
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Flash_ErasePage
|
||||
;
|
||||
; Interrupts must be disabled!
|
||||
;
|
||||
; IN:
|
||||
; - Z: Address of the page to erase.
|
||||
; OUT:
|
||||
; - nothing
|
||||
; REGS: R20 (R16)
|
||||
|
||||
Flash_ErasePage:
|
||||
ldi r20, (1<<PGERS) + (1<<SPMEN) ; enable next SPM, erase page (R1/R0 ignored)
|
||||
rcall flashDoSpm ; (R16)
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Flash_WritePage
|
||||
;
|
||||
; Interrupts must be disabled!
|
||||
;
|
||||
; IN:
|
||||
; - Z: Address of the page to erase.
|
||||
; OUT:
|
||||
; - nothing
|
||||
; REGS: R15, R20 (R16)
|
||||
|
||||
Flash_WritePage:
|
||||
ldi r20, (1<<PGWRT) + (1<<SPMEN) ; enable next SPM, write page (R1/R0 ignored)
|
||||
rcall flashDoSpm ; (R16)
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; flashDoSpm
|
||||
;
|
||||
; wait until possible previous SPM finished and then issue another SPM.
|
||||
;
|
||||
; IN:
|
||||
; - R20: value for register SPMCR
|
||||
; - R0: low value for SPM
|
||||
; - R1: high value for SPM
|
||||
; - Z : address for SPM (byte address!)
|
||||
; OUT:
|
||||
; - nothing
|
||||
; REGS: R16
|
||||
|
||||
flashDoSpm:
|
||||
wait: ; wait for possibly previous SPM to complete
|
||||
in r16, SPMCSR
|
||||
sbrc r16, SPMEN
|
||||
rjmp wait
|
||||
; SPM timed sequence
|
||||
out SPMCSR, r20
|
||||
spm
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; flashReadEepromIncr
|
||||
;
|
||||
; Read a byte from EEPROM (see example in ATtiny24/44/84 manual p.19).
|
||||
;
|
||||
; IN:
|
||||
; - X: EEPROM Address to read from
|
||||
; OUT:
|
||||
; - R16: byte read
|
||||
; - X: EEPROM Address incremented
|
||||
; REGS: R16
|
||||
|
||||
flashReadEepromIncr:
|
||||
sbic EECR, EEPE ; wait for previous write to complete (if any)
|
||||
rjmp flashReadEepromIncr
|
||||
out EEARH, xh ; set EEPROM address
|
||||
out EEARL, xl
|
||||
sbi EECR, EERE ; start EEPROM read by writing EERE
|
||||
in r16, EEDR ; read data from data register
|
||||
adiw xh:xl, 1
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; flashReadUid
|
||||
;
|
||||
; Read UID from EEPROM.
|
||||
;
|
||||
; IN:
|
||||
; OUT:
|
||||
; - R18:R19:R20:R21: UID
|
||||
; REGS: R16, X
|
||||
|
||||
flashReadUid:
|
||||
push r15
|
||||
in r15, SREG
|
||||
cli
|
||||
ldi xl, LOW(EEPROM_OFFS_UUID)
|
||||
ldi xh, HIGH(EEPROM_OFFS_UUID)
|
||||
rcall flashReadEepromIncr ; (R16)
|
||||
mov r18, r16
|
||||
rcall flashReadEepromIncr ; (R16)
|
||||
mov r19, r16
|
||||
rcall flashReadEepromIncr ; (R16)
|
||||
mov r20, r16
|
||||
rcall flashReadEepromIncr ; (R16)
|
||||
mov r21, r16
|
||||
out SREG, r15
|
||||
pop r15
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
FLASH_END:
|
||||
.equ MODULE_SIZE_FLASH = FLASH_END-FLASH_BEGIN
|
||||
|
||||
|
||||
|
||||
600
avr/modules/flash/flashproto.asm
Normal file
600
avr/modules/flash/flashproto.asm
Normal file
@@ -0,0 +1,600 @@
|
||||
; ***************************************************************************
|
||||
; 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. *
|
||||
; ***************************************************************************
|
||||
|
||||
|
||||
|
||||
.equ FLASH_ERROR_NONE = 0
|
||||
.equ FLASH_ERROR_MSGERROR = 1
|
||||
|
||||
.equ FLASH_RECVBUFFER_MAXLEN = 128
|
||||
.equ FLASH_CMD_FLASH_RSP = 74
|
||||
|
||||
|
||||
.equ FLASH_MSG_OFFS_DESTADDR = 0
|
||||
.equ FLASH_MSG_OFFS_MSGLEN = 1
|
||||
.equ FLASH_MSG_OFFS_MSGDATA = 2
|
||||
.equ FLASH_MSG_OFFS_CMD = 2 ; first at COM2_MSG_OFFS_MSGDATA
|
||||
.equ FLASH_MSG_OFFS_SRCADDR = 3
|
||||
.equ FLASH_MSG_OFFS_PAYLOAD = 4 ; payload for the cmd follows here
|
||||
|
||||
|
||||
.equ FLASH_PACKET_DATA_OFFS_ADDR = FLASH_MSG_OFFS_PAYLOAD+0 ; 4 bytes
|
||||
.equ FLASH_PACKET_DATA_OFFS_DATA = FLASH_MSG_OFFS_PAYLOAD+4 ; n bytes
|
||||
|
||||
.equ FLASH_PACKET_START_OFFS_UID = FLASH_MSG_OFFS_PAYLOAD+0 ; 4 bytes
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; data
|
||||
|
||||
|
||||
.dseg
|
||||
|
||||
flashDataBegin:
|
||||
flashUid: .byte 4
|
||||
flashSendBuffer: .byte 32
|
||||
flashRecvBuffer: .byte FLASH_RECVBUFFER_MAXLEN
|
||||
flashDataEnd:
|
||||
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; code
|
||||
|
||||
|
||||
.cseg
|
||||
|
||||
|
||||
|
||||
FLASH_PROTO_BEGIN:
|
||||
|
||||
|
||||
|
||||
|
||||
bootLoader:
|
||||
cli ; disable interrupts throughout the whole process
|
||||
|
||||
; setup stack
|
||||
.ifdef SPH ; if SPH is defined
|
||||
ldi r16, High(RAMEND)
|
||||
out SPH, r16 ; init MSB stack pointer
|
||||
.endif
|
||||
ldi r16, Low(RAMEND)
|
||||
out SPL, r16 ; init LSB stack pointer
|
||||
|
||||
; rcall watchdogOff ; turn off watchdog timer (sometimes it stays on after reboot)
|
||||
|
||||
; 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 DDRA, PORTA3 ; out
|
||||
cbi PORTA, PORTA3 ; on
|
||||
sbi DDRA, PORTA2 ; out (debug)
|
||||
sbi PORTA, PORTA2 ; off (debug)
|
||||
|
||||
rcall flashReadUid
|
||||
sts flashUid, r18
|
||||
sts flashUid+1, r19
|
||||
sts flashUid+2, r20
|
||||
sts flashUid+3, r21
|
||||
|
||||
; wait for 3 secs before sending message
|
||||
ldi r16, 30
|
||||
rcall flashWaitForMulti100ms
|
||||
|
||||
; send flash ready message
|
||||
ldi xl, LOW(flashSendBuffer)
|
||||
ldi xh, HIGH(flashSendBuffer)
|
||||
rcall flashWriteFlashReady
|
||||
rcall flashSendPacketUntilSuccess
|
||||
|
||||
sbi PORTA, PORTA3 ; LED off
|
||||
|
||||
bootLoader_loop1:
|
||||
; wait up to 10s for incoming FLASH_START message
|
||||
ldi r16, CPRO_CMD_FLASH_START
|
||||
ldi r17, 100 ; 100*100ms=10s
|
||||
rcall flashWaitForSpecificMessageWithLed
|
||||
brcc bootLoader_startFirmware
|
||||
|
||||
; either FLASH_START or FLASH_END received
|
||||
cpi r16, CPRO_CMD_FLASH_START ; not FLASH_START, no flashing requested
|
||||
brne bootLoader_startFirmware
|
||||
; receive and flash new firmware
|
||||
|
||||
rcall flashHandleFlashStart
|
||||
brcc bootLoader_loop1
|
||||
; received a FLASH START msg, handle flashing
|
||||
rcall bootLoaderFlash
|
||||
brcc bootLoader_waitAndRestartBootLoader
|
||||
|
||||
; try to start firmware
|
||||
bootLoader_startFirmware:
|
||||
sbi PORTA, PORTA3 ; LED off
|
||||
|
||||
ldi r16, 20
|
||||
rcall flashWaitForMulti100ms
|
||||
rjmp firmwareStart
|
||||
|
||||
bootLoader_waitAndRestartBootLoader:
|
||||
sbi PORTA, PORTA3 ; LED off
|
||||
ldi r16, 20
|
||||
rcall flashWaitForMulti100ms
|
||||
rjmp bootLoader
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bootLoaderFlash:
|
||||
bootLoaderFlash_loop1:
|
||||
; wait up to 10s for incoming FLASH_DATA message
|
||||
ldi r16, CPRO_CMD_FLASH_DATA
|
||||
ldi r17, 100 ; 100*100ms=10s
|
||||
rcall flashWaitForSpecificMessageWithLed
|
||||
brcc bootLoaderFlash_error
|
||||
|
||||
; either FLASH_DATA or FLASH_END received
|
||||
cpi r16, CPRO_CMD_FLASH_DATA ; not FLASH_DATA, flashing ended/aborted
|
||||
brne bootLoaderFlash_end
|
||||
; flash data
|
||||
rcall flashHandleFlashData
|
||||
rjmp bootLoaderFlash_loop1
|
||||
bootLoaderFlash_end:
|
||||
sec
|
||||
ret
|
||||
bootLoaderFlash_error:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; wait for a specific message to arrive within given time, flashing LED
|
||||
;
|
||||
; IN:
|
||||
; - R16: message type to receive
|
||||
; - R17: wait time in 100ms (1=100ms, 2=200ms etc.)
|
||||
; OUT:
|
||||
; - CFLAG: set if msg received (either expected msg or FLASH_END), cleared otherwise
|
||||
; - R16: message type received (if CFLAG set)
|
||||
; REGS: R2, R16, R17 (R1, R24, R25, X)
|
||||
|
||||
flashWaitForSpecificMessageWithLed:
|
||||
mov r2, r16
|
||||
sbi PORTA, PORTA3 ; LED off
|
||||
|
||||
flashWaitForSpecificMessageWithLed_loop:
|
||||
sbi PINA, PORTA3 ; toggle LED
|
||||
mov r16, r2
|
||||
push r17
|
||||
ldi r17, 100 ; wait up to 100ms
|
||||
rcall flashWaitForSpecificMessage ; (R1, R16, R17, R24, R25, X)
|
||||
pop r17
|
||||
brcs flashWaitForSpecificMessageWithLed_received
|
||||
dec r17
|
||||
brne flashWaitForSpecificMessageWithLed_loop
|
||||
sbi PORTA, PORTA3 ; off
|
||||
clc
|
||||
ret
|
||||
flashWaitForSpecificMessageWithLed_received:
|
||||
sbi PORTA, PORTA3 ; off
|
||||
sec
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; wait for a specific message to arrive within given time.
|
||||
;
|
||||
; IN:
|
||||
; - R16: msg command to wait for
|
||||
; - R17: time to wait for packet (in milliseconds)
|
||||
; OUT:
|
||||
; - CFLAG: set if msg received, cleared on timeout
|
||||
; - R16 : message type received
|
||||
; REGS: R1, R16, R17, X (R24, R25)
|
||||
|
||||
flashWaitForSpecificMessage:
|
||||
mov r1, r16 ; expected message type
|
||||
flashWaitForSpecificMessage_loop0:
|
||||
; wait for ATTN to go low
|
||||
flashWaitForSpecificMessage_loop1:
|
||||
ldi r16, 0 ; wait for low
|
||||
rcall flashWaitForAttnState1ms ; (R22, R24)
|
||||
brcs flashWaitForSpecificMessage_isLow
|
||||
dec r17
|
||||
brne flashWaitForSpecificMessage_loop1
|
||||
rjmp flashWaitForSpecificMessage_timeout
|
||||
; receive message
|
||||
flashWaitForSpecificMessage_isLow: ; is low, receive message, check for msg type
|
||||
push r17
|
||||
ldi r16, COM2_MAINTENANCE_ADDR
|
||||
ldi r17, FLASH_RECVBUFFER_MAXLEN-3
|
||||
ldi xl, LOW(flashRecvBuffer)
|
||||
ldi xh, HIGH(flashRecvBuffer)
|
||||
rcall com2ReceivePacketRaw
|
||||
pop r17
|
||||
brcc flashWaitForSpecificMessage_waitAttnHigh
|
||||
ldi xl, LOW(flashRecvBuffer)
|
||||
ldi xh, HIGH(flashRecvBuffer)
|
||||
adiw xh:xl, COM2_MSG_OFFS_CMD
|
||||
ld r16, X
|
||||
sbiw xh:xl, COM2_MSG_OFFS_CMD
|
||||
cp r16, r1
|
||||
breq flashWaitForSpecificMessage_received
|
||||
cpi r16, CPRO_CMD_FLASH_END
|
||||
breq flashWaitForSpecificMessage_received
|
||||
|
||||
flashWaitForSpecificMessage_waitAttnHigh:
|
||||
dec r17
|
||||
breq flashWaitForSpecificMessage_timeout
|
||||
; wait for ATTN to go high
|
||||
flashWaitForSpecificMessage_loop2:
|
||||
ldi r16, 0xff ; wait for high
|
||||
rcall flashWaitForAttnState1ms ; (R22, R24)
|
||||
brcs flashWaitForSpecificMessage_isHigh
|
||||
dec r17
|
||||
brne flashWaitForSpecificMessage_loop2
|
||||
rjmp flashWaitForSpecificMessage_timeout
|
||||
|
||||
flashWaitForSpecificMessage_isHigh:
|
||||
rjmp flashWaitForSpecificMessage_loop0
|
||||
flashWaitForSpecificMessage_received: ; R16 contains message type
|
||||
sec
|
||||
ret
|
||||
flashWaitForSpecificMessage_timeout:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Wait for up to 1ms for ATTN line to reach the given state
|
||||
;
|
||||
; IN:
|
||||
; - R16: expected state (0xff for high, 0 for low)
|
||||
; OUT:
|
||||
; - CFLAG: set if state reached, cleared otherwise
|
||||
; REGS: R24 (R22)
|
||||
|
||||
flashWaitForAttnState1ms:
|
||||
ldi r24, 100
|
||||
flashWaitForAttnState1ms_loop:
|
||||
push r17
|
||||
in r17, COM_PIN_ATTN
|
||||
eor r17, r16
|
||||
andi r17, (1<<COM_PINNUM_ATTN)
|
||||
pop r17
|
||||
breq flashWaitForAttnState1ms_stateReached
|
||||
|
||||
Utils_WaitNanoSecs 10000, 0, r22 ; wait for 10us
|
||||
dec r24
|
||||
brne flashWaitForAttnState1ms_loop
|
||||
clc
|
||||
ret
|
||||
flashWaitForAttnState1ms_stateReached:
|
||||
sec
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; wait indefinately until ATTN line is high, send packet over wire, retry until successfull
|
||||
;
|
||||
; IN:
|
||||
; - x : ptr to buffer to send
|
||||
; OUT:
|
||||
; - nothing
|
||||
; REGS: R15, R16, R22 (R17, R21, X)
|
||||
|
||||
flashSendPacketUntilSuccess:
|
||||
push xl
|
||||
push xh
|
||||
rcall COM2_SendPacketWithAttn
|
||||
pop xh
|
||||
pop xl
|
||||
brcc flashSendPacket_error
|
||||
ret
|
||||
flashSendPacket_error:
|
||||
rcall flashWaitForAttnHigh
|
||||
rjmp flashSendPacketUntilSuccess
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; wait indefinately for free ATTN line
|
||||
;
|
||||
; IN:
|
||||
; - nothing
|
||||
; OUT:
|
||||
; - nothing
|
||||
; REGS: R15, R16, R22 (R17, R21, X)
|
||||
|
||||
flashWaitForAttnHigh:
|
||||
rcall com2WaitForAttnHigh ; waits for up to 100us
|
||||
brcc flashWaitForAttnHigh_stillLow
|
||||
ret
|
||||
flashWaitForAttnHigh_stillLow:
|
||||
rcall flashWaitDependingOnUid ; (R16, R18, R22, R24, R25)
|
||||
rjmp flashWaitForAttnHigh
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; wait depending on lowest byte of uid.
|
||||
;
|
||||
; Wait interval is between 100ms and 25s (i.e. 255*100ms). This is used to avoid
|
||||
; all nodes on the network trying to send messages at the exact same time (e.g. after
|
||||
; power outage which would affect all nodes at the same time).
|
||||
;
|
||||
; IN:
|
||||
; - nothing
|
||||
; OUT:
|
||||
; - nothing
|
||||
; REGS: R16 (R18, R22, R24, R25)
|
||||
|
||||
flashWaitDependingOnUid:
|
||||
lds r16, flashUid
|
||||
tst r16
|
||||
brne flashWaitDependingOnUid_l1
|
||||
ldi r16, 17
|
||||
flashWaitDependingOnUid_l1:
|
||||
rjmp flashWaitForMulti100ms
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; wait for multiples of 100ms.
|
||||
;
|
||||
; IN:
|
||||
; - R16: number of 100ms loops
|
||||
; OUT:
|
||||
; - nothing
|
||||
; REGS: R16 (R18, R22, R24, R25)
|
||||
|
||||
flashWaitForMulti100ms:
|
||||
flashWaitForMulti100ms_loop:
|
||||
rcall flashWaitFor100ms ; (R18, R22, R24, R25)
|
||||
dec r16
|
||||
brne flashWaitForMulti100ms_loop
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; wait for 100 milliseconds.
|
||||
;
|
||||
; IN:
|
||||
; - nothing
|
||||
; OUT:
|
||||
; - nothing
|
||||
; REGS: R18 (R22, R24, R25)
|
||||
|
||||
flashWaitFor100ms:
|
||||
ldi r18, 100
|
||||
flashWaitFor100ms_loop:
|
||||
rcall flashWaitFor1ms ; (R22, R24, R25)
|
||||
dec r18
|
||||
brne flashWaitFor100ms_loop
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; wait for 1 millisecond.
|
||||
;
|
||||
; IN:
|
||||
; - nothing
|
||||
; OUT:
|
||||
; - nothing
|
||||
; REGS: R24 (R22)
|
||||
|
||||
flashWaitFor1ms:
|
||||
ldi r24, 10
|
||||
flashWaitFor1ms_loop:
|
||||
Utils_WaitNanoSecs 100000, 0, r22 ; wait for 100us
|
||||
dec r24
|
||||
brne flashWaitFor1ms_loop
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Write a FLASH_RESPONSE packet.
|
||||
;
|
||||
; IN:
|
||||
; - R16: response code (0 if ok, error code otherwise)
|
||||
; - X : buffer to write to
|
||||
; OUT:
|
||||
; - nothing
|
||||
; MODIFIED REGS: R16, R17 (R18, R19, R20)
|
||||
|
||||
flashWriteFlashRsp:
|
||||
clr r18
|
||||
st X+, r18 ; dest address (unused)
|
||||
ldi r18, 3 ; msg code+src address+one payload byte
|
||||
st X+, r18 ; msg len
|
||||
ldi r17, CPRO_CMD_FLASH_RSP
|
||||
st X+, r17 ; msg code
|
||||
clr r17
|
||||
st X+, r17 ; src address (not used)
|
||||
st X, r16 ; payload byte
|
||||
sbiw xh:xl, 4
|
||||
rcall com2CalcAndAddChecksumByte ; (R16, R17, R18, R19, R20, X)
|
||||
sbiw xh:xl, 5
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Write a FLASH_READY packet.
|
||||
;
|
||||
; IN:
|
||||
; - X : buffer to write to
|
||||
; OUT:
|
||||
; - nothing
|
||||
; MODIFIED REGS: R16, Z (R17, R18, R19, R20)
|
||||
|
||||
flashWriteFlashReady:
|
||||
ldi r16, 0xff
|
||||
st X+, r16 ; dest address (unused)
|
||||
ldi r16, 12 ; msg code+src address+ten payload bytes
|
||||
st X+, r16 ; msg len
|
||||
ldi r16, CPRO_CMD_FLASH_READY
|
||||
st X+, r16 ; msg code
|
||||
ldi r16, COM2_MAINTENANCE_ADDR
|
||||
st X+, r16 ; src address (not used)
|
||||
; payload
|
||||
lds r16, flashUid
|
||||
st X+, r16
|
||||
lds r16, flashUid+1
|
||||
st X+, r16
|
||||
lds r16, flashUid+2
|
||||
st X+, r16
|
||||
lds r16, flashUid+3
|
||||
st X+, r16
|
||||
ldi zl, low(firmwareType*2)
|
||||
ldi zh, HIGH(firmwareType*2)
|
||||
lpm r16, Z+
|
||||
st X+, r16 ; firmwareType (low)
|
||||
lpm r16, Z+
|
||||
st X+, r16 ; firmwareType (high)
|
||||
lpm r16, Z+
|
||||
st X+, r16 ; firmwareVersion (low)
|
||||
lpm r16, Z+
|
||||
st X+, r16 ; firmwareVersion (high)
|
||||
ldi r16, LOW(PAGESIZE*2)
|
||||
st X+, r16
|
||||
ldi r16, HIGH(PAGESIZE*2)
|
||||
st X, r16
|
||||
sbiw xh:xl, 13
|
||||
rcall com2CalcAndAddChecksumByte ; (R16, R17, R18, R19, R20, X)
|
||||
sbiw xh:xl, 14
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Handle FLASH START packet.
|
||||
;
|
||||
; IN:
|
||||
; - X : buffer containing the message
|
||||
; OUT:
|
||||
; - CFLAG: set if message is for us, cleared otherwise
|
||||
; REGS: r16, r18. r19. r20, r21, X (R15, R17, R22)
|
||||
|
||||
flashHandleFlashStart:
|
||||
lds r18, flashUid
|
||||
lds r19, flashUid+1
|
||||
lds r20, flashUid+2
|
||||
lds r21, flashUid+3
|
||||
adiw xh:xl, FLASH_PACKET_START_OFFS_UID
|
||||
ld r16, X+
|
||||
cp r16, r18
|
||||
brne flashHandleFlashStart_notMe
|
||||
ld r16, X+
|
||||
cp r16, r19
|
||||
brne flashHandleFlashStart_notMe
|
||||
ld r16, X+
|
||||
cp r16, r20
|
||||
brne flashHandleFlashStart_notMe
|
||||
ld r16, X
|
||||
cp r16, r21
|
||||
brne flashHandleFlashStart_notMe
|
||||
; okay, flash start message is for us
|
||||
rcall flashWaitFor100ms
|
||||
rcall flashSendFlashResponse ; (R15, R16, R17, R18, R19, R20, R21, R22, X)
|
||||
sec
|
||||
ret
|
||||
flashHandleFlashStart_notMe:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Handle FLASH DATA packet.
|
||||
;
|
||||
; IN:
|
||||
; - X : buffer containing the message
|
||||
; OUT:
|
||||
; - CFLAG: set if message is for us, cleared otherwise
|
||||
; REGS: R0, R1, R15, R16, R17, R18, R19, R20, R21, R24, R25, X, Z
|
||||
|
||||
flashHandleFlashData:
|
||||
adiw xh:xl, FLASH_MSG_OFFS_MSGLEN
|
||||
ld r18, X ; length (subtract 6
|
||||
cpi r18, 6 ; cmd(1), src(1), addr(4)
|
||||
brcs flashHandleFlashData_badData
|
||||
subi r18, 6 ; remaining length
|
||||
adiw xh:xl, FLASH_PACKET_DATA_OFFS_ADDR-FLASH_MSG_OFFS_MSGLEN
|
||||
ld zl, X+ ; address (low)
|
||||
ld zh, X+ ; address (high)
|
||||
adiw xh:xl, 2 ; ignore high bytes, points to first data byte now
|
||||
|
||||
; rcall Flash_StartPage ; (R0, R1, R16, R20, R24, R25)
|
||||
push zl
|
||||
push zh
|
||||
flashHandleFlashData_loop:
|
||||
ld r0, X+
|
||||
ld r1, X+
|
||||
rcall Flash_WriteIntoPage ; (R15, R16, Z+)
|
||||
subi r18, 2
|
||||
brne flashHandleFlashData_loop
|
||||
pop zh
|
||||
pop zl
|
||||
rcall Flash_FinishPage ; (R15, R16, R20)
|
||||
clr r16
|
||||
rjmp flashHandleFlashData_sendResponse
|
||||
flashHandleFlashData_badData:
|
||||
ldi r16, FLASH_ERROR_MSGERROR
|
||||
flashHandleFlashData_sendResponse:
|
||||
rcall flashSendFlashResponse ; (R15, R16, R17, R18, R19, R20, R21, R22, X)
|
||||
sec
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Create and send a FLASH RESPONSE packet
|
||||
;
|
||||
; IN:
|
||||
; - R16: response code to send
|
||||
; OUT:
|
||||
; - nothing
|
||||
; REGS: r16, X (R15, R17, R18, R19, R20, R21, R22)
|
||||
|
||||
flashSendFlashResponse:
|
||||
; send flash ready message
|
||||
ldi xl, LOW(flashSendBuffer)
|
||||
ldi xh, HIGH(flashSendBuffer)
|
||||
clr r16
|
||||
rcall flashWriteFlashRsp ; (R16, R17, R18, R19, R20)
|
||||
rjmp flashSendPacketUntilSuccess ; (R15, R16, R17, R21, R22, X)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
FLASH_PROTO_END:
|
||||
.equ MODULE_SIZE_FLASH_PROTO = FLASH_PROTO_END-FLASH_PROTO_BEGIN
|
||||
|
||||
|
||||
825
avr/modules/lcd/lcd.asm
Normal file
825
avr/modules/lcd/lcd.asm
Normal file
@@ -0,0 +1,825 @@
|
||||
; ***************************************************************************
|
||||
; 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. *
|
||||
; ***************************************************************************
|
||||
|
||||
|
||||
|
||||
; Some code in this module is based on C-code in Tiny4kOLED (https://github.com/datacute/Tiny4kOLED/tree/master/src)
|
||||
; by Stephen Denne (MIT license), rewritten in AVR assembler
|
||||
;
|
||||
; - page 0 is top line, page 7 ist bottom line
|
||||
; - column 0 is the leftmost colum, column 127 is the rightmost column
|
||||
; - a page has a height of 8 (->8 bits)
|
||||
; - when writing a byte to a position (e.g. page 0, column 0)
|
||||
; - writing to chip RAM is done in columns
|
||||
;
|
||||
; Page 0: col 0 col 1 ... col 127
|
||||
; Row 0(LSB) 0/0 1/0 ... 127/0
|
||||
; Row 1 0/1 1/1 ... 127/1
|
||||
; Row 2 0/2 1/2 ... 127/2
|
||||
; Row 3 0/3 1/3 ... 127/3
|
||||
; ...
|
||||
; Row 7(MSB) 0/7 1/7 ... 127/7
|
||||
; and so one
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; defines
|
||||
|
||||
.equ LCD_WIDTH = 128
|
||||
.equ LCD_HEIGHT = 64
|
||||
|
||||
.equ LCD_PAGE_COUNT = 8
|
||||
|
||||
.equ LCD_CMD_MODE = 0x00
|
||||
.equ LCD_DATA_MODE = 0x40
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; data
|
||||
|
||||
.dseg
|
||||
|
||||
lcdDataBegin:
|
||||
lcdDataEnd:
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; code
|
||||
|
||||
.cseg
|
||||
|
||||
|
||||
LCD_BEGIN:
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; LCD_Init
|
||||
;
|
||||
; IN:
|
||||
; - nothing
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, clear on error
|
||||
; USED:
|
||||
|
||||
LCD_Init:
|
||||
ldi zl, LOW(lcdInitCommandsBegin)
|
||||
ldi zh, HIGH(lcdInitCommandsBegin)
|
||||
ldi r16, 8
|
||||
rcall lcdWriteCommandsFromFlash
|
||||
|
||||
ldi r16, 0
|
||||
rcall LCD_Fill
|
||||
|
||||
ldi r16, 255
|
||||
rcall LCD_Fill
|
||||
|
||||
ldi r16, 0
|
||||
rcall LCD_Fill
|
||||
|
||||
ldi r18, 20
|
||||
ldi r19, 0
|
||||
rcall LCD_SetCursor
|
||||
|
||||
ldi zl, LOW(lcdHelloMsg)
|
||||
ldi zh, HIGH(lcdHelloMsg)
|
||||
rcall LCD_PrintFromFlash
|
||||
|
||||
; set cursor to next line here, sometimes this doesn't work correctly
|
||||
; when called later. TODO: find out what goes wrong here...
|
||||
ldi r18, 0
|
||||
ldi r19, 2
|
||||
rcall LCD_SetCursor
|
||||
|
||||
sec
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; LCD_Fini
|
||||
;
|
||||
; IN:
|
||||
; - nothing
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, clear on error
|
||||
; USED:
|
||||
|
||||
LCD_Fini:
|
||||
sec
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; LCD_SetCursor
|
||||
;
|
||||
; Set cursor. X is specified in pixels, Y is specified in character rows (8 pixels).
|
||||
; Left upper corner is 0/0 (x/y), right lower corner is 127/7
|
||||
;
|
||||
; IN:
|
||||
; - R18: X
|
||||
; - R19: Y
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, cleared otherwise
|
||||
; REGS: r1, r2, r15, r16 (R16, R17, R18, R22)
|
||||
|
||||
LCD_SetCursor:
|
||||
in r15, SREG
|
||||
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)
|
||||
pop r15
|
||||
out SREG, r15
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; LCD_Fill
|
||||
;
|
||||
; Fill display RAM with the given value.
|
||||
;
|
||||
; IN:
|
||||
; - R16: data to write
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, cleared otherwise
|
||||
; REGS: r15, r16, r18, r19, r20, r21 (r17, r22)
|
||||
|
||||
LCD_Fill:
|
||||
in r15, SREG
|
||||
push r15
|
||||
cli
|
||||
mov r20, r16
|
||||
|
||||
ldi r21, 0 ; Y
|
||||
LCD_Fill_loopY:
|
||||
clr r18
|
||||
mov r19, r21
|
||||
rcall LCD_SetCursor
|
||||
brcc LCD_Fill_error
|
||||
|
||||
rcall twiStart
|
||||
ldi r16, (LCD_TWI_ADDRESS*2)
|
||||
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
|
||||
brcc LCD_Fill_error
|
||||
ldi r16, LCD_DATA_MODE
|
||||
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
|
||||
brcc LCD_Fill_error
|
||||
|
||||
ldi r19, 0
|
||||
LCD_Fill_loopX:
|
||||
mov r16, r20
|
||||
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
|
||||
rcall twiSendByte
|
||||
brcc LCD_Fill_error
|
||||
inc r19
|
||||
cpi r19, LCD_WIDTH
|
||||
brcs LCD_Fill_loopX
|
||||
rcall twiStop
|
||||
inc r21
|
||||
cpi r21, LCD_PAGE_COUNT
|
||||
brcs LCD_Fill_loopY
|
||||
pop r15
|
||||
out SREG, r15
|
||||
sec
|
||||
ret
|
||||
LCD_Fill_error:
|
||||
rcall twiStop
|
||||
pop r15
|
||||
out SREG, r15
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; LCD_PrintFromFlash
|
||||
;
|
||||
; Print a string from flash at the current position.
|
||||
;
|
||||
; IN:
|
||||
; - Z: position of string to print
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, cleared otherwise
|
||||
; REGS: r15, r16, Z (R17, R18, R22)
|
||||
|
||||
LCD_PrintFromFlash:
|
||||
in r15, SREG
|
||||
push r15
|
||||
cli
|
||||
lsl zl
|
||||
rol zh
|
||||
rcall twiStart
|
||||
ldi r16, (LCD_TWI_ADDRESS*2)
|
||||
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
|
||||
brcc LCD_PrintFromFlash_error
|
||||
ldi r16, LCD_DATA_MODE
|
||||
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
|
||||
brcc LCD_PrintFromFlash_error
|
||||
|
||||
LCD_PrintFromFlash_loop:
|
||||
lpm r16, z+
|
||||
tst r16
|
||||
breq LCD_PrintFromFlash_end
|
||||
push zh
|
||||
push zl
|
||||
rcall lcdPrintOneChar
|
||||
pop zl
|
||||
pop zh
|
||||
brcc LCD_PrintFromFlash_error
|
||||
rjmp LCD_PrintFromFlash_loop
|
||||
LCD_PrintFromFlash_end:
|
||||
rcall twiStop
|
||||
pop r15
|
||||
out SREG, r15
|
||||
sec
|
||||
ret
|
||||
|
||||
LCD_PrintFromFlash_error:
|
||||
rcall twiStop
|
||||
pop r15
|
||||
out SREG, r15
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; LCD_PrintChar
|
||||
;
|
||||
; Print a character at the current position.
|
||||
;
|
||||
; IN:
|
||||
; - R16: char
|
||||
; OUT:
|
||||
; REGS: r15, r16, r17, Z
|
||||
|
||||
LCD_PrintChar:
|
||||
in r15, SREG
|
||||
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
|
||||
pop r15
|
||||
out SREG, r15
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; LCD_PrintHexByte
|
||||
;
|
||||
; Convert a given byte into HEX and write it to the current position.
|
||||
;
|
||||
; IN:
|
||||
; - R16: byte to convert to hex
|
||||
; OUT:
|
||||
; REGS: r15, r16, r17, Z
|
||||
|
||||
LCD_PrintHexByte:
|
||||
in r15, SREG
|
||||
push r15
|
||||
cli
|
||||
mov r20, r16
|
||||
rcall twiStart
|
||||
ldi r16, (LCD_TWI_ADDRESS*2)
|
||||
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
|
||||
brcc LCD_PrintHexByte_error
|
||||
ldi r16, LCD_DATA_MODE
|
||||
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
|
||||
brcc LCD_PrintHexByte_error
|
||||
mov r16, r20
|
||||
rcall lcdPrintHexByte
|
||||
brcc LCD_PrintHexByte_error
|
||||
rcall twiStop
|
||||
pop r15
|
||||
out SREG, r15
|
||||
sec
|
||||
ret
|
||||
LCD_PrintHexByte_error:
|
||||
rcall twiStop
|
||||
pop r15
|
||||
out SREG, r15
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; LCD_PrintHexWord
|
||||
;
|
||||
; Convert a give word into HEX and write it to the current position.
|
||||
;
|
||||
; IN:
|
||||
; - r18: low byte of the word
|
||||
; - r19: high byte of the word
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, cleared otherwise
|
||||
; REGS: r15, r16, r17, Z
|
||||
|
||||
LCD_PrintHexWord:
|
||||
in r15, SREG
|
||||
push r15
|
||||
cli
|
||||
push r18
|
||||
push r19
|
||||
rcall twiStart
|
||||
ldi r16, (LCD_TWI_ADDRESS*2)
|
||||
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
|
||||
brcc LCD_PrintHexWord_errorPop
|
||||
ldi r16, LCD_DATA_MODE
|
||||
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
|
||||
brcc LCD_PrintHexWord_errorPop
|
||||
pop r19
|
||||
pop r18
|
||||
|
||||
rcall lcdPrintHexWord
|
||||
brcc LCD_PrintHexWord_errorNoPop
|
||||
rcall twiStop
|
||||
pop r15
|
||||
out SREG, r15
|
||||
sec
|
||||
ret
|
||||
LCD_PrintHexWord_errorPop:
|
||||
rcall twiStop
|
||||
pop r19
|
||||
pop r18
|
||||
LCD_PrintHexWord_errorNoPop:
|
||||
pop r15
|
||||
out SREG, r15
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; lcdPrintHexWord
|
||||
;
|
||||
; Convert a given word into HEX and write it to the current position.
|
||||
;
|
||||
; IN:
|
||||
; - r18: low byte of the word
|
||||
; - r19: high byte of the word
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, cleared otherwise
|
||||
|
||||
lcdPrintHexWord:
|
||||
mov r16, r19
|
||||
push r18
|
||||
rcall lcdPrintHexByte
|
||||
pop r18
|
||||
brcc lcdPrintHexWord_error
|
||||
mov r16, r18
|
||||
rcall lcdPrintHexByte
|
||||
brcc lcdPrintHexWord_error
|
||||
sec
|
||||
ret
|
||||
lcdPrintHexWord_error:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; lcdPrintHexByte
|
||||
;
|
||||
; Convert a give byte into HEX and write it to the current position.
|
||||
;
|
||||
; IN:
|
||||
; - R16: byte to convert to hex
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, cleared otherwise
|
||||
; REGS: r16, r20 (r16, r17)
|
||||
|
||||
lcdPrintHexByte:
|
||||
mov r20, r16
|
||||
swap r16
|
||||
rcall lcdNibbleToAscii ; write high nibble (r16, r17)
|
||||
rcall lcdPrintOneChar ; (r16, r17, Z)
|
||||
brcc lcdPrintHexByte_error
|
||||
mov r16, r20
|
||||
rcall lcdNibbleToAscii ; write low nibble
|
||||
rcall lcdPrintOneChar
|
||||
brcc lcdPrintHexByte_error
|
||||
sec
|
||||
ret
|
||||
lcdPrintHexByte_error:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; lcdNibbleToAscii
|
||||
;
|
||||
; Convert a nibble to an ASCII char.
|
||||
; IN:
|
||||
; - R16: byte (in bits 0-3)
|
||||
; OUT:
|
||||
; - R16: ASCII representation of that nibble (e.g. '0' for 0)
|
||||
; REGS: r16, r17
|
||||
|
||||
lcdNibbleToAscii:
|
||||
andi r16, 0xf
|
||||
cpi r16, 10
|
||||
brcs lcdNibbleToAscii_l1
|
||||
ldi r17, 7
|
||||
add r16, r17
|
||||
lcdNibbleToAscii_l1:
|
||||
ldi r17, '0'
|
||||
add r16, r17
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; lcdWriteCommandsFromFlash
|
||||
;
|
||||
; IN:
|
||||
; - R16: number of bytes to send
|
||||
; - Z=pointer to data
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, cleared otherwise
|
||||
|
||||
; REGS: r16, r20, Z (r17, r18, r22)
|
||||
|
||||
lcdWriteCommandsFromFlash:
|
||||
rcall twiStart
|
||||
lsl zl
|
||||
rol zh
|
||||
mov r20, r16 ; number of bytes
|
||||
ldi r16, (LCD_TWI_ADDRESS*2)
|
||||
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
|
||||
brcc lcdWriteCommandsFromFlash_error
|
||||
|
||||
lcdWriteCommandsFromFlash_loop:
|
||||
lpm r16, z+
|
||||
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
|
||||
brcc lcdWriteCommandsFromFlash_error
|
||||
dec r20
|
||||
brne lcdWriteCommandsFromFlash_loop
|
||||
rcall twiStop ; (R22)
|
||||
sec
|
||||
ret
|
||||
|
||||
lcdWriteCommandsFromFlash_error:
|
||||
rcall twiStop
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; lcdPrintOneChar
|
||||
;
|
||||
; Print a character at the current position.
|
||||
;
|
||||
; IN:
|
||||
; - R16: char
|
||||
; OUT:
|
||||
; REGS: r16, r19, Z (R17, R18, R22)
|
||||
|
||||
lcdPrintOneChar:
|
||||
rcall lcdGetCharMatrix ; (r16, r17, Z)
|
||||
ldi r16, 0 ; spacing between chars
|
||||
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
|
||||
brcc lcdPrintOneChar_error
|
||||
ldi r19, 6
|
||||
lcdPrintOneChar_loop:
|
||||
lpm r16, z+
|
||||
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
|
||||
brcc lcdPrintOneChar_error
|
||||
dec r19
|
||||
brne lcdPrintOneChar_loop
|
||||
sec
|
||||
ret
|
||||
|
||||
lcdPrintOneChar_error:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; lcdGetCharMatrix
|
||||
;
|
||||
; Get pointer to matrix of given char.
|
||||
;
|
||||
; IN:
|
||||
; - R16: char
|
||||
; OUT:
|
||||
; - Z: pos of character matrix (ready for LPM)
|
||||
; REGS: r16, r17, Z
|
||||
|
||||
lcdGetCharMatrix:
|
||||
#ifdef LCD_MINIMAL_FONT
|
||||
rcall lcdUpcase
|
||||
cpi r16, 65+32
|
||||
brcc lcdGetCharMatrix_l1
|
||||
cpi r16, 32
|
||||
brcc lcdGetCharMatrix_l2
|
||||
lcdGetCharMatrix_l1:
|
||||
ldi r16, 32
|
||||
lcdGetCharMatrix_l2:
|
||||
ldi r17, 32
|
||||
sub r16, r17
|
||||
mov zl, r16
|
||||
clr zh
|
||||
clr r17
|
||||
lsl zl ; *2
|
||||
rol zh
|
||||
add zl, r16 ; *3
|
||||
adc zh, r17
|
||||
lsl zl ; *6
|
||||
rol zh
|
||||
ldi r16, LOW(lcdFont6x8Minimal*2)
|
||||
ldi r17, HIGH(lcdFont6x8Minimal*2)
|
||||
add zl, r16
|
||||
adc zh, r17
|
||||
ret
|
||||
#else
|
||||
cpi r16, 95+32
|
||||
brcc lcdGetCharMatrix_l1
|
||||
cpi r16, 32
|
||||
brcc lcdGetCharMatrix_l2
|
||||
lcdGetCharMatrix_l1:
|
||||
ldi r16, 32
|
||||
lcdGetCharMatrix_l2:
|
||||
ldi r17, 32
|
||||
sub r16, r17
|
||||
mov zl, r16
|
||||
clr zh
|
||||
clr r17
|
||||
lsl zl ; *2
|
||||
rol zh
|
||||
add zl, r16 ; *3
|
||||
adc zh, r17
|
||||
lsl zl ; *6
|
||||
rol zh
|
||||
ldi r16, LOW(lcdFont6x8*2)
|
||||
ldi r17, HIGH(lcdFont6x8*2)
|
||||
add zl, r16
|
||||
adc zh, r17
|
||||
ret
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef LCD_MINIMAL_FONT
|
||||
; ---------------------------------------------------------------------------
|
||||
; Uppercase the given character if it is lower case.
|
||||
;
|
||||
; IN:
|
||||
; - R16: char
|
||||
; OUT:
|
||||
; - R16: char
|
||||
; REGS: r16, r17
|
||||
|
||||
lcdUpcase:
|
||||
cpi r16, 'a'
|
||||
brcs lcdUpcase_done
|
||||
cpi r16, 'z'+1
|
||||
brcc lcdUpcase_done
|
||||
ldi r17, 32
|
||||
sub r16, r17
|
||||
lcdUpcase_done:
|
||||
ret
|
||||
#endif
|
||||
|
||||
|
||||
; TODO: set adressing mode??
|
||||
lcdInitCommandsBegin: ; 28 bytes
|
||||
.db LCD_CMD_MODE, 0xa8, ((LCD_PAGE_COUNT*8)-1), 0x8d, 0x14, 0xaf, 0xa1, 0xc8
|
||||
lcdInitCommandsEnd:
|
||||
|
||||
lcdHelloMsg: .db "AqHOME 2023", 0
|
||||
|
||||
|
||||
; font taken from Tiny4kOLED (https://github.com/datacute/Tiny4kOLED/tree/master/src) by Stephen Denne (MIT license),
|
||||
; original by Neven Boyanov
|
||||
#ifdef LCD_MINIMAL_FONT
|
||||
lcdFont6x8Minimal:
|
||||
.db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ; 0
|
||||
.db 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00 ; ! 1
|
||||
.db 0x00, 0x00, 0x07, 0x00, 0x07, 0x00 ; " 2
|
||||
.db 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14 ; # 3
|
||||
.db 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12 ; $ 4
|
||||
.db 0x00, 0x62, 0x64, 0x08, 0x13, 0x23 ; % 5
|
||||
.db 0x00, 0x36, 0x49, 0x55, 0x22, 0x50 ; & 6
|
||||
.db 0x00, 0x00, 0x05, 0x03, 0x00, 0x00 ; ' 7
|
||||
.db 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00 ; ( 8
|
||||
.db 0x00, 0x00, 0x41, 0x22, 0x1c, 0x00 ; ) 9
|
||||
.db 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14 ; * 10
|
||||
.db 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08 ; + 11
|
||||
.db 0x00, 0x00, 0x00, 0xA0, 0x60, 0x00 ; , 12
|
||||
.db 0x00, 0x08, 0x08, 0x08, 0x08, 0x08 ; - 13
|
||||
.db 0x00, 0x00, 0x60, 0x60, 0x00, 0x00 ; . 14
|
||||
.db 0x00, 0x20, 0x10, 0x08, 0x04, 0x02 ; / 15
|
||||
.db 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E ; 0 16
|
||||
.db 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00 ; 1 17
|
||||
.db 0x00, 0x42, 0x61, 0x51, 0x49, 0x46 ; 2 18
|
||||
.db 0x00, 0x21, 0x41, 0x45, 0x4B, 0x31 ; 3 19
|
||||
.db 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10 ; 4 20
|
||||
.db 0x00, 0x27, 0x45, 0x45, 0x45, 0x39 ; 5 21
|
||||
.db 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30 ; 6 22
|
||||
.db 0x00, 0x01, 0x71, 0x09, 0x05, 0x03 ; 7 23
|
||||
.db 0x00, 0x36, 0x49, 0x49, 0x49, 0x36 ; 8 24
|
||||
.db 0x00, 0x06, 0x49, 0x49, 0x29, 0x1E ; 9 25
|
||||
.db 0x00, 0x00, 0x36, 0x36, 0x00, 0x00 ; : 26
|
||||
.db 0x00, 0x00, 0x56, 0x36, 0x00, 0x00 ; ; 27
|
||||
.db 0x00, 0x08, 0x14, 0x22, 0x41, 0x00 ; < 28
|
||||
.db 0x00, 0x14, 0x14, 0x14, 0x14, 0x14 ; = 29
|
||||
.db 0x00, 0x00, 0x41, 0x22, 0x14, 0x08 ; > 30
|
||||
.db 0x00, 0x02, 0x01, 0x51, 0x09, 0x06 ; ? 31
|
||||
.db 0x00, 0x32, 0x49, 0x59, 0x51, 0x3E ; @ 32
|
||||
.db 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C ; A 33
|
||||
.db 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36 ; B 34
|
||||
.db 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22 ; C 35
|
||||
.db 0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C ; D 36
|
||||
.db 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41 ; E 37
|
||||
.db 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01 ; F 38
|
||||
.db 0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A ; G 39
|
||||
.db 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F ; H 40
|
||||
.db 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00 ; I 41
|
||||
.db 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01 ; J 42
|
||||
.db 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41 ; K 43
|
||||
.db 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40 ; L 44
|
||||
.db 0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F ; M 45
|
||||
.db 0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F ; N 46
|
||||
.db 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E ; O 47
|
||||
.db 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06 ; P 48
|
||||
.db 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E ; Q 49
|
||||
.db 0x00, 0x7F, 0x09, 0x19, 0x29, 0x46 ; R 50
|
||||
.db 0x00, 0x46, 0x49, 0x49, 0x49, 0x31 ; S 51
|
||||
.db 0x00, 0x01, 0x01, 0x7F, 0x01, 0x01 ; T 52
|
||||
.db 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F ; U 53
|
||||
.db 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F ; V 54
|
||||
.db 0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F ; W 55
|
||||
.db 0x00, 0x63, 0x14, 0x08, 0x14, 0x63 ; X 56
|
||||
.db 0x00, 0x07, 0x08, 0x70, 0x08, 0x07 ; Y 57
|
||||
.db 0x00, 0x61, 0x51, 0x49, 0x45, 0x43 ; Z 58
|
||||
.db 0x00, 0x00, 0x7F, 0x41, 0x41, 0x00 ; [ 59
|
||||
.db 0x00, 0x02, 0x04, 0x08, 0x10, 0x20 ; \ 60
|
||||
.db 0x00, 0x00, 0x41, 0x41, 0x7F, 0x00 ; ] 61
|
||||
.db 0x00, 0x04, 0x02, 0x01, 0x02, 0x04 ; ^ 62
|
||||
.db 0x00, 0x40, 0x40, 0x40, 0x40, 0x40 ; _ 63
|
||||
.db 0x00, 0x00, 0x01, 0x02, 0x04, 0x00 ; ' 64
|
||||
#else
|
||||
lcdFont6x8:
|
||||
.db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ; 0
|
||||
.db 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00 ; ! 1
|
||||
.db 0x00, 0x00, 0x07, 0x00, 0x07, 0x00 ; " 2
|
||||
.db 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14 ; # 3
|
||||
.db 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12 ; $ 4
|
||||
.db 0x00, 0x62, 0x64, 0x08, 0x13, 0x23 ; % 5
|
||||
.db 0x00, 0x36, 0x49, 0x55, 0x22, 0x50 ; & 6
|
||||
.db 0x00, 0x00, 0x05, 0x03, 0x00, 0x00 ; ' 7
|
||||
.db 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00 ; ( 8
|
||||
.db 0x00, 0x00, 0x41, 0x22, 0x1c, 0x00 ; ) 9
|
||||
.db 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14 ; * 10
|
||||
.db 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08 ; + 11
|
||||
.db 0x00, 0x00, 0x00, 0xA0, 0x60, 0x00 ; , 12
|
||||
.db 0x00, 0x08, 0x08, 0x08, 0x08, 0x08 ; - 13
|
||||
.db 0x00, 0x00, 0x60, 0x60, 0x00, 0x00 ; . 14
|
||||
.db 0x00, 0x20, 0x10, 0x08, 0x04, 0x02 ; / 15
|
||||
.db 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E ; 0 16
|
||||
.db 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00 ; 1 17
|
||||
.db 0x00, 0x42, 0x61, 0x51, 0x49, 0x46 ; 2 18
|
||||
.db 0x00, 0x21, 0x41, 0x45, 0x4B, 0x31 ; 3 19
|
||||
.db 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10 ; 4 20
|
||||
.db 0x00, 0x27, 0x45, 0x45, 0x45, 0x39 ; 5 21
|
||||
.db 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30 ; 6 22
|
||||
.db 0x00, 0x01, 0x71, 0x09, 0x05, 0x03 ; 7 23
|
||||
.db 0x00, 0x36, 0x49, 0x49, 0x49, 0x36 ; 8 24
|
||||
.db 0x00, 0x06, 0x49, 0x49, 0x29, 0x1E ; 9 25
|
||||
.db 0x00, 0x00, 0x36, 0x36, 0x00, 0x00 ; : 26
|
||||
.db 0x00, 0x00, 0x56, 0x36, 0x00, 0x00 ; ; 27
|
||||
.db 0x00, 0x08, 0x14, 0x22, 0x41, 0x00 ; < 28
|
||||
.db 0x00, 0x14, 0x14, 0x14, 0x14, 0x14 ; = 29
|
||||
.db 0x00, 0x00, 0x41, 0x22, 0x14, 0x08 ; > 30
|
||||
.db 0x00, 0x02, 0x01, 0x51, 0x09, 0x06 ; ? 31
|
||||
.db 0x00, 0x32, 0x49, 0x59, 0x51, 0x3E ; @ 32
|
||||
.db 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C ; A 33
|
||||
.db 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36 ; B 34
|
||||
.db 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22 ; C 35
|
||||
.db 0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C ; D 36
|
||||
.db 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41 ; E 37
|
||||
.db 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01 ; F 38
|
||||
.db 0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A ; G 39
|
||||
.db 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F ; H 40
|
||||
.db 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00 ; I 41
|
||||
.db 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01 ; J 42
|
||||
.db 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41 ; K 43
|
||||
.db 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40 ; L 44
|
||||
.db 0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F ; M 45
|
||||
.db 0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F ; N 46
|
||||
.db 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E ; O 47
|
||||
.db 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06 ; P 48
|
||||
.db 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E ; Q 49
|
||||
.db 0x00, 0x7F, 0x09, 0x19, 0x29, 0x46 ; R 50
|
||||
.db 0x00, 0x46, 0x49, 0x49, 0x49, 0x31 ; S 51
|
||||
.db 0x00, 0x01, 0x01, 0x7F, 0x01, 0x01 ; T 52
|
||||
.db 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F ; U 53
|
||||
.db 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F ; V 54
|
||||
.db 0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F ; W 55
|
||||
.db 0x00, 0x63, 0x14, 0x08, 0x14, 0x63 ; X 56
|
||||
.db 0x00, 0x07, 0x08, 0x70, 0x08, 0x07 ; Y 57
|
||||
.db 0x00, 0x61, 0x51, 0x49, 0x45, 0x43 ; Z 58
|
||||
.db 0x00, 0x00, 0x7F, 0x41, 0x41, 0x00 ; [ 59
|
||||
.db 0x00, 0x02, 0x04, 0x08, 0x10, 0x20 ; \ 60
|
||||
.db 0x00, 0x00, 0x41, 0x41, 0x7F, 0x00 ; ] 61
|
||||
.db 0x00, 0x04, 0x02, 0x01, 0x02, 0x04 ; ^ 62
|
||||
.db 0x00, 0x40, 0x40, 0x40, 0x40, 0x40 ; _ 63
|
||||
.db 0x00, 0x00, 0x01, 0x02, 0x04, 0x00 ; ' 64
|
||||
.db 0x00, 0x20, 0x54, 0x54, 0x54, 0x78 ; a 65
|
||||
.db 0x00, 0x7F, 0x48, 0x44, 0x44, 0x38 ; b 66
|
||||
.db 0x00, 0x38, 0x44, 0x44, 0x44, 0x20 ; c 67
|
||||
.db 0x00, 0x38, 0x44, 0x44, 0x48, 0x7F ; d 68
|
||||
.db 0x00, 0x38, 0x54, 0x54, 0x54, 0x18 ; e 69
|
||||
.db 0x00, 0x08, 0x7E, 0x09, 0x01, 0x02 ; f 70
|
||||
.db 0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C ; g 71
|
||||
.db 0x00, 0x7F, 0x08, 0x04, 0x04, 0x78 ; h 72
|
||||
.db 0x00, 0x00, 0x44, 0x7D, 0x40, 0x00 ; i 73
|
||||
.db 0x00, 0x40, 0x80, 0x84, 0x7D, 0x00 ; j 74
|
||||
.db 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00 ; k 75
|
||||
.db 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00 ; l 76
|
||||
.db 0x00, 0x7C, 0x04, 0x18, 0x04, 0x78 ; m 77
|
||||
.db 0x00, 0x7C, 0x08, 0x04, 0x04, 0x78 ; n 78
|
||||
.db 0x00, 0x38, 0x44, 0x44, 0x44, 0x38 ; o 79
|
||||
.db 0x00, 0xFC, 0x24, 0x24, 0x24, 0x18 ; p 80
|
||||
.db 0x00, 0x18, 0x24, 0x24, 0x18, 0xFC ; q 81
|
||||
.db 0x00, 0x7C, 0x08, 0x04, 0x04, 0x08 ; r 82
|
||||
.db 0x00, 0x48, 0x54, 0x54, 0x54, 0x20 ; s 83
|
||||
.db 0x00, 0x04, 0x3F, 0x44, 0x40, 0x20 ; t 84
|
||||
.db 0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C ; u 85
|
||||
.db 0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C ; v 86
|
||||
.db 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C ; w 87
|
||||
.db 0x00, 0x44, 0x28, 0x10, 0x28, 0x44 ; x 88
|
||||
.db 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C ; y 89
|
||||
.db 0x00, 0x44, 0x64, 0x54, 0x4C, 0x44 ; z 90
|
||||
.db 0x00, 0x08, 0x36, 0x41, 0x41, 0x00 ; { 91
|
||||
.db 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00 ; | 92
|
||||
.db 0x00, 0x00, 0x41, 0x41, 0x36, 0x08 ; } 93
|
||||
.db 0x00, 0x08, 0x04, 0x08, 0x10, 0x08 ; ~ 94
|
||||
#endif
|
||||
|
||||
|
||||
LCD_END:
|
||||
.equ MODULE_SIZE_LCD = LCD_END-LCD_BEGIN
|
||||
|
||||
324
avr/modules/led/led.asm
Normal file
324
avr/modules/led/led.asm
Normal file
@@ -0,0 +1,324 @@
|
||||
; ***************************************************************************
|
||||
; 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. *
|
||||
; ***************************************************************************
|
||||
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; defs
|
||||
|
||||
.equ LED_DATA_OFFS_ADDRDDR = 0
|
||||
.equ LED_DATA_OFFS_ADDRPORT = 1
|
||||
.equ LED_DATA_OFFS_ADDRPIN = 2
|
||||
.equ LED_DATA_OFFS_PINMASK = 3
|
||||
|
||||
|
||||
.equ LED_SRAM_OFFS_PATTERNADDR = 0
|
||||
.equ LED_SRAM_OFFS_COUNTER = 2
|
||||
.equ LED_SRAM_OFFS_POS = 3
|
||||
.equ LED_SRAM_SIZE = 4
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; code
|
||||
|
||||
.cseg
|
||||
|
||||
|
||||
LED_BEGIN:
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Led_Init
|
||||
;
|
||||
; IN:
|
||||
; - Y: pointer to SRAM data
|
||||
; - Z: pointer to FLASH data
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, clear on error
|
||||
; USED: R1, R2, R3, R4, R16, R17, X
|
||||
|
||||
Led_Init:
|
||||
mov xh, yh
|
||||
mov xl, yl
|
||||
clr r16
|
||||
ldi r17, LED_SRAM_SIZE
|
||||
rcall Utils_FillSram
|
||||
|
||||
rcall ledGetFlashDataIntoRegs
|
||||
brcc Led_Init_end
|
||||
|
||||
; set bit in DDR register (-> output)
|
||||
mov xl, r1 ; DDR register address
|
||||
clr xh
|
||||
ld r16, x
|
||||
or r16, r4 ; output
|
||||
st x, r16
|
||||
|
||||
; turn off led
|
||||
rcall ledOff
|
||||
sec
|
||||
Led_Init_end:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Led_SetPattern
|
||||
;
|
||||
; IN:
|
||||
; - X: pointer to led pattern in flash
|
||||
; - Y: pointer to SRAM data
|
||||
; - Z: pointer to FLASH data
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, clear on error
|
||||
; USED: R1, R2, R3, R4, R16, R17, Z
|
||||
|
||||
Led_SetPattern:
|
||||
rcall ledGetFlashDataIntoRegs
|
||||
brcc Led_SetPattern_l2
|
||||
|
||||
std y+LED_SRAM_OFFS_PATTERNADDR, xl ; param 1
|
||||
std y+LED_SRAM_OFFS_PATTERNADDR+1, xh ; param 2
|
||||
|
||||
; reset pos in pattern
|
||||
clr r19
|
||||
std y+LED_SRAM_OFFS_POS, r19
|
||||
|
||||
; store counter for current pattern element
|
||||
mov zl, xl
|
||||
mov zh, xh
|
||||
lsl zl ; multiplay Z by 2
|
||||
rol zh
|
||||
lpm r19, z ; read current pattern counter
|
||||
std y+LED_SRAM_OFFS_COUNTER, r19
|
||||
|
||||
; each pattern starts with LED on
|
||||
rcall ledOn
|
||||
|
||||
Led_SetPattern_l2:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Led_Tick
|
||||
;
|
||||
; IN:
|
||||
; - Y: pointer to SRAM data
|
||||
; - Z: pointer to FLASH data
|
||||
; OUT:
|
||||
; - CFLAG: set if something done, reset otherwise
|
||||
; USED:
|
||||
|
||||
Led_Tick:
|
||||
rcall ledGetFlashDataIntoRegs
|
||||
brcs Led_Tick_l1
|
||||
ret
|
||||
|
||||
Led_Tick_l1:
|
||||
ldd zl, y+LED_SRAM_OFFS_PATTERNADDR
|
||||
ldd zh, y+LED_SRAM_OFFS_PATTERNADDR+1
|
||||
ldd r18, y+LED_SRAM_OFFS_POS
|
||||
ldd r19, y+LED_SRAM_OFFS_COUNTER
|
||||
|
||||
; test NULL ptr
|
||||
mov r16, zl;
|
||||
or r16, zh
|
||||
breq Led_Tick_end ; no current pattern, end
|
||||
|
||||
cpi r19, 2 ; current counter less than 2?
|
||||
brcs Led_Tick_nextPhase
|
||||
|
||||
dec r19
|
||||
std y+LED_SRAM_OFFS_COUNTER, r19
|
||||
ret
|
||||
|
||||
Led_Tick_nextPhase:
|
||||
lsl zl ; multiplay Z by 2
|
||||
rol zh
|
||||
inc r18 ; next pos
|
||||
rcall Led_Tick_getPattern
|
||||
cpi r16, 0xff
|
||||
breq Led_Tick_restart
|
||||
cpi r16, 0
|
||||
breq Led_Tick_stop
|
||||
|
||||
std y+LED_SRAM_OFFS_POS, r18
|
||||
std y+LED_SRAM_OFFS_COUNTER, r16
|
||||
|
||||
mov r17, r18
|
||||
andi r17, 1 ; even?
|
||||
breq Led_Tick_switchOn
|
||||
rjmp ledOff
|
||||
|
||||
Led_Tick_switchOn:
|
||||
; turn on led
|
||||
rjmp ledOn
|
||||
|
||||
|
||||
Led_Tick_stop:
|
||||
clr r16
|
||||
std y+LED_SRAM_OFFS_PATTERNADDR, r16
|
||||
std y+LED_SRAM_OFFS_PATTERNADDR+1, r16
|
||||
std y+LED_SRAM_OFFS_COUNTER, r16
|
||||
std y+LED_SRAM_OFFS_POS, r16
|
||||
|
||||
; LED off
|
||||
rcall ledOff
|
||||
|
||||
|
||||
Led_Tick_restart:
|
||||
ldi r18, 0
|
||||
rcall Led_Tick_getPattern
|
||||
cpi r16, 0xff
|
||||
breq Led_Tick_stop ; stop, because restart as first pattern is invalid
|
||||
cpi r16, 0
|
||||
breq Led_Tick_stop
|
||||
std y+LED_SRAM_OFFS_POS, r18 ; incremented pos in pattern
|
||||
std y+LED_SRAM_OFFS_COUNTER, r16 ; new counter value
|
||||
|
||||
rcall ledOn
|
||||
ret
|
||||
|
||||
|
||||
Led_Tick_getPattern: ; r18=pos
|
||||
ldd zl, y+LED_SRAM_OFFS_PATTERNADDR
|
||||
ldd zh, y+LED_SRAM_OFFS_PATTERNADDR+1
|
||||
lsl zl ; multiplay Z by 2
|
||||
rol zh
|
||||
|
||||
ldi r16, 0
|
||||
add zl, r18
|
||||
adc zh, r16
|
||||
lpm r16, z
|
||||
ret
|
||||
|
||||
Led_Tick_end:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; ledGetFlashDataIntoRegs
|
||||
;
|
||||
; IN:
|
||||
; - R28/ZL: pointer to data in flash (low)
|
||||
; - R29/ZH: pointer to data in flash (hi)
|
||||
; OUT:
|
||||
; - CARRY flag set if okay, clear on error
|
||||
; - R1: memory address of DDR register
|
||||
; - R2: memory address of PORT register
|
||||
; - R3: memory address of PIN register
|
||||
; - R4: mask for used pin
|
||||
; USED: R16
|
||||
|
||||
ledGetFlashDataIntoRegs:
|
||||
push zh
|
||||
push zl
|
||||
mov r16, zl
|
||||
or r16, zh
|
||||
breq ledGetFlashDataIntoRegs_error
|
||||
lsl zl
|
||||
rol zh
|
||||
lpm r1, z+ ; DDR
|
||||
lpm r2, z+ ; PORTR
|
||||
lpm r3, z+ ; PINR
|
||||
lpm r4, z ; pin mask
|
||||
pop zl
|
||||
pop zh
|
||||
sec
|
||||
ret
|
||||
|
||||
ledGetFlashDataIntoRegs_error:
|
||||
pop zl
|
||||
pop zh
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; ledOff
|
||||
;
|
||||
; IN:
|
||||
; - R2: port register address (low part only)
|
||||
; - R4: bit mask for pin to use
|
||||
; OUT:
|
||||
; - nothing
|
||||
; MODIFIED REGS: none
|
||||
; CYCLES: 26 (if R2 and R4 valid)
|
||||
|
||||
ledOff:
|
||||
tst r2 ; 1
|
||||
breq ledOff_end ; 1 if not taken
|
||||
tst r4 ; 1
|
||||
breq ledOff_end ; 1 if not taken
|
||||
push xh ; 2
|
||||
push xl ; 2
|
||||
push r16 ; 2
|
||||
mov xl, r2 ; 1 PORT register address
|
||||
clr xh ; 1
|
||||
ld r16, x ; 1
|
||||
or r16, r4 ; 1
|
||||
st x, r16 ; 2
|
||||
pop r16 ; 2
|
||||
pop xl ; 2
|
||||
pop xh ; 2
|
||||
ledOff_end:
|
||||
ret ; 4
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; ledOn
|
||||
;
|
||||
; IN:
|
||||
; - R2: port register address (low part only)
|
||||
; - R4: bit mask for pin to use
|
||||
; OUT:
|
||||
; - nothing
|
||||
; MODIFIED REGS: none
|
||||
; CYCLES: 28
|
||||
|
||||
ledOn: ; clock cycles
|
||||
tst r2 ; 1
|
||||
breq ledOn_end ; 1 if not taken
|
||||
tst r4 ; 1
|
||||
breq ledOn_end ; 1 if not taken
|
||||
|
||||
push xh ; 2
|
||||
push xl ; 2
|
||||
push r16 ; 2
|
||||
mov xl, r2 ; 1 PORT register address
|
||||
clr xh ; 1
|
||||
ld r16, x ; 1
|
||||
com r4 ; 1 invert bit mask for following AND
|
||||
and r16, r4 ; 1
|
||||
com r4 ; 1 undo inversion
|
||||
st x, r16 ; 2
|
||||
pop r16 ; 2
|
||||
pop xl ; 2
|
||||
pop xh ; 2
|
||||
ledOn_end:
|
||||
ret ; 4
|
||||
|
||||
|
||||
|
||||
LED_END:
|
||||
.equ MODULE_SIZE_LED = LED_END-LED_BEGIN
|
||||
|
||||
|
||||
|
||||
495
avr/modules/si7021/si7021.asm
Normal file
495
avr/modules/si7021/si7021.asm
Normal file
@@ -0,0 +1,495 @@
|
||||
; ***************************************************************************
|
||||
; 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 SI7021_FLAGS_PRESENT = 0x80
|
||||
.equ SI7021_FLAGS_TEMP_VALID = 0x40
|
||||
.equ SI7021_FLAGS_HUM_VALID = 0x20
|
||||
.equ SI7021_FLAGS_LASTWASTEMP = 0x10
|
||||
.equ SI7021_FLAGS_ERROR_MASK = 0x07
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; data
|
||||
|
||||
.dseg
|
||||
|
||||
si7021DataBegin:
|
||||
si7021Flags: .byte 1
|
||||
si7021FirmwareRevision: .byte 1
|
||||
si7021LastTemp: .byte 2
|
||||
si7021LastHumidity: .byte 2
|
||||
si7021DataEnd:
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; code
|
||||
|
||||
.cseg
|
||||
|
||||
|
||||
SI7021_BEGIN:
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; SI7021_Init
|
||||
;
|
||||
; IN:
|
||||
; - nothing
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, clear on error
|
||||
; USED:
|
||||
|
||||
SI7021_Init:
|
||||
ldi xh, HIGH(si7021DataBegin)
|
||||
ldi xl, LOW(si7021DataBegin)
|
||||
clr r16
|
||||
ldi r17, (si7021DataEnd-si7021DataBegin)
|
||||
rcall Utils_FillSram
|
||||
; check presence
|
||||
rcall si7021CheckPresence
|
||||
brcc SI7021_Init_error
|
||||
lds r16, si7021Flags
|
||||
ori r16, SI7021_FLAGS_PRESENT
|
||||
sts si7021Flags, r16
|
||||
; get firmware revision
|
||||
; rcall si7021ReadFirmwareRevision
|
||||
; brcc SI7021_Init_error
|
||||
; sts si7021FirmwareRevision, r16
|
||||
sec
|
||||
ret
|
||||
SI7021_Init_error:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; SI7021_Fini
|
||||
;
|
||||
; IN:
|
||||
; - nothing
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, clear on error
|
||||
; USED:
|
||||
|
||||
SI7021_Fini:
|
||||
sec
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; SI7021_PeriodicMeasurement
|
||||
;
|
||||
; Call this routine periodically to take measurements.
|
||||
; IN:
|
||||
; - nothing
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, clear on error
|
||||
; USED:
|
||||
|
||||
SI7021_PeriodicMeasurement:
|
||||
in r15, SREG
|
||||
push r15
|
||||
cli
|
||||
lds r17, si7021Flags
|
||||
mov r16, r17
|
||||
andi r16, SI7021_FLAGS_LASTWASTEMP
|
||||
brne si7021PeriodicMeasurement_hum
|
||||
ori r17, SI7021_FLAGS_LASTWASTEMP
|
||||
sts si7021Flags, r17
|
||||
push r17
|
||||
rcall si7021MeasureTemp
|
||||
pop r17
|
||||
brcc si7021PeriodicMeasurement_error
|
||||
ori r17, SI7021_FLAGS_TEMP_VALID
|
||||
sts si7021Flags, r17
|
||||
rcall si7021CalcTemp ; calculate temp*100 from sensor value
|
||||
sts si7021LastTemp, r18
|
||||
sts si7021LastTemp+1, r19
|
||||
rjmp si7021PeriodicMeasurement_done
|
||||
si7021PeriodicMeasurement_hum:
|
||||
andi r17, ~SI7021_FLAGS_LASTWASTEMP
|
||||
sts si7021Flags, r17
|
||||
push r17
|
||||
rcall si7021MeasureHumidity
|
||||
pop r17
|
||||
brcc si7021PeriodicMeasurement_error
|
||||
ori r17, SI7021_FLAGS_HUM_VALID
|
||||
sts si7021Flags, r17
|
||||
rcall si7021CalcHumidity
|
||||
sts si7021LastHumidity, r18
|
||||
sts si7021LastHumidity+1, r19
|
||||
si7021PeriodicMeasurement_done:
|
||||
pop r15
|
||||
out SREG, r15
|
||||
sec
|
||||
ret
|
||||
si7021PeriodicMeasurement_error:
|
||||
pop r15
|
||||
out SREG, r15
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; si7021CheckPresence
|
||||
;
|
||||
; Expects interrupts being disabled!
|
||||
;
|
||||
; IN:
|
||||
; - nothing
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, clear on error
|
||||
; USED:
|
||||
|
||||
si7021CheckPresence:
|
||||
rcall twiStart
|
||||
ldi r16, (SI7021_ADDR*2)+1
|
||||
rcall twiSendByte
|
||||
brcc si7021CheckPresence_notfound
|
||||
rcall twiStop
|
||||
sec
|
||||
ret
|
||||
|
||||
si7021CheckPresence_notfound:
|
||||
rcall twiStop
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
; ---------------------------------------------------------------------------
|
||||
; si7021ReadFirmwareRevision
|
||||
;
|
||||
; Expects interrupts being disabled!
|
||||
; Currently doesn't work (my SI7021 doesn't accept the command).
|
||||
;
|
||||
; IN:
|
||||
; - nothing
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, clear on error
|
||||
; - R16: firmware revision (0xff: version 1.0, 0x20: version 2.0)
|
||||
; USED:
|
||||
|
||||
si7021ReadFirmwareRevision:
|
||||
rcall twiStart
|
||||
ldi r16, (SI7021_ADDR*2) ; write access
|
||||
rcall twiSendByteExpectAck
|
||||
brcc si7021ReadFirmwareRevision_error1
|
||||
ldi r16, 0x84
|
||||
rcall twiSendByteExpectAck
|
||||
brcc si7021ReadFirmwareRevision_error2
|
||||
ldi r16, 0xb8
|
||||
rcall twiSendByteExpectAck
|
||||
brcc si7021ReadFirmwareRevision_error3
|
||||
rcall twiRestart
|
||||
ldi r16, (SI7021_ADDR*2)+1 ; read access
|
||||
rcall twiSendByteExpectAck
|
||||
brcc si7021ReadFirmwareRevision_error4
|
||||
rcall twiReceiveByte ; don't send ACK
|
||||
brcc si7021ReadFirmwareRevision_error5
|
||||
rcall twiStop
|
||||
sec
|
||||
ret
|
||||
|
||||
si7021ReadFirmwareRevision_error1:
|
||||
ldi r16, 1
|
||||
rcall si7021SetError
|
||||
rjmp si7021ReadFirmwareRevision_error
|
||||
si7021ReadFirmwareRevision_error2:
|
||||
ldi r16, 2
|
||||
rcall si7021SetError
|
||||
rjmp si7021ReadFirmwareRevision_error
|
||||
si7021ReadFirmwareRevision_error3:
|
||||
ldi r16, 3
|
||||
rcall si7021SetError
|
||||
rjmp si7021ReadFirmwareRevision_error
|
||||
si7021ReadFirmwareRevision_error4:
|
||||
ldi r16, 4
|
||||
rcall si7021SetError
|
||||
rjmp si7021ReadFirmwareRevision_error
|
||||
si7021ReadFirmwareRevision_error5:
|
||||
ldi r16, 5
|
||||
rcall si7021SetError
|
||||
rjmp si7021ReadFirmwareRevision_error
|
||||
|
||||
si7021ReadFirmwareRevision_error:
|
||||
rcall twiStop
|
||||
clc
|
||||
ret
|
||||
#endif
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; si7021MeasureTemp
|
||||
;
|
||||
; IN:
|
||||
; - nothing
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, clear on error
|
||||
; USED:
|
||||
|
||||
si7021MeasureTemp:
|
||||
ldi r16, 0xf3
|
||||
rjmp si7021MeasureAny
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; si7021MeasureHumidity
|
||||
;
|
||||
; IN:
|
||||
; - nothing
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, clear on error
|
||||
; USED:
|
||||
|
||||
si7021MeasureHumidity:
|
||||
ldi r16, 0xf5
|
||||
rjmp si7021MeasureAny
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; si7021MeasureAny
|
||||
;
|
||||
; Sends the given command to the sensor and reads the result.
|
||||
; Synchronization is done by sending re-start sequences until the sensor answers with
|
||||
; the value.
|
||||
; IN:
|
||||
; - R16: command to send
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, clear on error
|
||||
; USED: R14, R16, R18, R19
|
||||
|
||||
si7021MeasureAny:
|
||||
rcall twiStart ; (R22)
|
||||
push r16
|
||||
ldi r16, (SI7021_ADDR*2) ; write access
|
||||
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
|
||||
pop r16
|
||||
brcc si7021MeasureAny_error
|
||||
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
|
||||
|
||||
ldi r16, 200
|
||||
mov r14, r16
|
||||
si7021MeasureAny_loop: ; (R22)
|
||||
rcall twiRestart
|
||||
ldi r16, (SI7021_ADDR*2)+1 ; read access
|
||||
rcall twiSendByteExpectAck ; (R16, R17, R18, R22)
|
||||
brcs si7021MeasureAny_gotValue ; chip responds, receive values
|
||||
dec r14
|
||||
breq si7021MeasureAny_error ; timeout
|
||||
Utils_WaitNanoSecs 100000, 0, r22
|
||||
rjmp si7021MeasureAny_loop
|
||||
|
||||
si7021MeasureAny_gotValue:
|
||||
rcall twiReceiveByteSendAck ; (R16, R17, R18, R22)
|
||||
brcc si7021MeasureAny_error
|
||||
mov r19, r16 ; MSByte
|
||||
rcall twiReceiveByte ; no ACK (R16, R17, R18, R22)
|
||||
brcc si7021MeasureAny_error
|
||||
mov r18, r16
|
||||
rcall twiStop ; (R22)
|
||||
ldi r16, 0
|
||||
rcall si7021SetError ; (none)
|
||||
sec
|
||||
ret
|
||||
si7021MeasureAny_error:
|
||||
rcall twiStop ; (R22)
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; si7021SetError
|
||||
;
|
||||
; Set error code in flags.
|
||||
; IN:
|
||||
; - R16: error code to set (0-7)
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, clear on error
|
||||
; USED: none
|
||||
|
||||
|
||||
si7021SetError:
|
||||
push r17
|
||||
lds r17, si7021Flags
|
||||
andi r17, ~SI7021_FLAGS_ERROR_MASK
|
||||
or r17, r16
|
||||
sts si7021Flags, r17
|
||||
pop r17
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; si7021CalcTemp
|
||||
;
|
||||
; Calculates temperatur * 100.
|
||||
; Uses formula from specs: temp=(175.72*TEMP_CODE/65536)-46.85.
|
||||
;
|
||||
; IN:
|
||||
; - R19:R18: Temperature value read from sensor
|
||||
; OUT:
|
||||
; - R19:R18: calculated temperature(Celsius) * 100
|
||||
; USED: R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R26
|
||||
|
||||
si7021CalcTemp:
|
||||
mov r20, r18
|
||||
mov r21, r19
|
||||
ldi r23, HIGH(17572)
|
||||
ldi r22, LOW(17572)
|
||||
rcall si7021Mulu16x16_32 ; result is in R19:R18:R17:R16, we only use R19-R18 -> /65536
|
||||
ldi r16, LOW(4685)
|
||||
ldi r17, HIGH(4685)
|
||||
sub r18, r16
|
||||
sbc r19, r17
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; si7021CalcHumidity
|
||||
;
|
||||
; Calculates humidity in percent.
|
||||
; Uses formula from specs: rel humidity=(125*HUMIDITY_CODE/65536)-6.
|
||||
;
|
||||
; IN:
|
||||
; - R19:R18: Humidity value read from sensor
|
||||
; OUT:
|
||||
; - R19:R18: calculated relative humidity
|
||||
; USED: R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R26
|
||||
|
||||
si7021CalcHumidity:
|
||||
mov r20, r18
|
||||
mov r21, r19
|
||||
clr r23
|
||||
ldi r22, 125
|
||||
rcall si7021Mulu16x16_32 ; result is in R19:R18:R17:R16, we only use R19-R18 -> /65536
|
||||
ldi r16, 6
|
||||
clr r17
|
||||
sub r18, r16
|
||||
sbc r19, r17
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; si7021Mulu16x16_32
|
||||
;
|
||||
; Multiplies two unsigned 16 bit values resulting in one 32 bit value.
|
||||
; This is a rather simple but reasonable fast routine working just like you would
|
||||
; when doing multiplications with pen and paper.
|
||||
; TODO: adapt for signed values
|
||||
;
|
||||
; IN:
|
||||
; - R21:R20: 16 bit value A
|
||||
; - R23:R22: 16 bit value B
|
||||
; OUT:
|
||||
; - R19:R18:R17:R16: 32 bit result
|
||||
; USED: R16, R17, R18, R19, R20, R21, R22, R23, R24, R25, R26
|
||||
; R19:R18:R17:R16 = R21:R20 * R23:R22
|
||||
; R19:R18:R17:R16 = R25:R24:R21:R20 * R23:R22
|
||||
si7021Mulu16x16_32:
|
||||
clr r19
|
||||
clr r18
|
||||
clr r17
|
||||
clr r16
|
||||
clr r25
|
||||
clr r24
|
||||
ldi r26, 16 ; 16 bit multiplicator
|
||||
si7021Muls16x16_32_loop:
|
||||
lsr r23
|
||||
ror r22
|
||||
brcc si7021Muls16x16_32_noadd ; current digit in B is 0, don't add shifted A to result
|
||||
add r16, r22
|
||||
adc r17, r23
|
||||
adc r18, r24
|
||||
adc r19, r25
|
||||
; brcs si7021Muls16x16_32_overflow ; can't happen
|
||||
si7021Muls16x16_32_noadd:
|
||||
dec r26
|
||||
breq si7021Muls16x16_32_done
|
||||
lsl r20
|
||||
rol r21
|
||||
rol r24
|
||||
rol r25
|
||||
; brcs si7021Muls16x16_32_overflow ; can't happen
|
||||
rjmp si7021Muls16x16_32_loop
|
||||
si7021Muls16x16_32_done:
|
||||
clc
|
||||
ret
|
||||
;si7021Muls16x16_32_overflow: ; never reached. Multiplying 2 16 bit values can't overflow 32 bit
|
||||
; sec
|
||||
; ret
|
||||
|
||||
|
||||
|
||||
|
||||
SI7021_SendTemp:
|
||||
lds r16, si7021Flags
|
||||
andi r16, SI7021_FLAGS_TEMP_VALID
|
||||
brne SI7021_SendTemp_haveValue
|
||||
sec
|
||||
ret
|
||||
SI7021_SendTemp_haveValue:
|
||||
ldi r16, 0xff ; destination address
|
||||
ldi r17, VALUE_ID_TEMP1 ; value id
|
||||
ldi r22, AQHOME_VALUETYPE_TEMP
|
||||
lds r18, si7021LastTemp ; value
|
||||
lds r19, si7021LastTemp+1
|
||||
ldi r20, 100 ; denominator
|
||||
clr r21
|
||||
rjmp SI7021_SendValue
|
||||
|
||||
|
||||
|
||||
SI7021_SendHumidity:
|
||||
lds r16, si7021Flags
|
||||
andi r16, SI7021_FLAGS_HUM_VALID
|
||||
brne SI7021_SendHumidity_haveValue
|
||||
clc
|
||||
ret
|
||||
SI7021_SendHumidity_haveValue:
|
||||
ldi r16, 0xff ; destination address
|
||||
ldi r17, VALUE_ID_HUM1 ; value id
|
||||
ldi r22, AQHOME_VALUETYPE_HUMIDITY
|
||||
lds r18, si7021LastHumidity ; value
|
||||
lds r19, si7021LastHumidity+1
|
||||
ldi r20, 1 ; denominator
|
||||
clr r21
|
||||
rjmp SI7021_SendValue
|
||||
|
||||
|
||||
SI7021_SendValue:
|
||||
ldi xl, LOW(com2SendBuffer)
|
||||
ldi xh, HIGH(com2SendBuffer)
|
||||
rcall CPRO_WriteValue
|
||||
rjmp COM2_SendPacket
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
SI7021_END:
|
||||
.equ MODULE_SIZE_SI7021 = SI7021_END-SI7021_BEGIN
|
||||
|
||||
|
||||
109
avr/modules/stats/stats.asm
Normal file
109
avr/modules/stats/stats.asm
Normal file
@@ -0,0 +1,109 @@
|
||||
; ***************************************************************************
|
||||
; 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 STATS_POS_MAX = 4
|
||||
.equ STATS_POS_SEND = 4
|
||||
.equ STATS_POS_RECV = 3
|
||||
.equ STATS_POS_SYS = 2
|
||||
.equ STATS_POS_MEM = 1
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; data
|
||||
|
||||
.dseg
|
||||
|
||||
|
||||
statsDataBegin:
|
||||
statsRemaining: .byte 1
|
||||
statsDataEnd:
|
||||
|
||||
statsSendTimer: .byte 2 ; intentionally outside zeroed out are
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; code
|
||||
|
||||
.cseg
|
||||
|
||||
|
||||
|
||||
Stats_Init:
|
||||
; preset SRAM data area
|
||||
ldi xh, HIGH(statsDataBegin)
|
||||
ldi xl, LOW(statsDataBegin)
|
||||
clr r16
|
||||
ldi r17, (statsDataEnd-statsDataBegin)
|
||||
rcall Utils_FillSram
|
||||
sec
|
||||
ret
|
||||
|
||||
|
||||
|
||||
Stats_Run:
|
||||
in r15, SREG
|
||||
push r15
|
||||
cli
|
||||
ldi xl, LOW(com2SendBuffer)
|
||||
ldi xh, HIGH(com2SendBuffer)
|
||||
ldi r16, 0xff
|
||||
|
||||
lds r17, statsRemaining
|
||||
tst r17
|
||||
breq Stats_Run_done
|
||||
|
||||
cpi r17, STATS_POS_RECV
|
||||
brne Stats_Run_l1
|
||||
rcall CPRO_WriteComRecvStats
|
||||
rjmp Stats_Run_SendPacket
|
||||
Stats_Run_l1:
|
||||
cpi r17, STATS_POS_SYS
|
||||
brne Stats_Run_l2
|
||||
rcall CPRO_WriteSysStats
|
||||
rjmp Stats_Run_SendPacket
|
||||
Stats_Run_l2:
|
||||
cpi r17, STATS_POS_MEM
|
||||
brne Stats_Run_l3
|
||||
rcall CPRO_WriteMemStats
|
||||
rjmp Stats_Run_SendPacket
|
||||
Stats_Run_l3:
|
||||
cpi r17, STATS_POS_SEND
|
||||
brne Stats_Run_l4
|
||||
rcall CPRO_WriteComSendStats
|
||||
rjmp Stats_Run_SendPacket
|
||||
Stats_Run_l4:
|
||||
; add more stats here
|
||||
rjmp Stats_Run_done
|
||||
Stats_Run_SendPacket:
|
||||
rcall COM2_SendPacket
|
||||
brcc Stats_Run_done ; only decrement counter if message successfully sent
|
||||
lds r16, statsRemaining
|
||||
dec r16
|
||||
sts statsRemaining, r16
|
||||
Stats_Run_done:
|
||||
pop r15
|
||||
out SREG, r15
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
Stats_Timer:
|
||||
ldi r16, STATS_POS_MAX ; RECV, SYS
|
||||
sts statsRemaining, r16
|
||||
ret
|
||||
|
||||
|
||||
|
||||
332
avr/modules/timer/timer.asm
Normal file
332
avr/modules/timer/timer.asm
Normal file
@@ -0,0 +1,332 @@
|
||||
; ***************************************************************************
|
||||
; 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. *
|
||||
; ***************************************************************************
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; defs
|
||||
|
||||
.equ TIMER_FLAGS_IF_ADDR = 1
|
||||
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; data
|
||||
|
||||
.dseg
|
||||
|
||||
timerModuleData:
|
||||
timerModuleTickCounter: .byte 1
|
||||
timerTicksSinceLastRun: .byte 2
|
||||
timerModuleCounterSecs: .byte 4
|
||||
timerInterrupts: .byte 2
|
||||
timerModuleData_end:
|
||||
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; code
|
||||
|
||||
.cseg
|
||||
|
||||
TIMER_BEGIN:
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Timer_Init
|
||||
;
|
||||
; IN:
|
||||
; - nothing
|
||||
; OUT:
|
||||
; - nothing
|
||||
; USED: r16, r17, x
|
||||
|
||||
Timer_Init: ; setup timer for IRQ every 100ms
|
||||
; reset data in SDRAM
|
||||
ldi xh, HIGH(timerModuleData)
|
||||
ldi xl, LOW(timerModuleData)
|
||||
ldi r16, 0
|
||||
ldi r17, (timerModuleData_end-timerModuleData)
|
||||
rcall Utils_FillSram
|
||||
|
||||
; CTC mode (WGM2:0=2, OCR0A=value, OCF0A Flag =1, -> IRQ_OC0A
|
||||
|
||||
; CMP-A interrupt about every 100ms
|
||||
ldi r16, (1<<CS02) | (1<<CS00) ; Prescaler 1024
|
||||
out TCCR0B, r16
|
||||
|
||||
ldi r16, (1<<WGM01) ; CTC mode
|
||||
out TCCR0A, r16
|
||||
|
||||
ldi r16, 98-1 ; (1,000,000/1024)/10 = 97.65625
|
||||
out OCR0A, r16
|
||||
|
||||
ldi r16, (1<<OCF0A) ; clear pending interrupts
|
||||
out TIFR0, r16
|
||||
|
||||
ldi r16, (1<<OCIE0A)
|
||||
out TIMSK0, r16
|
||||
|
||||
rcall timerInitTimers
|
||||
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Timer_Fini
|
||||
;
|
||||
; IN:
|
||||
; - nothing
|
||||
; OUT:
|
||||
; - nothing
|
||||
; USED:
|
||||
|
||||
Timer_Fini:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Timer_Run
|
||||
;
|
||||
; IN:
|
||||
; - nothing
|
||||
; OUT:
|
||||
; - CFLAG: set if something done, cleared otherwise
|
||||
; USED: r15, r16, r24, r25 (more depending on called routines)
|
||||
|
||||
Timer_Run:
|
||||
in r15, SREG
|
||||
cli
|
||||
lds r24, timerTicksSinceLastRun
|
||||
lds r25, timerTicksSinceLastRun+1
|
||||
clr r16 ; replace with 0 for next IRQ
|
||||
sts timerTicksSinceLastRun, r16
|
||||
sts timerTicksSinceLastRun+1, r16
|
||||
out SREG, r15 ; restore global IRQ flag
|
||||
sbiw r25:r24, 0
|
||||
clc ; flag "nothing done"
|
||||
breq Timer_Run_End
|
||||
Timer_Run_loop: ; for every occurred 100ms irq
|
||||
push r24
|
||||
push r25
|
||||
rcall onEvery100ms
|
||||
pop r25
|
||||
pop r24
|
||||
lds r16, timerModuleTickCounter
|
||||
inc r16
|
||||
cpi r16, 10
|
||||
brcc Timer_Run_SecondElapsed
|
||||
sts timerModuleTickCounter, r16
|
||||
rjmp Timer_Run_loop_end
|
||||
Timer_Run_SecondElapsed:
|
||||
clr r16
|
||||
sts timerModuleTickCounter, r16
|
||||
push r24
|
||||
push r25
|
||||
rcall timerRunTimers
|
||||
pop r25
|
||||
pop r24
|
||||
Timer_Run_loop_end:
|
||||
sbiw r25:r24, 1
|
||||
brne Timer_Run_loop
|
||||
sec
|
||||
Timer_Run_End:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Set timer value.
|
||||
;
|
||||
; Setting a timer to 0 effectively stops the timer.
|
||||
;
|
||||
; IN:
|
||||
; - r16: new timer value (low)
|
||||
; - r17: new timer value (high)
|
||||
; - X : pointer to timer value in SRAM
|
||||
; OUT:
|
||||
; - nothing
|
||||
; REGS: X
|
||||
|
||||
Timer_SetValue:
|
||||
push r15
|
||||
in r15, SREG
|
||||
cli
|
||||
st X+, r16
|
||||
st X+, r17
|
||||
out SREG, r15
|
||||
pop r15
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; Set timer value to 1s.
|
||||
;
|
||||
; IN:
|
||||
; - X : pointer to timer value in SRAM
|
||||
; OUT:
|
||||
; - nothing
|
||||
; REGS: X
|
||||
|
||||
Timer_SetValueTo1s:
|
||||
push r16
|
||||
push r17
|
||||
ldi r16, 1
|
||||
clr r17
|
||||
rcall Timer_SetValue
|
||||
pop r17
|
||||
pop r16
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
timerInitTimers:
|
||||
ldi zl, LOW(timerList*2)
|
||||
ldi zh, HIGH(timerList*2)
|
||||
clr r16 ; run var for pos in time table
|
||||
clr r17 ; 0 for adc
|
||||
timerInitTimers_loop:
|
||||
rcall timerReadTableEntry
|
||||
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
|
||||
inc r16
|
||||
rjmp timerInitTimers_loop
|
||||
|
||||
timerInitTimers_end:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
timerRunTimers:
|
||||
ldi xl, LOW(timerModuleCounterSecs)
|
||||
ldi xh, HIGH(timerModuleCounterSecs)
|
||||
rcall Utils_IncrementCounter32
|
||||
ldi zl, LOW(timerList*2)
|
||||
ldi zh, HIGH(timerList*2)
|
||||
timerRunTimers_loop:
|
||||
rcall timerReadTableEntry
|
||||
mov r16, xl
|
||||
or r16, xh
|
||||
breq timerRunTimers_end
|
||||
mov r16, r22
|
||||
andi r16, TIMER_FLAGS_IF_ADDR
|
||||
breq timerRunTimers_l1 ; no need to check address
|
||||
lds r16, com2Address ; check address
|
||||
tst r16
|
||||
breq timerRunTimers_loop ; no address, ignore counter
|
||||
timerRunTimers_l1:
|
||||
ld r24, X+
|
||||
ld r25, X
|
||||
sbiw r25:r24, 1
|
||||
brcs timerRunTimers_loop ; overflow, so already was zero, ignore entry
|
||||
breq timerRunTimers_reachedZero ; reached zero
|
||||
st X, r25
|
||||
st -X, r24
|
||||
rjmp timerRunTimers_loop
|
||||
timerRunTimers_reachedZero:
|
||||
st X, r21 ; reset initial value
|
||||
st -X, r20
|
||||
push zl
|
||||
push zh
|
||||
rcall timerCallR19R18
|
||||
pop zh
|
||||
pop zl
|
||||
rjmp timerRunTimers_loop
|
||||
timerRunTimers_end:
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; read time table entry.
|
||||
;
|
||||
; IN:
|
||||
; - Z : pointer to time list entry (suitable for LPM)
|
||||
; OUT:
|
||||
; - r19:r18: handler routine
|
||||
; - X : SRAM address for counter
|
||||
; - r21:r20: initial value
|
||||
; - r22 : flags
|
||||
; - r23 : reserved
|
||||
timerReadTableEntry:
|
||||
lpm xl, Z+ ; SRAM address of counter
|
||||
lpm xh, Z+
|
||||
lpm r18, Z+ ; routine (low)
|
||||
lpm r19, Z+ ; routine (high)
|
||||
lpm r22, Z+ ; flags
|
||||
lpm r23, Z+ ; reserved
|
||||
lpm r20, Z+ ; initial value
|
||||
lpm r21, Z+
|
||||
ret
|
||||
|
||||
|
||||
|
||||
timerCallR19R18:
|
||||
push r18
|
||||
push r19
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; OC0A interrupt handler
|
||||
;
|
||||
; Called every 100 milliseconds, increments timerTicksSinceLastRun. The rest is done outside ISR
|
||||
; in Timer_Run.
|
||||
|
||||
timerIrqOC0A:
|
||||
push r15
|
||||
in r15, SREG
|
||||
|
||||
push r24
|
||||
push r25
|
||||
lds r24, timerTicksSinceLastRun
|
||||
lds r25, timerTicksSinceLastRun+1
|
||||
adiw r25:r24, 1
|
||||
sts timerTicksSinceLastRun, r24
|
||||
sts timerTicksSinceLastRun+1, r25
|
||||
|
||||
lds r24, timerInterrupts
|
||||
lds r25, timerInterrupts+1
|
||||
adiw r25:r24, 1
|
||||
sts timerInterrupts, r24
|
||||
sts timerInterrupts+1, r25
|
||||
|
||||
pop r25
|
||||
pop r24
|
||||
out SREG, r15
|
||||
pop r15
|
||||
reti
|
||||
|
||||
|
||||
|
||||
TIMER_END:
|
||||
.equ MODULE_SIZE_TIMER = TIMER_END-TIMER_BEGIN
|
||||
|
||||
|
||||
|
||||
441
avr/modules/twimaster/twimaster.asm
Normal file
441
avr/modules/twimaster/twimaster.asm
Normal file
@@ -0,0 +1,441 @@
|
||||
; ***************************************************************************
|
||||
; 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 TWI_BIT_LENGTH = 10000 ; 100000 and 200000 works for display: 10000, 100000, 200000
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; data
|
||||
|
||||
.dseg
|
||||
|
||||
twiMasterDataBegin:
|
||||
twiMasterScanEnabled: .byte 1
|
||||
twiMasterLastScanned: .byte 1
|
||||
twiMasterDataEnd:
|
||||
|
||||
|
||||
|
||||
; ***************************************************************************
|
||||
; code
|
||||
|
||||
.cseg
|
||||
|
||||
TWIMASTER_BEGIN:
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; macros
|
||||
|
||||
.macro twiClockHi
|
||||
cbi TWI_DDR_SCL, TWI_PINNUM_SCL ; set to input
|
||||
cbi TWI_PORT_SCL, TWI_PINNUM_SCL ; disable internal pullup
|
||||
.endmacro
|
||||
|
||||
|
||||
.macro twiClockLo
|
||||
sbi TWI_DDR_SCL, TWI_PINNUM_SCL ; set to output
|
||||
cbi TWI_PORT_SCL, TWI_PINNUM_SCL ; set to low
|
||||
.endmacro
|
||||
|
||||
|
||||
.macro twiDataHi
|
||||
cbi TWI_DDR_SDA, TWI_PINNUM_SDA ; set to input
|
||||
cbi TWI_PORT_SDA, TWI_PINNUM_SDA ; disable internal pullup
|
||||
.endmacro
|
||||
|
||||
|
||||
.macro twiDataLo
|
||||
sbi TWI_DDR_SDA, TWI_PINNUM_SDA ; set to output
|
||||
cbi TWI_PORT_SDA, TWI_PINNUM_SDA ; set to low
|
||||
.endmacro
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; TWI_Master_Init
|
||||
;
|
||||
; IN:
|
||||
; OUT:
|
||||
; - CFLAG: set if okay, clear on error
|
||||
; USED:
|
||||
|
||||
TWI_Master_Init:
|
||||
twiClockHi
|
||||
twiDataHi
|
||||
|
||||
; preset SRAM data area
|
||||
ldi xh, HIGH(twiMasterDataBegin)
|
||||
ldi xl, LOW(twiMasterDataBegin)
|
||||
clr r16
|
||||
ldi r17, (twiMasterDataEnd-twiMasterDataBegin)
|
||||
rcall Utils_FillSram
|
||||
|
||||
sec
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; TWI_Master_Fini
|
||||
;
|
||||
; IN:
|
||||
; OUT:
|
||||
; USED:
|
||||
|
||||
TWI_Master_Fini:
|
||||
sec
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; TWI_Master_Run
|
||||
;
|
||||
; IN:
|
||||
; OUT:
|
||||
; USED:
|
||||
|
||||
TWI_Master_Run:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; twiStart
|
||||
;
|
||||
; Send START condition on the bus.
|
||||
;
|
||||
; IN:
|
||||
; - nothing
|
||||
; OUT:
|
||||
; - nothing
|
||||
; USED: R22
|
||||
|
||||
twiStart:
|
||||
twiDataHi
|
||||
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
||||
twiClockHi
|
||||
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
||||
twiDataLo
|
||||
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
||||
twiClockLo
|
||||
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; twiStop
|
||||
;
|
||||
; Send STOP condition on the bus.
|
||||
;
|
||||
; IN:
|
||||
; - nothing
|
||||
; OUT:
|
||||
; - nothing
|
||||
; USED: R22
|
||||
|
||||
twiStop:
|
||||
twiDataLo
|
||||
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
||||
twiClockHi
|
||||
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
||||
twiDataHi
|
||||
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; twiRestart
|
||||
;
|
||||
; Send START condition again (needed for some chips to send address in write mode
|
||||
; and receive data afterwards in read mode).
|
||||
;
|
||||
; IN:
|
||||
; - nothing
|
||||
; OUT:
|
||||
; - nothing
|
||||
; USED: R22
|
||||
|
||||
|
||||
twiRestart:
|
||||
twiDataHi
|
||||
twiClockHi
|
||||
rjmp twiStart
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; twiReadBit
|
||||
;
|
||||
; Read a bit from the line (handling SCL line and possible clock stretching).
|
||||
;
|
||||
; IN:
|
||||
; - nothing
|
||||
; OUT:
|
||||
; - CARRY flag set: okay, cleared on error
|
||||
; - R16: bit read (if CARRY flag set), i.e. 0x00 or 0x01
|
||||
; USED: R16, R22
|
||||
|
||||
twiReadBit:
|
||||
twiDataHi
|
||||
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
||||
twiClockHi
|
||||
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
||||
ldi r16, 100
|
||||
twiReadBit_loop:
|
||||
sbic TWI_PIN_SCL, TWI_PINNUM_SCL
|
||||
rjmp twiReadBit_clockReleased
|
||||
Utils_WaitNanoSecs TWI_BIT_LENGTH/20, 0, r22
|
||||
dec r16
|
||||
brne twiReadBit_loop
|
||||
; timeout
|
||||
clc
|
||||
ret
|
||||
twiReadBit_clockReleased:
|
||||
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
||||
ldi r16, 1
|
||||
sbis TWI_PIN_SDA, TWI_PINNUM_SDA
|
||||
clr r16
|
||||
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
||||
twiClockLo
|
||||
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
||||
sec
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; twiWriteBit
|
||||
;
|
||||
; Write a bit to the line (handling SCL and SDA line and possible clock stretching).
|
||||
;
|
||||
; IN:
|
||||
; - R16: bit to send (either 0x00 or 0x01)
|
||||
; OUT:
|
||||
; - CARRY flag set: okay, cleared on error
|
||||
; USED: R16, R22
|
||||
|
||||
twiWriteBit:
|
||||
twiClockLo
|
||||
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
||||
tst r16
|
||||
breq twiWriteBit_write0
|
||||
twiDataHi
|
||||
rjmp twiWriteBit_written
|
||||
twiWriteBit_write0:
|
||||
twiDataLo
|
||||
twiWriteBit_written:
|
||||
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
||||
twiClockHi
|
||||
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
||||
ldi r16, 100
|
||||
twiWriteBit_loop:
|
||||
sbic TWI_PIN_SCL, TWI_PINNUM_SCL
|
||||
rjmp twiWriteBit_clockReleased
|
||||
Utils_WaitNanoSecs TWI_BIT_LENGTH/20, 0, r22
|
||||
dec r16
|
||||
brne twiWriteBit_loop
|
||||
; timeout
|
||||
clc
|
||||
ret
|
||||
twiWriteBit_clockReleased:
|
||||
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
||||
twiClockLo
|
||||
Utils_WaitNanoSecs TWI_BIT_LENGTH, 0, r22
|
||||
sec
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; twiSendByte
|
||||
;
|
||||
; Write a byte to the bus and reads the ACK bit back.
|
||||
;
|
||||
; IN:
|
||||
; - R16: byte to send
|
||||
; OUT:
|
||||
; - CARRY flag set: okay, cleared on error
|
||||
; - R16: ACK bit read (0x00 or 0x01)
|
||||
; USED: R16, R17, R18, R22
|
||||
|
||||
twiSendByte:
|
||||
mov r17, r16
|
||||
ldi r18, 8
|
||||
twiSendByte_loop:
|
||||
clr r16
|
||||
lsl r17 ; shift MSB out into carry flag
|
||||
rol r16 ; shift carry flag into r16
|
||||
rcall twiWriteBit ; (R16, R22)
|
||||
brcc twiSendByte_error
|
||||
dec r18
|
||||
brne twiSendByte_loop
|
||||
rcall twiReadBit ; r16: ACK bit received
|
||||
brcc twiSendByte_error
|
||||
sec
|
||||
ret
|
||||
twiSendByte_error:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; twiSendByteExpectAck
|
||||
;
|
||||
; Write a byte to the bus and expect ACK response.
|
||||
;
|
||||
; IN:
|
||||
; - R16: byte to send
|
||||
; OUT:
|
||||
; - CARRY flag set: okay, cleared on error (including case of non-ACK response)
|
||||
; USED: R16, R17, R18, R22
|
||||
|
||||
twiSendByteExpectAck:
|
||||
rcall twiSendByte
|
||||
brcc twiSendByteExpectAck_error
|
||||
tst r16
|
||||
brne twiSendByteExpectAck_error
|
||||
sec
|
||||
ret
|
||||
twiSendByteExpectAck_error:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; twiReceiveByte
|
||||
;
|
||||
; Read a byte from the bus. Does not send an ACK bit, this must be done by the caller,
|
||||
; if required.
|
||||
;
|
||||
; IN:
|
||||
; OUT:
|
||||
; - CARRY flag set: okay, cleared on error
|
||||
; - R16: byte received
|
||||
; USED: R16, R17, R18, R22
|
||||
|
||||
twiReceiveByte:
|
||||
clr r17
|
||||
ldi r18, 8
|
||||
twiReceiveByte_loop:
|
||||
rcall twiReadBit ; (R16, R22)
|
||||
brcc twiReceiveByte_error
|
||||
lsr r16
|
||||
rol r17
|
||||
dec r18
|
||||
brne twiReceiveByte_loop
|
||||
mov r16, r17
|
||||
sec
|
||||
ret
|
||||
twiReceiveByte_error:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------------
|
||||
; twiReceiveByteSendAck
|
||||
;
|
||||
; Read a byte from the bus. Sends ACK bit.
|
||||
;
|
||||
; IN:
|
||||
; OUT:
|
||||
; - CARRY flag set: okay, cleared on error
|
||||
; - R16: byte received
|
||||
; USED: R16, R17, R18, R22
|
||||
|
||||
twiReceiveByteSendAck:
|
||||
rcall twiReceiveByte
|
||||
brcc twiReceiveByteSendAck_error
|
||||
push r16
|
||||
clr r16
|
||||
rcall twiWriteBit ; send ACK (R16, R22)
|
||||
pop r16
|
||||
sec
|
||||
ret
|
||||
twiReceiveByteSendAck_error:
|
||||
clc
|
||||
ret
|
||||
|
||||
|
||||
|
||||
#ifdef WITH_DEBUG
|
||||
|
||||
TWI_Master_ScanNext:
|
||||
in r15, SREG
|
||||
cli
|
||||
lds r16, twiMasterScanEnabled
|
||||
tst r16
|
||||
breq TWI_Master_ScanNext_end
|
||||
lds r16, twiMasterLastScanned
|
||||
tst r16
|
||||
brne TWI_Master_ScanNext_inc
|
||||
ldi r16, 7
|
||||
TWI_Master_ScanNext_inc:
|
||||
inc r16
|
||||
cpi r16, 121
|
||||
breq TWI_Master_ScanNext_finshed
|
||||
; check current address
|
||||
mov r21, r16
|
||||
rcall twiStart
|
||||
sec
|
||||
rol r16 ; (ADDR<<1) + 1: read from address
|
||||
rcall twiSendByte
|
||||
brcc TWI_Master_ScanNext_abort ; clock stretching too long, bus error
|
||||
sts twiMasterLastScanned, r21
|
||||
rcall twiStop
|
||||
tst r16
|
||||
brne TWI_Master_ScanNext_noAnswer
|
||||
; send message about available address
|
||||
mov r1, r21
|
||||
ldi r16, 1
|
||||
mov r2, r16
|
||||
ldi r16, 255 ; send to all
|
||||
push r15
|
||||
rcall CPRO_EnqueueTwiBusMember
|
||||
pop r15
|
||||
rjmp TWI_Master_ScanNext_end
|
||||
TWI_Master_ScanNext_noAnswer:
|
||||
; send message about available address
|
||||
; mov r1, r21
|
||||
; clr r2
|
||||
; ldi r16, 255 ; send to all
|
||||
; push r15
|
||||
; rcall CPRO_EnqueueTwiBusMember
|
||||
; pop r15
|
||||
rjmp TWI_Master_ScanNext_end
|
||||
TWI_Master_ScanNext_abort:
|
||||
rcall twiStop
|
||||
rjmp TWI_Master_ScanNext_end
|
||||
TWI_Master_ScanNext_finshed:
|
||||
clr r16
|
||||
sts twiMasterScanEnabled, r16
|
||||
TWI_Master_ScanNext_end:
|
||||
out SREG, r15
|
||||
ret
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
TWIMASTER_END:
|
||||
.equ MODULE_SIZE_TWIMASTER = TWIMASTER_END-TWIMASTER_BEGIN
|
||||
|
||||
Reference in New Issue
Block a user