; *************************************************************************** ; 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. * ; *************************************************************************** .include "modules/com2/buffer.asm" ; *************************************************************************** ; data .dseg com2DataBegin: com2Address: .byte 1 com2Interrupts: .byte 2 com2LastMsgId: .byte 2 com2RecvStatsBegin: ; 12 bytes com2StatsPacketsIn: .byte 2 com2StatsContentError: .byte 2 com2StatsIoError: .byte 2 com2StatsNoBufferError: .byte 2 com2StatsHandled: .byte 2 com2StatsMissed: .byte 2 ; currently not used com2RecvStatsEnd: com2SendStatsBegin: ; 6 bytes com2StatsPacketsOut: .byte 2 com2StatsCollisions: .byte 2 com2StatsBusyError: .byte 2 com2SendStatsEnd: com2StatsNotForMe: .byte 2 com2StatsIgnored: .byte 2 com2MaxSendBuffersUsed: .byte 1 com2MaxRecvBuffersUsed: .byte 1 com2SendBuffer: .byte COM2_BUFFER_SIZE com2DataEnd: ; *************************************************************************** ; code .cseg COM2_BEGIN: ; --------------------------------------------------------------------------- ; @routine Com2_Init @global ; ; @return CFLAG set if okay, clear on error ; @clobbers 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 rjmp COMIO_Init ; @end ; --------------------------------------------------------------------------- ; @routine Com2_Run @global ; ; @return CFLAG set if something done, can be called again immediately (otherwise: wait for timer interrupt and retry) ; @clobbers (R1, R3, R16, R17, R18, R19, R22, X) COM2_Run: rcall COMIO_Run brcs COM2_Run_carrySet rjmp com2HandleNextPacketInQueue ; return CFLAG from com2HandleNextPacketInQueue COM2_Run_carrySet: rcall com2HandleNextPacketInQueue sec ; return CFLAG set regardless of com2HandleNextPacketInQueue ret ; @end ; --------------------------------------------------------------------------- ; @routine com2HandleNextPacketInQueue ; ; Get next received packet, call onPacketReceived on it and release it ; @return CFLAG set if something done ; @clobbers any com2HandleNextPacketInQueue: rcall COMIO_GetNextReceivedPacket brcc com2HandleNextPacketInQueue_retNc push xl push xh rcall com2CheckMessageInBuffer pop xh pop xl brcs com2HandleNextPacketInQueue_crcOk ldi xl, LOW(com2StatsContentError) ldi xh, HIGH(com2StatsContentError) rjmp com2HandleNextPacketInQueue_incCounterDeallocBuffer com2HandleNextPacketInQueue_crcOk: 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 COMIO_ReleaseReceivedPacket sec ret com2HandleNextPacketInQueue_retNc: clc ret ; @end ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; Preparing messages ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; --------------------------------------------------------------------------- ; @routine COM2_WriteMsgWithCmdAndSrcAddr @global ; ; Write a simple packet into the given buffer with payload being only CMD and source address. ; ; IN: ; @param R16 destination address ; @param R18 command (e.g. CPRO_CMD_PING or CPRO_CMD_PONG) ; @param X pointer to buffer to write to ; @return CFLAG set if okay, clear otherwise ; @clobbers 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 ; @end ; --------------------------------------------------------------------------- ; @routine COM2_BeginMsgWithVariablePayload @global ; ; begin packet with variable payload. ; ; @param R16 destination address ; @param R17 flags ; @param R18 command (e.g. CPRO_CMD_PING) ; @param X pointer to packet buffer ; @return X points to end of packet as it was written so far ; @clobbers 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 rcall COM2_AddSecsToBuffer COM2_BeginMsgWithVariablePayload_l1: lsr r3 ; shift out COM2_PAYLOAD_FLAGS_UID brcc COM2_BeginMsgWithVariablePayload_l2 ; write uid rcall COM2_AddUidToBuffer COM2_BeginMsgWithVariablePayload_l2: ret ; @end ; --------------------------------------------------------------------------- ; @routine COM2_AddUidToBuffer @global ; ; Write UID into buffer given by X. ; ; @return X points to behind written uid ; @param X pointer to packet buffer ; @clobbers: r18, r19, r20, r21 (r16) COM2_AddUidToBuffer: 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 ret ; @end ; --------------------------------------------------------------------------- ; @routine COM2_AddSecsToBuffer @global ; ; Write current seconds counter (4 bytes) into buffer given by X, advance X. ; ; @return X points to behind written seconds ; @param X pointer to packet buffer ; @clobbers r16 COM2_AddSecsToBuffer: lds r16, timerModuleCounterSecs ; add current seconds counter st X+, r16 lds r16, timerModuleCounterSecs+1 st X+, r16 lds r16, timerModuleCounterSecs+2 st X+, r16 lds r16, timerModuleCounterSecs+3 st X+, r16 ret ; @end ; --------------------------------------------------------------------------- ; @routine COM2_AddNextMsgIdToBuffer @global ; ; Write next message id (2 bytes) into buffer given by X, advance X. ; ; @return X points to behind written message id ; @param X pointer to packet buffer ; @clobbers: r16, r17, r18 COM2_AddNextMsgIdToBuffer: ldi r18, 1 lds r16, com2LastMsgId lds r17, com2LastMsgId+1 add r16, r18 dec r18 adc r17, r18 sts com2LastMsgId, r16 sts com2LastMsgId+1, r17 st X+, r16 st X+, r17 ret ; @end ; --------------------------------------------------------------------------- ; com2CalcPayloadSize ; ; Calculate payload size from given flags ; ; @param R16 flags ; @return R16 payload size ; @clobbers 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 ; @end ; --------------------------------------------------------------------------- ; @routine COM2_SendPacket ; ; send packet from sendBuffer, if line free. ; ; @return CFLAG set if okay (packet sent), cleared on error ; @clobbers any (depending on io implementation) COM2_SendPacket: ldi xl, LOW(com2SendBuffer) ldi xh, HIGH(com2SendBuffer) rjmp COMIO_SendPacket ; @end .include "modules/com2/crc.asm" COM2_END: .equ MODULE_SIZE_COM2 = COM2_END-COM2_BEGIN