; *************************************************************************** ; 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. * ; *************************************************************************** ; *************************************************************************** ; defines .equ APP_NETWORK_STATE_INITIALWAIT = 0 ; initially wait .equ APP_NETWORK_STATE_NEEDADDRESS = 1 ; wait for range msgs after sending "NEEDADDRESS" .equ APP_NETWORK_STATE_CLAIMADDRESS1 = 2 ; wait for "DENYADDRESS" .equ APP_NETWORK_STATE_CLAIMADDRESS2 = 3 ; wait for "DENYADDRESS" .equ APP_NETWORK_STATE_CLAIMADDRESS3 = 4 ; wait for "DENYADDRESS" .equ APP_NETWORK_STATE_HAVEADDRESS1 = 5 ; just notify (and handle "DENYADDRESS") .equ APP_NETWORK_STATE_HAVEADDRESS2 = 6 ; just notify (and handle "DENYADDRESS") .equ APP_NETWORK_STATE_UP = 7 .equ APP_NETWORK_STATE_COUNT = 8 .equ APP_NETWORK_TIMER_100MS = 50 .equ APP_NETWORK_ADDRESS_RANGE_BEGIN = 1 .equ APP_NETWORK_ADDRESS_RANGE_END = 191 .equ APP_NETWORK_REBOOT_TIME_100MS = 20 ; *************************************************************************** ; data .dseg ; *************************************************************************** ; code .cseg ; --------------------------------------------------------------------------- ; @routine AppNetwork_Init @global ; AppNetwork_Init: rcall appNetworkResetState sec ret ; @end ; --------------------------------------------------------------------------- ; @routine AppNetwork_Fini @global ; AppNetwork_Fini: ret ; @end ; --------------------------------------------------------------------------- ; @routine AppNetwork_Every100ms @global ; AppNetwork_Every100ms: ldd r16, Y+NET_IFACE_OFFS_STATETIMER tst r16 brne AppNetwork_Every100ms_decAndJump ret AppNetwork_Every100ms_decAndJump: dec r16 std Y+NET_IFACE_OFFS_STATETIMER, r16 brne AppNetwork_Every100ms_end ldd r16, Y+NET_IFACE_OFFS_STATUS cpi r16, APP_NETWORK_STATE_COUNT brcs AppNetwork_Every100ms_jump AppNetwork_Every100ms_end: ret AppNetwork_Every100ms_jump: ldi zl, LOW(appNetworkTimerTable) ldi zh, HIGH(appNetworkTimerTable) add zl, r16 adc zh, r16 sub zh, r16 ijmp ; @end ; --------------------------------------------------------------------------- ; @routine AppNetwork_EveryDay @global ; ; @clobbers R16, R17, X AppNetwork_EveryDay: bigjmp NET_Interface_ResetStats ; (R16, R17, X) ; @end ; --------------------------------------------------------------------------- ; @routine AppNetwork_HandleMsg @global ; ; @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 cpi r16, NETMSG_CMD_REBOOT_REQUEST 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: 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: bigcall NETMSG_Address_Read ; R18=cmd, R19=addr(R18, R19) mov r16, r18 subi r16, NETMSG_CMD_NEED_ADDRESS ldi zl, LOW(appNetworkMsgTable) ldi zh, HIGH(appNetworkMsgTable) add zl, r16 adc zh, r16 sub zh, r16 ijmp AppNetwork_HandleMsg_handleRebootMsg: rcall appNetworkHandleRebootRequest ret AppNetwork_HandleMsg_handlePingMsg: #ifdef MODULES_LED_SIMPLE bigcall LedSimple_SignalId ; (R18, R19, R20) #endif rjmp appNetworkHandlePingRequest AppNetwork_HandleMsg_clcRet: clc AppNetwork_HandleMsg_end: ret ; @end ; --------------------------------------------------------------------------- ; @routine appNetworkHandleRebootRequest ; ; @param X pointer to received message appNetworkHandleRebootRequest: rcall NETMSG_RebootRequestRead brcc appNetworkHandleRebootRequest_end ; uid doesn't match ; reboot cli bigjmp BOOTLOADER_ADDR appNetworkHandleRebootRequest_end: ret ; @end appNetworkHandlePingRequest: ld r17, X lds r16, (netInterfaceData+NET_IFACE_OFFS_ADDRESS) cp r16, r17 breq appNetworkHandlePingRequest_forMe cpi r17, 0xff breq appNetworkHandlePingRequest_forMe clc rjmp appNetworkHandlePingRequest_end appNetworkHandlePingRequest_forMe: adiw xh:xl, NETMSG_OFFS_SRCADDR ld r17, X push r17 bigcall NET_Buffer_Alloc ; (R16, R17, X) pop r17 brcc appNetworkHandlePingRequest_end ; jmp on error push r16 ; buffer num mov r16, r17 ; DEST addr adiw xh:xl, 1 ldi yl, LOW(netInterfaceData) ldi yh, HIGH(netInterfaceData) bigcall NETMSG_Pong_Write ; (R16, R17, R18, R19, R20, X) sbiw xh:xl, 1 pop r16 ; buffer num bigcall NET_Interface_AddOrReleaseOutMsg ; (R16, R17, R18, X) appNetworkHandlePingRequest_end: ret appNetworkHandleReeunumRequest: push xl push xh bigcall Utils_ReadUid ; r21:r20:r19:r18=uid (r16, X) pop xh pop xl rcall NETMSG_Range_Read ; r20=range begin, r21=range end (none) ldi r16, APP_NETWORK_STATE_INITIALWAIT std Y+NET_IFACE_OFFS_STATUS, r16 cpi r18, 20 brcc appNetworkHandleReeunumRequest_setWait subi r18, -20 ; minimum 2s appNetworkHandleReeunumRequest_setWait: std Y+NET_IFACE_OFFS_STATETIMER, r18 ; use lowest byte of uid as wat time std Y+NET_IFACE_OFFS_RANGE_BEGIN, r20 std Y+NET_IFACE_OFFS_RANGE_END, r21 ret ; @end appNetworkTimerTable: rjmp appNetworkHandleStateInitialWait rjmp appNetworkHandleStateNeedAddress rjmp appNetworkHandleStateClaimAddress1 rjmp appNetworkHandleStateClaimAddress2 rjmp appNetworkHandleStateClaimAddress3 rjmp appNetworkHandleStateHaveAddress1 rjmp appNetworkHandleStateHaveAddress2 rjmp appNetworkHandleStateUp appNetworkHandleStateInitialWait: ldi r18, NETMSG_CMD_NEED_ADDRESS rjmp appNetworkSendMsgNextState appNetworkHandleStateNeedAddress: ldi r18, NETMSG_CMD_CLAIM_ADDRESS rjmp appNetworkSendMsgNextState appNetworkHandleStateClaimAddress1: ldi r18, NETMSG_CMD_CLAIM_ADDRESS rjmp appNetworkSendMsgNextState appNetworkHandleStateClaimAddress2: ldi r18, NETMSG_CMD_CLAIM_ADDRESS rjmp appNetworkSendMsgNextState appNetworkHandleStateClaimAddress3: ldi r18, NETMSG_CMD_HAVE_ADDRESS rjmp appNetworkSendMsgNextState appNetworkHandleStateHaveAddress1: ldi r18, NETMSG_CMD_HAVE_ADDRESS rjmp appNetworkSendMsgNextState appNetworkHandleStateHaveAddress2: ldi r16, APP_NETWORK_STATE_UP std Y+NET_IFACE_OFFS_STATUS, r16 ldi r16, APP_NETWORK_TIMER_100MS std Y+NET_IFACE_OFFS_STATETIMER, r16 ; store new address in IFACE and in EEPROM ldd r16, Y+NET_IFACE_OFFS_ADDRESS ldi xl, LOW(EEPROM_OFFS_COMADDR) ldi xh, HIGH(EEPROM_OFFS_COMADDR) bigcall Eeprom_WriteByteIfChanged ; write address to EEPROM (R17) appNetworkHandleStateHaveAddress2_end: ret appNetworkHandleStateUp: ldi r16, 200 ; come again after 20s (nothing to do for now, maybe add some cleanup later) std Y+NET_IFACE_OFFS_STATETIMER, r16 ret ; --------------------------------------------------------------------------- ; @routine appNetworkSendMsgNextState ; ; @param R18 msg type to send ; @clobbers R16, R19 (R17, R18, R20, R21, X) appNetworkSendMsgNextState: 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 inc r16 std Y+NET_IFACE_OFFS_STATUS, r16 ldi r16, APP_NETWORK_TIMER_100MS std Y+NET_IFACE_OFFS_STATETIMER, r16 ret appNetworkSendMsgNextState_retry: ldi r16, 1 std Y+NET_IFACE_OFFS_STATETIMER, r16 ret ; @end appNetworkMsgTable: rjmp appNetworkHandleMsgNeedAddr rjmp appNetworkHandleMsgHaveAddr rjmp appNetworkHandleMsgClaimAddr rjmp appNetworkHandleMsgDenyAddr ; --------------------------------------------------------------------------- ; @routine appNetworkHandleMsgNeedAddr ; ; @param R18 command ; @param R19 address to send appNetworkHandleMsgNeedAddr: clc ret ; @end ; --------------------------------------------------------------------------- ; @routine appNetworkHandleMsgHaveAddr ; ; @param R18 command ; @param R19 address to send appNetworkHandleMsgHaveAddr: clc ret ; @end ; --------------------------------------------------------------------------- ; @routine appNetworkHandleMsgClaimAddr ; ; @param R18 command ; @param R19 address from CLAIM_ADDRESS message appNetworkHandleMsgClaimAddr: ldd r16, Y+NET_IFACE_OFFS_ADDRESS cp r19, r16 brne appNetworkHandleMsgClaimAddr_end ; not our address ldd r16, Y+NET_IFACE_OFFS_STATUS 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 appNetworkHandleMsgClaimAddr_end: ret ; @end ; --------------------------------------------------------------------------- ; @routine appNetworkHandleMsgDenyAddr ; ; @param R18 command ; @param R19 address from DENY_ADDR message appNetworkHandleMsgDenyAddr: ; check state ldd r16, Y+NET_IFACE_OFFS_STATUS 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_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 ; 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 rcall appNetworkResetState ldi r16, 200 ; wait for 20s before trying whole process again std Y+NET_IFACE_OFFS_STATETIMER, r16 rjmp appNetworkHandleMsgDenyAddr_end appNetworkHandleMsgDenyAddr_claimNext: ; send CLAIM_ADDR for next address (new state: APP_NETWORK_STATE_NEEDADDRESS+1) 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 rjmp appNetworkSendMsgNextState appNetworkHandleMsgDenyAddr_end: ret ; @end ; --------------------------------------------------------------------------- ; @routine appNetworkSendAddrMsg ; ; @param Y pointer to device to write msg for ; @param R18 command ; @param R19 address to send ; @clobbers R16 (R17, R18, R19, R20, R21, X) appNetworkSendAddrMsg: bigcall NET_Buffer_Alloc ; (R16, R17, X) brcc appNetworkSendAddrMsg_end adiw xh:xl, 1 push r16 bigcall NETMSG_Address_Write ; (R16, R17, R18, R19, R20, R21) pop r16 sbiw xh:xl, 1 bigcall NET_Interface_AddOutgoingMsgNum ; (R17, R18, X) brcs appNetworkSendAddrMsg_end bigcall NET_Buffer_ReleaseByNum ; (R16, X) clc appNetworkSendAddrMsg_end: ret ; @end ; --------------------------------------------------------------------------- ; @routine appNetworkResetState ; ; @param Y pointer to device to write msg for ; @clobbers R16 appNetworkResetState: ldi r16, APP_NETWORK_STATE_INITIALWAIT std Y+NET_IFACE_OFFS_STATUS, r16 ldi r16, APP_NETWORK_TIMER_100MS 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 cpi r16, 0xff breq appNetworkResetState_setRangeEnd std Y+NET_IFACE_OFFS_RANGE_BEGIN, r16 std Y+NET_IFACE_OFFS_ADDRESS, r16 ; preset address from EEPROM appNetworkResetState_setRangeEnd: ldi r16, APP_NETWORK_ADDRESS_RANGE_END ; last possible address+1 std Y+NET_IFACE_OFFS_RANGE_END, r16 ret ; @end ; --------------------------------------------------------------------------- ; @routine appNetworkGetAddressFromEeprom ; ; @return R16 address from EEPROM ; @clobbers X appNetworkGetAddressFromEeprom: ldi xl, LOW(EEPROM_OFFS_COMADDR) ldi xh, HIGH(EEPROM_OFFS_COMADDR) rcall Eeprom_ReadByte ; r16=addr (none) ret ; @end