debounce updates

This commit is contained in:
John Wellbelove 2026-11-01 19:11:27 +00:00
parent fa8e897237
commit 9236f8f313
4 changed files with 155 additions and 55 deletions

View File

@ -60,8 +60,7 @@ namespace etl
/// Constructor.
//*************************************************************************
debounce_value_base(value_type initial_value)
: value(initial_value)
, last_value(initial_value)
: last_value(initial_value)
, count(0)
, state(Unstable)
, notification(nullptr)
@ -71,7 +70,7 @@ namespace etl
//*************************************************************************
/// Adds a new value.
/// If the value has changed, the counter is reset and the value is marked as unstable.
/// Returns 'true' if the value is stable.
/// Returns 'true' if the value has changed.
//*************************************************************************
bool add(value_type value, count_type stable_count)
{
@ -108,7 +107,7 @@ namespace etl
last_value = value;
return is_stable();
return has_changed();
}
//*************************************************************************
@ -133,7 +132,7 @@ namespace etl
//*************************************************************************
value_type get() const
{
return value;
return last_value;
}
//*************************************************************************
@ -163,7 +162,6 @@ namespace etl
Changed = 2
};
value_type value;
value_type last_value;
count_type count;
notification_type* notification;
@ -171,51 +169,7 @@ namespace etl
};
} // namespace private_debounce_value
template <typename TValue, typename TCount, typename TTag>
class debounce_value;
//*************************************************************************
/// A debounced for a value.
/// The debounced will only change its value if the new value has been stable for a given number of calls.
/// Compile-time stable count.
//*************************************************************************
template <typename TValue, typename TCount, TCount Stable_Count>
class debounce_value<TValue, TCount, etl::integral_constant<TCount, Stable_Count>> // (2) compile-time specialization
: public private_debounce_value::debounce_value_base<TValue, TCount>
{
public:
using value_type = typename private_debounce_value::debounce_value_base<TValue, TCount>::value_type;
using count_type = typename private_debounce_value::debounce_value_base<TValue, TCount>::count_type;
//*************************************************************************
/// Constructor.
//*************************************************************************
explicit debounce_value(value_type initial_value)
: private_debounce_value::debounce_value_base<TValue, TCount>(initial_value)
{
}
//*************************************************************************
/// Adds a new value to the debounced.
/// If the value has changed, the counter is reset and the debounced is marked as unstable.
//*************************************************************************
bool add(value_type value)
{
return private_debounce_value::debounce_value_base<TValue, TCount>::add(value, Stable_Count);
}
};
//*************************************************************************
/// A debounced for a value.
/// The debounced will only change its value if the new value has been stable for a given number of calls.
/// Runtime stable count.
//*************************************************************************
struct debounce_runtime_tag
{
};
template <typename TValue, typename TCount = uint16_t, typename TTag = debounce_runtime_tag>
template <typename TValue, typename TCount>
class debounce_value : public private_debounce_value::debounce_value_base<TValue, TCount>
{
public:

View File

@ -30,6 +30,8 @@ SOFTWARE.
#include "etl/debounce_value.h"
#include <vector>
namespace
{
uint8_t notification_value = 0;
@ -46,7 +48,8 @@ namespace
SUITE(test_debounce)
{
TEST(test_debounce_value_runtime)
//*************************************************************************
TEST(test_debounce_value)
{
const uint8_t Initial_Value = 1;
const uint8_t Stable_Count = 4;
@ -81,12 +84,13 @@ namespace
CHECK_TRUE(value.add(2));
CHECK_TRUE(value.is_stable());
CHECK_TRUE(value.has_changed());
CHECK_EQUAL(2, value.get());
// Notified.
CHECK_EQUAL(2, notification_value);
// Still stable.
CHECK_TRUE(value.add(2));
CHECK_FALSE(value.add(2));
CHECK_TRUE(value.is_stable());
CHECK_FALSE(value.has_changed());
@ -112,14 +116,148 @@ namespace
CHECK_TRUE(value.add(3));
CHECK_TRUE(value.is_stable());
CHECK_TRUE(value.has_changed());
CHECK_EQUAL(3, value.get());
// Notified.
CHECK_EQUAL(3, notification_value);
// Stable.
CHECK_TRUE(value.add(3));
CHECK_FALSE(value.add(3));
CHECK_TRUE(value.is_stable());
CHECK_FALSE(value.has_changed());
}
//*************************************************************************
TEST(test_debounce_value_modify_stable_count)
{
const uint8_t Initial_Value = 1;
const uint8_t Stable_Count = 4;
etl::debounce_value<uint8_t, uint8_t> value(Initial_Value, Stable_Count);
value.set_notification(notification);
notification_value = 0;
CHECK_FALSE(value.is_stable());
CHECK_FALSE(value.has_changed());
//*******************************
// Transition from unstable to stable.
CHECK_FALSE(value.add(2));
CHECK_FALSE(value.is_stable());
CHECK_FALSE(value.has_changed());
CHECK_FALSE(value.add(2));
CHECK_FALSE(value.is_stable());
CHECK_FALSE(value.has_changed());
CHECK_FALSE(value.add(2));
CHECK_FALSE(value.is_stable());
CHECK_FALSE(value.has_changed());
// Not notified yet.
CHECK_EQUAL(0, notification_value);
// Stable & changed.
CHECK_TRUE(value.add(2));
CHECK_TRUE(value.is_stable());
CHECK_TRUE(value.has_changed());
CHECK_EQUAL(2, value.get());
// Notified.
CHECK_EQUAL(2, notification_value);
// Still stable.
CHECK_FALSE(value.add(2));
CHECK_TRUE(value.is_stable());
CHECK_FALSE(value.has_changed());
//*******************************
// Change the stable count.
value.set_stable_count(2);
//*******************************
// Transition from unstable to stable.
// Unstable.
CHECK_FALSE(value.add(3));
CHECK_FALSE(value.is_stable());
CHECK_FALSE(value.has_changed());
// Not notified yet.
CHECK_EQUAL(2, notification_value);
// Stable & changed.
CHECK_TRUE(value.add(3));
CHECK_TRUE(value.is_stable());
CHECK_TRUE(value.has_changed());
CHECK_EQUAL(3, value.get());
// Notified.
CHECK_EQUAL(3, notification_value);
// Stable.
CHECK_FALSE(value.add(3));
CHECK_TRUE(value.is_stable());
CHECK_FALSE(value.has_changed());
}
//*************************************************************************
TEST(test_debounce_value_modify_notification)
{
const uint8_t Initial_Value = 1;
const uint8_t Stable_Count = 4;
etl::debounce_value<uint8_t, uint8_t> value(Initial_Value, Stable_Count);
value.set_notification(notification);
notification_value = 0;
//*******************************
// Transition from unstable to stable.
CHECK_FALSE(value.add(2));
CHECK_FALSE(value.add(2));
CHECK_FALSE(value.add(2));
CHECK_TRUE(value.add(2));
// Notified.
CHECK_EQUAL(2, notification_value);
value.clear_notification();
//*******************************
// Transition from unstable to stable.
// Unstable.
CHECK_FALSE(value.add(3));
CHECK_FALSE(value.add(3));
CHECK_FALSE(value.add(3));
CHECK_TRUE(value.add(3));
// Not notified, so the value remains the same.
CHECK_EQUAL(2, notification_value);
}
//*************************************************************************
TEST(test_debounce_values_from_an_input)
{
std::vector<uint8_t> input = { 1, 2, 3, 3, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6 };
std::vector<uint8_t> output;
std::vector<uint8_t> expected = { 2, 3, 4, 6 };
const uint8_t Stable_Count = 3;
etl::debounce_value<uint8_t, uint8_t> value(0, Stable_Count);
for (uint8_t v : input)
{
if (value.add(v))
{
output.push_back(value.get());
}
}
CHECK_EQUAL(expected.size(), output.size());
CHECK_ARRAY_EQUAL(expected.data(), output.data(), expected.size());
}
}
} // namespace

View File

@ -10411,7 +10411,6 @@
<ClCompile Include="..\test_math_functions.cpp" />
<ClCompile Include="..\test_message.cpp" />
<ClCompile Include="..\test_message_broker.cpp" />
<ClCompile Include="..\test_notification.cpp" />
<ClCompile Include="..\test_not_null_pointer.cpp" />
<ClCompile Include="..\test_not_null_pointer_constexpr.cpp" />
<ClCompile Include="..\test_not_null_unique_pointer.cpp" />

View File

@ -1566,6 +1566,12 @@
<ClInclude Include="..\..\include\etl\format.h">
<Filter>UnitTest++\Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\include\etl\debounce_value.h">
<Filter>UnitTest++\Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\include\etl\notification.h">
<Filter>UnitTest++\Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\test_string_char.cpp">
@ -3839,6 +3845,9 @@
<ClCompile Include="..\test_vector_member_function_pointer_external_buffer.cpp">
<Filter>Tests\Containers</Filter>
</ClCompile>
<ClCompile Include="..\test_debounce_value.cpp">
<Filter>Tests\Misc</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\..\library.properties">