diff --git a/aqhome/msg/node/0BUILD b/aqhome/msg/node/0BUILD index 595ef36..43d0bc1 100644 --- a/aqhome/msg/node/0BUILD +++ b/aqhome/msg/node/0BUILD @@ -62,6 +62,7 @@ m_flashend.h m_flashready.h m_flashresponse.h + m_range.h @@ -89,6 +90,7 @@ m_flashend.c m_flashready.c m_flashresponse.c + m_range.c diff --git a/aqhome/msg/node/m_node.c b/aqhome/msg/node/m_node.c index 3959207..f345b4a 100644 --- a/aqhome/msg/node/m_node.c +++ b/aqhome/msg/node/m_node.c @@ -28,6 +28,7 @@ #include "aqhome/msg/node/m_flashend.h" #include "aqhome/msg/node/m_flashready.h" #include "aqhome/msg/node/m_flashresponse.h" +#include "aqhome/msg/node/m_range.h" #include @@ -212,6 +213,7 @@ const char *AQH_NodeMessage_MsgTypeToChar(uint8_t i) case AQH_MSG_TYPE_CLAIM_ADDRESS: return "ClaimAddress"; case AQH_MSG_TYPE_DENY_ADDRESS: return "DenyAddress"; case AQH_MSG_TYPE_ADDRESS_RANGE: return "Range"; + case AQH_MSG_TYPE_REENUM: return "Reenum"; case AQH_MSG_TYPE_FLASH_START: return "FlashStart"; case AQH_MSG_TYPE_FLASH_END: return "FlashEnd"; @@ -246,6 +248,8 @@ void AQH_NodeMessage_DumpSpecificToBuffer(const AQH_MESSAGE *msg, GWEN_BUFFER *d case AQH_MSG_TYPE_HAVE_ADDRESS: AQH_AddrMessage_DumpToBuffer(msg, dbuf, sText); break; case AQH_MSG_TYPE_CLAIM_ADDRESS: AQH_AddrMessage_DumpToBuffer(msg, dbuf, sText); break; case AQH_MSG_TYPE_DENY_ADDRESS: AQH_AddrMessage_DumpToBuffer(msg, dbuf, sText); break; + case AQH_MSG_TYPE_ADDRESS_RANGE: AQH_RangeMessage_DumpToBuffer(msg, dbuf, sText); break; + case AQH_MSG_TYPE_REENUM: AQH_RangeMessage_DumpToBuffer(msg, dbuf, sText); break; case AQH_MSG_TYPE_FLASH_START: AQH_FlashStartMessage_DumpToBuffer(msg, dbuf, sText); break; case AQH_MSG_TYPE_FLASH_END: AQH_FlashEndMessage_DumpToBuffer(msg, dbuf, sText); break; @@ -266,7 +270,6 @@ void AQH_NodeMessage_DumpSpecificToBuffer(const AQH_MESSAGE *msg, GWEN_BUFFER *d case AQH_MSG_TYPE_DEBUG: case AQH_MSG_TYPE_TWIBUSMEMBER: - case AQH_MSG_TYPE_ADDRESS_RANGE: default: AQH_NodeMessage_DumpToBuffer(msg, dbuf, sText); break; } } diff --git a/aqhome/msg/node/m_node.h b/aqhome/msg/node/m_node.h index ba9acb2..151d625 100644 --- a/aqhome/msg/node/m_node.h +++ b/aqhome/msg/node/m_node.h @@ -40,6 +40,7 @@ #define AQH_MSG_TYPE_CLAIM_ADDRESS 62 #define AQH_MSG_TYPE_DENY_ADDRESS 63 #define AQH_MSG_TYPE_ADDRESS_RANGE 64 +#define AQH_MSG_TYPE_REENUM 65 #define AQH_MSG_TYPE_FLASH_START 70 #define AQH_MSG_TYPE_FLASH_END 71 diff --git a/aqhome/msg/node/m_range.c b/aqhome/msg/node/m_range.c new file mode 100644 index 0000000..fa898c6 --- /dev/null +++ b/aqhome/msg/node/m_range.c @@ -0,0 +1,61 @@ +/**************************************************************************** + * This file is part of the project AqHome. + * AqHome (c) by 2025 Martin Preuss, all rights reserved. + * + * The license for this file can be found in the file COPYING which you + * should have received along with this file. + ****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include +#endif + + + +#include "aqhome/msg/node/m_range.h" +#include "aqhome/msg/node/m_node.h" + +#include + + +#define AQH_MSG_OFFS_RANGE_UID 0 /* 4 bytes */ +#define AQH_MSG_OFFS_RANGE_BEGIN 4 /* 1 bytes */ +#define AQH_MSG_OFFS_RANGE_END 5 /* 1 bytes */ + + + +uint32_t AQH_RangeMessage_GetUid(const AQH_MESSAGE *msg) +{ + return AQH_Message_ReadUint32At(msg, AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_RANGE_UID, 0); +} + + + +uint8_t AQH_RangeMessage_GetRangeBegin(const AQH_MESSAGE *msg) +{ + return AQH_Message_ReadUint8At(msg, AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_RANGE_BEGIN, 0); +} + + + +uint8_t AQH_RangeMessage_GetRangeEnd(const AQH_MESSAGE *msg) +{ + return AQH_Message_ReadUint8At(msg, AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_RANGE_END, 0); +} + + + +void AQH_RangeMessage_DumpToBuffer(const AQH_MESSAGE *msg, GWEN_BUFFER *dbuf, const char *sText) +{ + GWEN_Buffer_AppendArgs(dbuf, + "0x%02x->0x%02x: RANGE(%s) %s (uid=0x%08x, begin=0x%x, end=0x%x)\n", + AQH_NodeMessage_GetSourceAddress(msg), + AQH_NodeMessage_GetDestAddress(msg), + AQH_NodeMessage_MsgTypeToChar(AQH_NodeMessage_GetMsgType(msg)), + sText, + (unsigned int) AQH_RangeMessage_GetUid(msg), + AQH_RangeMessage_GetRangeBegin(msg), + AQH_RangeMessage_GetRangeEnd(msg)); +} + + diff --git a/aqhome/msg/node/m_range.h b/aqhome/msg/node/m_range.h new file mode 100644 index 0000000..a77120e --- /dev/null +++ b/aqhome/msg/node/m_range.h @@ -0,0 +1,30 @@ +/**************************************************************************** + * This file is part of the project AqHome. + * AqHome (c) by 2025 Martin Preuss, all rights reserved. + * + * The license for this file can be found in the file COPYING which you + * should have received along with this file. + ****************************************************************************/ + +#ifndef AQH_M_RANGE_H +#define AQH_M_RANGE_H + + +#include +#include + +#include + + +/* This message is used for message types ClaimAddr, DenyAddr, HaveAddr */ + +AQHOME_API uint32_t AQH_RangeMessage_GetUid(const AQH_MESSAGE *msg); +AQHOME_API uint8_t AQH_RangeMessage_GetAddr(const AQH_MESSAGE *msg); +AQHOME_API uint8_t AQH_RangeMessage_GetRangeBegin(const AQH_MESSAGE *msg); +AQHOME_API uint8_t AQH_RangeMessage_GetRangeEnd(const AQH_MESSAGE *msg); + +AQHOME_API void AQH_RangeMessage_DumpToBuffer(const AQH_MESSAGE *msg, GWEN_BUFFER *dbuf, const char *sText); + + + +#endif diff --git a/avr/apps/network/main.asm b/avr/apps/network/main.asm index 18e7ed5..5205261 100644 --- a/avr/apps/network/main.asm +++ b/avr/apps/network/main.asm @@ -117,6 +117,13 @@ AppNetwork_EveryDay: ; @param X pointer to received message AppNetwork_HandleMsg: + push xl + push xh + rcall AppNetwork_HandleMsg_savedX + pop xh + pop xl + rjmp AppNetwork_HandleMsg_end +AppNetwork_HandleMsg_savedX: adiw xh:xl, NETMSG_OFFS_CMD ld r16, X sbiw xh:xl, NETMSG_OFFS_CMD @@ -124,14 +131,21 @@ AppNetwork_HandleMsg: breq AppNetwork_HandleMsg_handleRebootMsg cpi r16, NETMSG_CMD_PING breq AppNetwork_HandleMsg_handlePingMsg + cpi r16, NETMSG_CMD_REENUM + breq AppNetwork_HandleMsg_handleReenumMsg cpi r16, NETMSG_CMD_NEED_ADDRESS brcs AppNetwork_HandleMsg_clcRet ; lower than "HAVE_NEED" cpi r16, NETMSG_CMD_ADDRESS_RANGE breq AppNetwork_HandleMsg_handleRangeMsg brcc AppNetwork_HandleMsg_clcRet ; higher or equal to "ADDR_RANGE" rjmp AppNetwork_HandleMsg_handleAddrMsg +AppNetwork_HandleMsg_handleReenumMsg: + rjmp appNetworkHandleReeunumRequest AppNetwork_HandleMsg_handleRangeMsg: - ; TODO + bigcall NETMSG_Range_Read + std Y+NET_IFACE_OFFS_RANGE_BEGIN, r20 + std Y+NET_IFACE_OFFS_RANGE_END, r21 + std Y+NET_IFACE_OFFS_ADDRESS, r20 rjmp AppNetwork_HandleMsg_clcRet AppNetwork_HandleMsg_handleAddrMsg: @@ -145,21 +159,13 @@ AppNetwork_HandleMsg_handleAddrMsg: sub zh, r16 ijmp AppNetwork_HandleMsg_handleRebootMsg: - push xl - push xh - rcall appNetworkHandleRebootRequest - pop xh - pop xl + rcall appNetworkHandleRebootRequest ret AppNetwork_HandleMsg_handlePingMsg: - push xl - push xh - rcall appNetworkHandlePingRequest - pop xh - pop xl - ret + rjmp appNetworkHandlePingRequest AppNetwork_HandleMsg_clcRet: clc +AppNetwork_HandleMsg_end: ret ; @end @@ -171,12 +177,8 @@ AppNetwork_HandleMsg_clcRet: ; @param X pointer to received message appNetworkHandleRebootRequest: - ld r16, X ; dest addr - cpi r16, 0xff ; don't reboot for broadcast address - breq appNetworkHandleRebootRequest_end - rcall NETMSG_RebootRequestRead - brcc appNetworkHandleRebootRequest_end + brcc appNetworkHandleRebootRequest_end ; uid doesn't match ; reboot cli bigjmp BOOTLOADER_ADDR @@ -207,6 +209,20 @@ appNetworkHandlePingRequest_end: +appNetworkHandleReeunumRequest: + rcall NETMSG_Range_Read + ldi r16, APP_NETWORK_STATE_INITIALWAIT + std Y+NET_IFACE_OFFS_STATUS, r16 + ldd r16, Y+NET_IFACE_OFFS_ADDRESS ; use current address as timer + std Y+NET_IFACE_OFFS_STATETIMER, r16 + ldi r16, APP_NETWORK_ADDRESS_RANGE_BEGIN + std Y+NET_IFACE_OFFS_RANGE_BEGIN, r20 + std Y+NET_IFACE_OFFS_RANGE_END, r21 + ret +; @end + + + appNetworkTimerTable: rjmp appNetworkHandleStateInitialWait rjmp appNetworkHandleStateNeedAddress @@ -253,12 +269,8 @@ appNetworkHandleStateHaveAddress2: std Y+NET_IFACE_OFFS_STATUS, r16 ldi r16, APP_NETWORK_TIMER_100MS std Y+NET_IFACE_OFFS_STATETIMER, r16 - ldd r16, Y+NET_IFACE_OFFS_RANGE_BEGIN ; set interface address - ldd r17, Y+NET_IFACE_OFFS_ADDRESS - cp r16, r17 - breq appNetworkHandleStateHaveAddress2_end ; store new address in IFACE and in EEPROM - std Y+NET_IFACE_OFFS_ADDRESS, r16 + ldd r16, Y+NET_IFACE_OFFS_ADDRESS push r15 in r15, SREG cli @@ -284,7 +296,7 @@ appNetworkHandleStateUp: ; @clobbers R16, R19 (R17, R18, R20, R21, X) appNetworkSendMsgNextState: - ldd r19, Y+NET_IFACE_OFFS_RANGE_BEGIN + ldd r19, Y+NET_IFACE_OFFS_ADDRESS rcall appNetworkSendAddrMsg ; (R16, R17, R18, R19, R20, R21, X) brcc appNetworkSendMsgNextState_retry ldd r16, Y+NET_IFACE_OFFS_STATUS @@ -349,9 +361,9 @@ appNetworkHandleMsgClaimAddr: cp r19, r16 brne appNetworkHandleMsgClaimAddr_end ; not our address ldd r16, Y+NET_IFACE_OFFS_STATUS - cpi r16, APP_NETWORK_STATE_UP ; up? - brne appNetworkHandleMsgClaimAddr_end ; nope, ignore - ; network is up, someone claimed our address, deny it + cpi r16, APP_NETWORK_STATE_CLAIMADDRESS1 + brcs appNetworkHandleMsgClaimAddr_end ; nope, ignore + ; network is somewhat up, someone claimed our address, deny it ldi r18, NETMSG_CMD_DENY_ADDRESS ; deny our addr ldd r19, Y+NET_IFACE_OFFS_ADDRESS rjmp appNetworkSendAddrMsg @@ -373,12 +385,12 @@ appNetworkHandleMsgDenyAddr: cpi r16, APP_NETWORK_STATE_UP breq appNetworkHandleMsgDenyAddr_end ; ignore (our network stack is up) ; still setting up address, check whether the last one is denied now - ldd r16, Y+NET_IFACE_OFFS_RANGE_BEGIN + ldd r16, Y+NET_IFACE_OFFS_ADDRESS cp r19, r16 ; our claimed address? brne appNetworkHandleMsgDenyAddr_end ; nope, jump ; try next address (if any left) ldd r17, Y+NET_IFACE_OFFS_RANGE_END - inc r16 ; RANGE_BEGIN+1 + inc r16 ; next address cp r17, r16 ; smaller than or equal to RANGE_END? brcc appNetworkHandleMsgDenyAddr_claimNext ; out of addresses, start completely new after some waiting time @@ -388,7 +400,7 @@ appNetworkHandleMsgDenyAddr: rjmp appNetworkHandleMsgDenyAddr_end appNetworkHandleMsgDenyAddr_claimNext: ; send CLAIM_ADDR for next address (new state: APP_NETWORK_STATE_NEEDADDRESS+1) - std Y+NET_IFACE_OFFS_RANGE_BEGIN, r16 + std Y+NET_IFACE_OFFS_ADDRESS, r16 ldi r16, APP_NETWORK_STATE_NEEDADDRESS std Y+NET_IFACE_OFFS_STATUS, r16 ldi r18, NETMSG_CMD_CLAIM_ADDRESS @@ -439,6 +451,7 @@ appNetworkResetState: std Y+NET_IFACE_OFFS_STATETIMER, r16 ldi r16, APP_NETWORK_ADDRESS_RANGE_BEGIN std Y+NET_IFACE_OFFS_RANGE_BEGIN, r16 + std Y+NET_IFACE_OFFS_ADDRESS, r16 rcall appNetworkGetAddressFromEeprom ; R16=addr (R15, X) tst r16 breq appNetworkResetState_setRangeEnd diff --git a/avr/apps/router/main.asm b/avr/apps/router/main.asm index 4df9bf2..76e1d0d 100644 --- a/avr/apps/router/main.asm +++ b/avr/apps/router/main.asm @@ -56,6 +56,8 @@ AppRouter_Init: ldi r16, 0xef sts appRouterRangeEnd, r16 + rcall appRouterReadConfFromEeprom ; try to read config from EEPROM + ; set interface number for NETDEV0 ldi r16, NETDEV0_IFACENUM sts netInterfaceData+NET_IFACE_OFFS_IFACENUM, r16 @@ -97,35 +99,207 @@ AppRouter_Run: ; --------------------------------------------------------------------------- -; @routine AppRouter_HandleMsg @global +; @routine appRouterHandleMsgAnyDev @global ; ; @param X pointer to received message +; @return CFLAG set if msg handled, cleared otherwise +; @clobbers any, !X -AppRouter_HandleMsg: - adiw xh:xl, NETMSG_OFFS_CMD ; maybe move ping/reboot handling to all/main.asm? +appRouterHandleMsgAnyDev: + push xl + push xh + rcall appRouterHandleMsgAnyDev_savedX + pop xh + pop xl + rjmp appRouterHandleMsgAnyDev_end +appRouterHandleMsgAnyDev_savedX: + adiw xh:xl, NETMSG_OFFS_CMD ; maybe move ping/reboot handling to all/main.asm? ld r16, X sbiw xh:xl, NETMSG_OFFS_CMD cpi r16, NETMSG_CMD_REBOOT_REQUEST - breq AppRouter_HandleMsg_handleRebootMsg + breq appRouterHandleMsgAnyDev_handleRebootMsg cpi r16, NETMSG_CMD_PING - breq AppRouter_HandleMsg_handlePingMsg - rjmp AppRouter_HandleMsg_clcRet -AppRouter_HandleMsg_handleRebootMsg: - push xl - push xh - rcall appRouterHandleRebootRequest - pop xh - pop xl + breq appRouterHandleMsgAnyDev_handlePingMsg + cpi r16, NETMSG_CMD_VALUE_SET + breq appRouterHandleMsgAnyDev_handleSetValue + rjmp appRouterHandleMsgAnyDev_clcRet +appRouterHandleMsgAnyDev_handleRebootMsg: + rcall appRouterHandleRebootRequest ret -AppRouter_HandleMsg_handlePingMsg: - push xl - push xh - rcall appRouterHandlePingRequest - pop xh - pop xl +appRouterHandleMsgAnyDev_handlePingMsg: + rcall appRouterHandlePingRequest ret -AppRouter_HandleMsg_clcRet: +appRouterHandleMsgAnyDev_handleSetValue: + rcall NETMSG_ValueRead ; (none) + cpi r17, VALUE_ID_ROUTER_SETRANGE + breq appRouterHandleMsgAnyDev_handleSetRange + rjmp appRouterHandleMsgAnyDev_clcRet +appRouterHandleMsgAnyDev_handleSetRange: + sts netInterfaceData+NET_IFACE_OFFS_ADDRESS, r18 ; use first address for router itself + sts netInterfaceData2+NET_IFACE_OFFS_ADDRESS, r18 ; use same address for both interfaces to save on addresses + inc r18 ; start range after router + sts appRouterRangeBegin, r18 + sts appRouterRangeEnd, r19 + ; send ACK + ldi r23, NETMSG_CMD_VALUE_SET_ACK + rcall Main_SendValueResponse ; (clobbers all, including Y) + ; let subnodes re-eunumerate + ldi r18, NETMSG_CMD_REENUM + rcall appRouterSendRangeMsgToDev1 ; (R16, R17, R18, R19, R20, R21, X, Y) + rcall appRouterWriteConfToEeprom ; (r16, r17, X) + sec + ret +appRouterHandleMsgAnyDev_clcRet: clc +appRouterHandleMsgAnyDev_end: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine appRouterHandleDev1Msg @global +; +; Handle messages from controlled subnet. +; +; @param X pointer to received message +; @return CFLAG set if msg handled, cleared otherwise +; @clobbers any, !X + +appRouterHandleDev1Msg: + push xl + push xh + rcall appRouterHandleDev1Msg_savedX + pop xh + pop xl + rjmp appRouterHandleDev1Msg_end +appRouterHandleDev1Msg_savedX: + adiw xh:xl, NETMSG_OFFS_CMD ; maybe move ping/reboot handling to all/main.asm? + ld r16, X + sbiw xh:xl, NETMSG_OFFS_CMD + cpi r16, NETMSG_CMD_NEED_ADDRESS + breq appRouterHandleDev1Msg_handleNeedAddr + cpi r16, NETMSG_CMD_CLAIM_ADDRESS + breq appRouterHandleDev1Msg_handleClaimAddr + ; add more here + rjmp appRouterHandleDev1Msg_clcRet +appRouterHandleDev1Msg_handleNeedAddr: + ldi r18, NETMSG_CMD_ADDRESS_RANGE + rcall appRouterSendRangeMsgToDev1 ; (R16, R17, R18, R19, R20, R21, X, Y) + sec + rjmp appRouterHandleDev1Msg_end +appRouterHandleDev1Msg_handleClaimAddr: + rcall NETMSG_Address_Read ; R18=cmd, R19=addr(R18, R19) + rcall appRouterIsR19InRange + brcs appRouterHandleDev1Msg_end + ; is not in subnet range, deny + rcall appRouterSendDenyAddrR19ToDev1 ; (R16, R17, R18, R19, R20, R21, X, Y) + sec + rjmp appRouterHandleDev1Msg_end +appRouterHandleDev1Msg_clcRet: + clc +appRouterHandleDev1Msg_end: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine appRouterIsR19InRange +; +; @param R19 address to check against range +; @clobbers R16 + +appRouterIsR19InRange: + lds r16, appRouterRangeBegin + cp r19, r16 + brcs appRouterIsR19InRangeClcRet + lds r16, appRouterRangeEnd + cp r16, r19 + brcs appRouterIsR19InRangeClcRet + sec + rjmp appRouterIsR19InRange_end +appRouterIsR19InRangeClcRet: + clc +appRouterIsR19InRange_end: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine appRouterSendDenyAddrR19ToDev1 +; +; @param R19 address to send +; @clobbers R16, R17, R18, R19, R20, R21, X, Y + +appRouterSendDenyAddrR19ToDev1: + ldi r18, NETMSG_CMD_DENY_ADDRESS ; deny addr + rjmp appRouterSendAddrMsgToDev1 ; (R16, R17, R18, R19, R20, R21, X, Y) +; @end + + + +; --------------------------------------------------------------------------- +; @routine appRouterSendAddrMsgToDev1 +; +; @param R18 command +; @param R19 address to send +; @clobbers R16 (R17, R18, R19, R20, R21, X, Y) + +appRouterSendAddrMsgToDev1: + bigcall NET_Buffer_Alloc ; (R16, R17, X) + brcc appRouterSendAddrMsgToDev1_end + push r16 + adiw xh:xl, 1 + bigcall NETMSG_Address_Write ; (R16, R17, R18, R19, R20, R21) + sbiw xh:xl, 1 + pop r16 + rcall appRouterSendMsgToDev1 ; (R16, R17, R18, X, Y) +appRouterSendAddrMsgToDev1_end: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine appRouterSendRangeMsgToDev1 +; +; @param R18 msg code +; @clobbers (R16, R17, R18, R19, R20, R21, X, Y) + +appRouterSendRangeMsgToDev1: + bigcall NET_Buffer_Alloc ; (R16, R17, X) + brcc appRouterSendRangeMsgToDev1_end + push r16 + lds r20, appRouterRangeBegin + lds r21, appRouterRangeEnd + adiw xh:xl, 1 + bigcall NETMSG_Range_Write ; (R16, R17, R18, R19, R20, R21) + sbiw xh:xl, 1 + pop r16 + rcall appRouterSendMsgToDev1 ; (R16, R17, R18, X, Y) +appRouterSendRangeMsgToDev1_end: + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine appRouterSendMsgToDev1 +; +; @param R16 num of allocated buffer +; @param X msg to send (points to start of allocated buffer, e.g. buffer header) +; @clobbers Y (R16, R17, R18, X) + +appRouterSendMsgToDev1: + ldi yl, LOW(netInterfaceData2) + ldi yh, HIGH(netInterfaceData2) + bigcall NET_Interface_AddOutgoingMsgNum ; (R17, R18, X) + brcs appRouterSendMsgToDev1_end + bigcall NET_Buffer_ReleaseByNum ; (R16, X) + clc +appRouterSendMsgToDev1_end: ret ; @end @@ -134,13 +308,11 @@ AppRouter_HandleMsg_clcRet: ; --------------------------------------------------------------------------- ; @routine appRouterHandleRebootRequest ; +; Doesn't return if reboot msg is valid. +; ; @param X pointer to received message appRouterHandleRebootRequest: - ld r16, X ; dest addr - cpi r16, 0xff ; don't reboot for broadcast address - breq appRouterHandleRebootRequest_end - rcall NETMSG_RebootRequestRead brcc appRouterHandleRebootRequest_end ; reboot @@ -152,6 +324,11 @@ appRouterHandleRebootRequest_end: +; --------------------------------------------------------------------------- +; @routine appRouterHandlePingRequest +; +; @param X pointer to received message + appRouterHandlePingRequest: adiw xh:xl, NETMSG_OFFS_SRCADDR ld r17, X @@ -180,14 +357,14 @@ appRouterHandlePingRequest_end: appRouterCheckRecvdMsg: rcall NET_PeekNextIncomingMsgNum ; check read queue (bufNum->r16) - brcc appRouterCheckRecvdMsg_end ; no msg, jmp + brcc appRouterCheckRecvdMsg_end ; no msg, jmp rcall NET_Buffer_Locate ; (R17) + rcall appRouterHandleRouterMsgWithHdr ; filter out router msgs + brcs appRouterCheckRecvdMsg_removeMsg ; handled by router code, don't forward ; let system handle incoming messages - push r16 - adiw xh:xl, 1 - rcall appRouterLetSysHandleMsg - sbiw xh:xl, 1 - pop r16 + adiw xh:xl, 1 + rcall appRouterLetSysHandleMsg + sbiw xh:xl, 1 ; forward to other interface ld r17, X @@ -197,11 +374,43 @@ appRouterCheckRecvdMsg: brcc appRouterCheckRecvdMsg_end ; could not add, jmp rcall NET_GetNextIncomingMsgNum ; take off the queue rjmp appRouterCheckRecvdMsg + +appRouterCheckRecvdMsg_removeMsg: + rcall NET_GetNextIncomingMsgNum ; take off the queue + rcall NET_Buffer_ReleaseByNum ; (R16, X) + sec appRouterCheckRecvdMsg_end: ret ; @end +; --------------------------------------------------------------------------- +; @routine appRouterHandleRouterMsgWithHdr +; +; @param X pointer to msg +; @return CFLAG set if msg handled, cleared otherwise + +appRouterHandleRouterMsgWithHdr: + ld r17, X + andi r17, (1< diff --git a/avr/common/eeprom-r.asm b/avr/common/eeprom-r.asm new file mode 100644 index 0000000..bd66fa0 --- /dev/null +++ b/avr/common/eeprom-r.asm @@ -0,0 +1,86 @@ +; *************************************************************************** +; copyright : (C) 2025 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. * +; *************************************************************************** + +#ifndef AQH_AVR_COMMON_EEPROM_R_H +#define AQH_AVR_COMMON_EEPROM_R_H + + + +; --------------------------------------------------------------------------- +; @routine Eeprom_ReadByte +; +; Read a byte from EEPROM (see example in ATtiny24/44/84 manual p.19). +; +; @param X EEPROM Address to read from +; @return CFLAG set if address okay, cleared if out of range +; @return R16 byte read +; @return X EEPROM Address incremented +; @clobbers none + +Eeprom_ReadByte: + rcall Eeprom_CheckAddr + brcs Eeprom_ReadByte_addrOk + ret +Eeprom_ReadByte_addrOk: + ; call routine with IRQs disabled + push r15 + inr r15, SREG + cli + rcall Eeprom_ReadByte_noirq + outr SREG, r15 + pop r15 + sec + ret +Eeprom_ReadByte_noirq: + ; wait until EEPROM ready +Eeprom_ReadByte_waitLoop: +.ifdef EEPE + sbic EECR, EEPE ; wait for previous write to complete (if any) +.else + sbic EECR, EEWE ; wait for previous write to complete (if any) +.endif + rjmp Eeprom_ReadByte_waitLoop +; read from EEPROM + 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 + ret +; @end + + + +; --------------------------------------------------------------------------- +; @routine Eeprom_CheckAddr +; +; +; @param X EEPROM Address to validate +; @return CFLAG set if address okay, cleared if out of range +; @clobbers r16 + +Eeprom_CheckAddr: + mov r16, xl + subi r16, LOW(EEPROMEND) + mov r16, xh + sbci r16, HIGH(EEPROMEND) + brcc Eeprom_CheckAddr_ok + clc + rjmp Eeprom_CheckAddr_end +Eeprom_CheckAddr_ok: + sec +Eeprom_CheckAddr_end: + ret +; @end + + + + +#endif ; AQH_AVR_COMMON_EEPROM_R_H + + diff --git a/avr/common/eeprom-w.asm b/avr/common/eeprom-w.asm new file mode 100644 index 0000000..02d87a2 --- /dev/null +++ b/avr/common/eeprom-w.asm @@ -0,0 +1,100 @@ +; *************************************************************************** +; copyright : (C) 2025 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. * +; *************************************************************************** + +#ifndef AQH_AVR_COMMON_EEPROM_W_H +#define AQH_AVR_COMMON_EEPROM_W_H + + +; --------------------------------------------------------------------------- +; Utils_WriteEepromIncr +; +; Write a byte to EEPROM (see example in ATtiny24/44/84 manual p.18). +; +; @param R16 byte to write +; @param X EEPROM Address to write to +; @return CFLAG set if data written, cleared on error +; @clobbers R17 + +Eeprom_WriteByte: + mov r17, r16 + rcall Eeprom_CheckAddr ; (r16) + mov r16, r17 + brcs Eeprom_WriteByte_addrOk + ret +Eeprom_WriteByte_addrOk: + ; call routine with IRQs disabled + push r15 + inr r15, SREG + cli + rcall Eeprom_WriteByte_noirq + outr SREG, r15 + pop r15 + sec + ret +Eeprom_WriteByte_noirq: + ; wait for EEPROM to be ready +Eeprom_WriteByte_waitLoop: +.ifdef EEPE + sbic EECR, EEPE ; wait for previous write to complete (if any) +.else + sbic EECR, EEWE ; wait for previous write to complete (if any) +.endif + rjmp Eeprom_WriteByte_waitLoop + ; write data +.ifdef EEPM1 + ldi r17, (0< + diff --git a/avr/devices/r05/main/main.asm b/avr/devices/r05/main/main.asm index b777a22..b036a5e 100644 --- a/avr/devices/r05/main/main.asm +++ b/avr/devices/r05/main/main.asm @@ -89,6 +89,7 @@ .equ VALUE_ID_DS18B20_TEMP = 0x06 .equ VALUE_ID_LEDSIMPLE_TIMING = 0x88 +.equ VALUE_ID_ROUTER_SETRANGE = 0x89 ; *************************************************************************** diff --git a/avr/modules/network/msg/0BUILD b/avr/modules/network/msg/0BUILD index 88b6afe..8c7a484 100644 --- a/avr/modules/network/msg/0BUILD +++ b/avr/modules/network/msg/0BUILD @@ -13,6 +13,9 @@ device-w.asm memstats-w.asm pong-w.asm + range-d.asm + range-r.asm + range-w.asm reboot-d.asm reboot-r.asm recvstats-w.asm diff --git a/avr/modules/network/msg/defs.asm b/avr/modules/network/msg/defs.asm index e5b8c3d..5b2a62c 100644 --- a/avr/modules/network/msg/defs.asm +++ b/avr/modules/network/msg/defs.asm @@ -26,6 +26,7 @@ .equ NETMSG_CMD_CLAIM_ADDRESS = 62 .equ NETMSG_CMD_DENY_ADDRESS = 63 .equ NETMSG_CMD_ADDRESS_RANGE = 64 +.equ NETMSG_CMD_REENUM = 65 .equ NETMSG_CMD_FLASH_START = 70 .equ NETMSG_CMD_FLASH_END = 71 diff --git a/avr/modules/network/msg/range-d.asm b/avr/modules/network/msg/range-d.asm new file mode 100644 index 0000000..723d8cc --- /dev/null +++ b/avr/modules/network/msg/range-d.asm @@ -0,0 +1,18 @@ +; *************************************************************************** +; copyright : (C) 2025 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 NETMSG_RANGE_OFFS_UID = 4 +.equ NETMSG_RANGE_OFFS_FROM = 8 +.equ NETMSG_RANGE_OFFS_TO = 9 + + + + diff --git a/avr/modules/network/msg/range-r.asm b/avr/modules/network/msg/range-r.asm new file mode 100644 index 0000000..ad46e4c --- /dev/null +++ b/avr/modules/network/msg/range-r.asm @@ -0,0 +1,38 @@ +; *************************************************************************** +; copyright : (C) 2025 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 + + +; --------------------------------------------------------------------------- +; @routine NETMSG_RangeRead @global +; Read a RANGE message. +; +; @param X buffer to read from +; @return R18 command +; @return R20 range begin +; @return R21 range end +; @clobbers none + +NETMSG_Range_Read: + adiw xh:xl, NETMSG_OFFS_CMD + ld r18, X ; command + adiw xh:xl, NETMSG_RANGE_OFFS_FROM-NETMSG_OFFS_CMD ; skip src addr and uid + ld r20, X+ ; range from + ld r21, X ; range to + sbiw xh:xl, NETMSG_RANGE_OFFS_TO ; back to msg begin + ret +; @end + + + diff --git a/avr/modules/network/msg/range-w.asm b/avr/modules/network/msg/range-w.asm new file mode 100644 index 0000000..1511da4 --- /dev/null +++ b/avr/modules/network/msg/range-w.asm @@ -0,0 +1,44 @@ +; *************************************************************************** +; copyright : (C) 2025 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. * +; *************************************************************************** + + +; --------------------------------------------------------------------------- +; @routine NETMSG_Range_Write +; +; @param Y pointer to device to write msg for +; @param X pointer to buffer to write to +; @param R18 command +; @param R20 range begin +; @param R21 range end +; @clobbers R16, R18 (R17, R19, R20, R21, Z) + +NETMSG_Range_Write: + ldi r16, 0xff + st X+, r16 ; dest address + ldi r16, 8 ; msg code+src address+6 payload bytes + st X+, r16 ; msg len + st X+, r18 ; msg code + ldd r16, Y+NET_IFACE_OFFS_ADDRESS + st X+, r16 ; src address + push r20 + push r21 + rcall NETMSG_Common_AddUidToBuffer ; (R16, R18, R19, R20, R21) + pop r21 + pop r20 + st X+, r20 ; range begin + st X+, r21 ; range end + + sbiw xh:xl, 10 ; go back to beginning of message (1 byte dst addr, 1 byte length, 8 bytes payload) + rcall NETMSG_CalcAndAddChecksumByte ; (R16, R17, R18, R19, R20, X) + sbiw xh:xl, 11 ; go back to beginning of message (1 byte dst addr, 1 byte length, 8 bytes payload, 1 byte crc) + ret +; @end + + +