diff --git a/firmware/util/scaled_channel.h b/firmware/util/scaled_channel.h index d8219defd9..f2b8256634 100644 --- a/firmware/util/scaled_channel.h +++ b/firmware/util/scaled_channel.h @@ -32,19 +32,30 @@ class scaled_channel : scaled_channel_base { using TSelf = scaled_channel; public: + struct IncompleteType; + constexpr scaled_channel() : m_value(static_cast(0)) { } - constexpr scaled_channel(float val) - { - val *= float(mul) / div; - if (std::is_integral_v) { - m_value = std::roundf(val); - } else { - m_value = val; - } + + // Only allow conversion directly to T when mul/div are both 1, otherwise this constructor doesn't exist and the float conversion is used. + constexpr scaled_channel(std::conditional_t val) { + m_value = val; + } + + // Scale the float in to our scaled channel + constexpr scaled_channel(std::conditional_t val) { + // If there are scale factors, it must NOT be a float. Why would you scale a float? + static_assert(std::is_integral_v); + + m_value = std::roundf(val * float(mul) / div); + } + + // Only allow conversion directly to T when mul/div are both 1, otherwise this operator doesn't exist and the float conversion is used. + constexpr operator typename std::conditional_t() const { + return m_value; } // Allow reading back out as a float (note: this may be lossy!) - constexpr operator float() const { + constexpr operator typename std::conditional_t() const { return m_value * (float(div) / mul); } @@ -56,7 +67,6 @@ public: static_assert(mul == 1 && div == 1, "Increment operator only supported for non-scaled integer types"); static_assert(std::is_integral_v, "Increment operator only supported for non-scaled integer types"); - m_value++; } diff --git a/java_console/io/src/test/java/com/rusefi/native_/JniUnitTest.java b/java_console/io/src/test/java/com/rusefi/native_/JniUnitTest.java index f1c6f284b4..b1c868bee8 100644 --- a/java_console/io/src/test/java/com/rusefi/native_/JniUnitTest.java +++ b/java_console/io/src/test/java/com/rusefi/native_/JniUnitTest.java @@ -9,7 +9,8 @@ import org.junit.Test; import java.nio.ByteBuffer; -import static com.rusefi.config.generated.Fields.*; +import static com.rusefi.config.generated.Fields.TS_FILE_VERSION; +import static com.rusefi.config.generated.Fields.engine_type_e_MRE_MIATA_NB2_MAP; import static com.rusefi.shared.FileUtil.littleEndianWrap; import static junit.framework.Assert.*; @@ -24,10 +25,7 @@ public class JniUnitTest { engineLogic.invokePeriodicCallback(); - /* - todo: fix me https://github.com/rusefi/rusefi/issues/4128 assertEquals(TS_FILE_VERSION, (int) getValue(engineLogic.getOutputs(), Sensor.FIRMWARE_VERSION)); - */ assertEquals(14.0, getValue(engineLogic.getOutputs(), Sensor.TARGET_AFR)); double veValue = getValue(engineLogic.getOutputs(), Sensor.veValue); diff --git a/unit_tests/tests/util/test_scaled_channel.cpp b/unit_tests/tests/util/test_scaled_channel.cpp index af199d0fac..2832fbcd15 100644 --- a/unit_tests/tests/util/test_scaled_channel.cpp +++ b/unit_tests/tests/util/test_scaled_channel.cpp @@ -32,3 +32,14 @@ TEST(ScaledChannel, Basic) { i2 = -11; EXPECT_FLOAT_EQ(i2, -10); // round } } + +TEST(ScaledChannel, IntegerBehavior) { + scaled_channel test; + + // Check that a round trip thru scaled_channel gets us back the same integer + uint32_t a = 20210311; + test = a; + uint32_t b = test; + + EXPECT_EQ(a, b); +}