diff --git a/src/core/common/num_utils.hpp b/src/core/common/num_utils.hpp index 6e4b81e6c..598324098 100644 --- a/src/core/common/num_utils.hpp +++ b/src/core/common/num_utils.hpp @@ -131,6 +131,29 @@ template uint16_t ClampToUint16(UintType aValue) return static_cast(Min(aValue, static_cast(NumericLimits::kMax))); } +/** + * Returns a clamped version of given integer to a `int8_t`. + * + * If @p aValue is smaller than min value of a `int8_t`, the min value of `int8_t` is returned. + * If @p aValue is larger than max value of a `int8_t`, the max value of `int8_t` is returned. + * + * @tparam IntType The value type (MUST be `int16_t`, `int32_t`, or `int64_t`). + * + * @param[in] aValue The value to clamp. + * + * @returns The clamped version of @p aValue to `int8_t`. + * + */ +template int8_t ClampToInt8(IntType aValue) +{ + static_assert(TypeTraits::IsSame::kValue || TypeTraits::IsSame::kValue || + TypeTraits::IsSame::kValue, + "IntType must be `int16_t, `int32_t`, or `int64_t`"); + + return static_cast(Clamp(aValue, static_cast(NumericLimits::kMin), + static_cast(NumericLimits::kMax))); +} + /** * This template function performs a three-way comparison between two values. * diff --git a/src/core/thread/link_metrics.cpp b/src/core/thread/link_metrics.cpp index cfe784c4f..12e7d4a1c 100644 --- a/src/core/thread/link_metrics.cpp +++ b/src/core/thread/link_metrics.cpp @@ -812,7 +812,7 @@ int8_t ScaleRawValueToRssi(uint8_t aRawValue) value = DivideAndRoundToClosest(value, NumericLimits::kMax); value += kMinRssi; - return static_cast(value); + return ClampToInt8(value); } } // namespace LinkMetrics diff --git a/tests/unit/test_link_quality.cpp b/tests/unit/test_link_quality.cpp index 2562ec8ef..8070abe52 100644 --- a/tests/unit/test_link_quality.cpp +++ b/tests/unit/test_link_quality.cpp @@ -518,6 +518,13 @@ public: VerifyOrQuit(LinkMetrics::ScaleRssiToRawValue(1) == 255); VerifyOrQuit(LinkMetrics::ScaleRssiToRawValue(10) == 255); VerifyOrQuit(LinkMetrics::ScaleRssiToRawValue(127) == 255); + + // Test corner case of ScaleRawValueToRssi + for (uint8_t rawValue = 0; rawValue < 2; rawValue++) + { + int8_t rssi = LinkMetrics::ScaleRawValueToRssi(rawValue); + printf("\nRaw Value: %u -> RSSI : %-3d", rawValue, rssi); + } } };