From 9123c0cad8c4256f180ca6eaa608b933c1e1c045 Mon Sep 17 00:00:00 2001 From: Adrian Del Grosso <10929341+ad3154@users.noreply.github.com> Date: Wed, 21 Feb 2024 19:25:44 -0700 Subject: [PATCH] [Core]: Made preferred address optional This changes internal control functions to allow no preferred address or the null address as preferred. If no preferred address (or null) is provided and the NAME allows for arbitrary addressing, we'll just find an address in the arbitrary address range for the user. --- .../isobus/can_internal_control_function.hpp | 8 ++++++ .../src/can_address_claim_state_machine.cpp | 28 +++++++++++++++---- isobus/src/can_internal_control_function.cpp | 5 ++++ test/address_claim_tests.cpp | 2 +- 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/isobus/include/isobus/isobus/can_internal_control_function.hpp b/isobus/include/isobus/isobus/can_internal_control_function.hpp index e969e70c5..3b1060764 100644 --- a/isobus/include/isobus/isobus/can_internal_control_function.hpp +++ b/isobus/include/isobus/isobus/can_internal_control_function.hpp @@ -41,6 +41,14 @@ namespace isobus /// @returns A shared pointer to an InternalControlFunction object created with the parameters passed in static std::shared_ptr create(NAME desiredName, std::uint8_t preferredAddress, std::uint8_t CANPort); + /// @brief The factory function to construct an internal control function. + /// This version of the factory function will automatically assign the preferred address somewhere in the arbitrary address + /// range, which means your NAME must have the arbitrary address bit set. + /// @param[in] desiredName The NAME for this control function to claim as + /// @param[in] CANPort The CAN channel index for this control function to use + /// @returns A shared pointer to an InternalControlFunction object created with the parameters passed in + static std::shared_ptr create(NAME desiredName, std::uint8_t CANPort); + /// @brief Destroys this control function, by removing it from the network manager /// @param[in] expectedRefCount The expected number of shared pointers to this control function after removal /// @returns true if the control function was successfully removed from everywhere in the stack, otherwise false diff --git a/isobus/src/can_address_claim_state_machine.cpp b/isobus/src/can_address_claim_state_machine.cpp index dcb21f9b1..9f0d8e1ff 100644 --- a/isobus/src/can_address_claim_state_machine.cpp +++ b/isobus/src/can_address_claim_state_machine.cpp @@ -24,8 +24,13 @@ namespace isobus m_preferredAddress(preferredAddressValue) { assert(m_preferredAddress != BROADCAST_CAN_ADDRESS); - assert(m_preferredAddress != NULL_CAN_ADDRESS); assert(portIndex < CAN_PORT_MAXIMUM); + + if (NULL_CAN_ADDRESS == m_preferredAddress) + { + // If we don't have a preferred address, your NAME must be arbitrary address capable! + assert(m_isoname.get_arbitrary_address_capable()); + } std::default_random_engine generator; std::uniform_int_distribution distribution(0, 255); m_randomClaimDelay_ms = distribution(generator) * 0.6f; // Defined by ISO part 5 @@ -143,9 +148,16 @@ namespace isobus if (SystemTiming::time_expired_ms(m_timestamp_ms, addressContentionTime_ms + m_randomClaimDelay_ms)) { - std::shared_ptr deviceAtOurPreferredAddress = CANNetworkManager::CANNetwork.get_control_function(m_portIndex, m_preferredAddress, {}); + std::shared_ptr deviceAtOurPreferredAddress; + + if (NULL_CAN_ADDRESS != m_preferredAddress) + { + deviceAtOurPreferredAddress = CANNetworkManager::CANNetwork.get_control_function(m_portIndex, m_preferredAddress, {}); + } + // Time to find a free address - if (nullptr == deviceAtOurPreferredAddress) + if ((nullptr == deviceAtOurPreferredAddress) && + (NULL_CAN_ADDRESS != m_preferredAddress)) { // Our address is free. This is the best outcome. Claim it. set_current_state(State::SendPreferredAddressClaim); @@ -164,7 +176,8 @@ namespace isobus else { // We will move to another address if whoever is in our spot has a lower NAME - if (deviceAtOurPreferredAddress->get_NAME().get_full_name() < m_isoname.get_full_name()) + if ((nullptr == deviceAtOurPreferredAddress) || + (deviceAtOurPreferredAddress->get_NAME().get_full_name() < m_isoname.get_full_name())) { set_current_state(State::SendArbitraryAddressClaim); } @@ -199,11 +212,16 @@ namespace isobus // Search the range of generally available addresses bool addressFound = false; - for (std::uint8_t i = 128; i <= 247; i++) + for (std::uint8_t i = 128; i <= 235; i++) { if ((nullptr == CANNetworkManager::CANNetwork.get_control_function(m_portIndex, i, {})) && (send_address_claim(i))) { addressFound = true; + + if (NULL_CAN_ADDRESS == m_preferredAddress) + { + m_preferredAddress = i; + } LOG_DEBUG("[AC]: Internal control function %016llx could not use the preferred address, but has claimed address %u on channel %u", m_isoname.get_full_name(), i, diff --git a/isobus/src/can_internal_control_function.cpp b/isobus/src/can_internal_control_function.cpp index ab0768b32..c037b3686 100644 --- a/isobus/src/can_internal_control_function.cpp +++ b/isobus/src/can_internal_control_function.cpp @@ -34,6 +34,11 @@ namespace isobus return controlFunction; } + std::shared_ptr InternalControlFunction::create(NAME desiredName, std::uint8_t CANPort) + { + return create(desiredName, NULL_CAN_ADDRESS, CANPort); + } + bool InternalControlFunction::destroy(std::uint32_t expectedRefCount) { // We need to destroy the PGN request protocol before we destroy the control function diff --git a/test/address_claim_tests.cpp b/test/address_claim_tests.cpp index b4bd215a3..f38c048d3 100644 --- a/test/address_claim_tests.cpp +++ b/test/address_claim_tests.cpp @@ -46,7 +46,7 @@ TEST(ADDRESS_CLAIM_TESTS, PartneredClaim) secondName.set_function_instance(0); secondName.set_device_class_instance(0); secondName.set_manufacturer_code(69); - auto secondInternalECU2 = InternalControlFunction::create(secondName, 0x1D, 1); + auto secondInternalECU2 = InternalControlFunction::create(secondName, 1); const NAMEFilter filterSecond(NAME::NAMEParameters::FunctionCode, static_cast(NAME::Function::SeatControl)); auto firstPartneredSecondECU = PartneredControlFunction::create(0, { filterSecond });