Skip to content

Commit

Permalink
[Core]: Made preferred address optional
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ad3154 committed Feb 22, 2024
1 parent 212ffdb commit 9123c0c
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ namespace isobus
/// @returns A shared pointer to an InternalControlFunction object created with the parameters passed in
static std::shared_ptr<InternalControlFunction> 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<InternalControlFunction> 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
Expand Down
28 changes: 23 additions & 5 deletions isobus/src/can_address_claim_state_machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<unsigned int> distribution(0, 255);
m_randomClaimDelay_ms = distribution(generator) * 0.6f; // Defined by ISO part 5
Expand Down Expand Up @@ -143,9 +148,16 @@ namespace isobus

if (SystemTiming::time_expired_ms(m_timestamp_ms, addressContentionTime_ms + m_randomClaimDelay_ms))
{
std::shared_ptr<ControlFunction> deviceAtOurPreferredAddress = CANNetworkManager::CANNetwork.get_control_function(m_portIndex, m_preferredAddress, {});
std::shared_ptr<ControlFunction> 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);
Expand All @@ -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);
}
Expand Down Expand Up @@ -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,
Expand Down
5 changes: 5 additions & 0 deletions isobus/src/can_internal_control_function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ namespace isobus
return controlFunction;
}

std::shared_ptr<InternalControlFunction> 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
Expand Down
2 changes: 1 addition & 1 deletion test/address_claim_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::uint8_t>(NAME::Function::SeatControl));
auto firstPartneredSecondECU = PartneredControlFunction::create(0, { filterSecond });
Expand Down

0 comments on commit 9123c0c

Please sign in to comment.