From a2b8f783c441058d3815716f8a8098312c86d0c8 Mon Sep 17 00:00:00 2001 From: Stephan Hadinger Date: Mon, 5 Aug 2019 14:24:50 +0200 Subject: [PATCH] Removed float conversion and used changeUIntScale instead --- sonoff/support_float.ino | 37 +++++++++++++++++++++++++++++++++++ sonoff/xdrv_04_light.ino | 37 ----------------------------------- sonoff/xdrv_16_tuyadimmer.ino | 21 ++++++++------------ 3 files changed, 45 insertions(+), 50 deletions(-) diff --git a/sonoff/support_float.ino b/sonoff/support_float.ino index 6e9379a53..6fe23192d 100644 --- a/sonoff/support_float.ino +++ b/sonoff/support_float.ino @@ -371,3 +371,40 @@ float sqrt1(const float x) return u.x; } + +// +// changeUIntScale +// Change a value for range a..b to c..d, using only unsigned int math +// +// PRE-CONDITIONS (if not satisfied, you may 'halt and catch fire') +// from_min < from_max (not checked) +// to_min < to_max (not checked) +// from_min <= num <= from-max (chacked) +// POST-CONDITIONS +// to_min <= result <= to_max +// +uint16_t changeUIntScale(uint16_t inum, uint16_t ifrom_min, uint16_t ifrom_max, + uint16_t ito_min, uint16_t ito_max) { + // guard-rails + if ((ito_min >= ito_max) || (ifrom_min >= ifrom_max)) { + return ito_min; // invalid input, return arbitrary value + } + // convert to uint31, it's more verbose but code is more compact + uint32_t num = inum; + uint32_t from_min = ifrom_min; + uint32_t from_max = ifrom_max; + uint32_t to_min = ito_min; + uint32_t to_max = ito_max; + + // check source range + num = (num > from_max ? from_max : (num < from_min ? from_min : num)); + uint32_t numerator = (num - from_min) * (to_max - to_min); + uint32_t result; + if (numerator >= 0x80000000L) { + // don't do rounding as it would create an overflow + result = numerator / (from_max - from_min) + to_min; + } else { + result = (((numerator * 2) / (from_max - from_min)) + 1) / 2 + to_min; + } + return (uint32_t) (result > to_max ? to_max : (result < to_min ? to_min : result)); +} diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index dc223c327..8728f8bff 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -259,43 +259,6 @@ static uint32_t min3(uint32_t a, uint32_t b, uint32_t c) { return (a < b && a < c) ? a : (b < c) ? b : c; } -// -// changeUIntScale -// Change a value for range a..b to c..d, using only unsigned int math -// -// PRE-CONDITIONS (if not satisfied, you may 'halt and catch fire') -// from_min < from_max (not checked) -// to_min < to_max (not checked) -// from_min <= num <= from-max (chacked) -// POST-CONDITIONS -// to_min <= result <= to_max -// -uint16_t changeUIntScale(uint16_t inum, uint16_t ifrom_min, uint16_t ifrom_max, - uint16_t ito_min, uint16_t ito_max) { - // guard-rails - if ((ito_min >= ito_max) || (ifrom_min >= ifrom_max)) { - return ito_min; // invalid input, return arbitrary value - } - // convert to uint31, it's more verbose but code is more compact - uint32_t num = inum; - uint32_t from_min = ifrom_min; - uint32_t from_max = ifrom_max; - uint32_t to_min = ito_min; - uint32_t to_max = ito_max; - - // check source range - num = (num > from_max ? from_max : (num < from_min ? from_min : num)); - uint32_t numerator = (num - from_min) * (to_max - to_min); - uint32_t result; - if (numerator >= 0x80000000L) { - // don't do rounding as it would create an overflow - result = numerator / (from_max - from_min) + to_min; - } else { - result = (((numerator * 2) / (from_max - from_min)) + 1) / 2 + to_min; - } - return (uint32_t) (result > to_max ? to_max : (result < to_min ? to_min : result)); -} - // // LightStateClass // This class is an abstraction of the current light state. diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino index f2328cc83..362d85a3a 100644 --- a/sonoff/xdrv_16_tuyadimmer.ino +++ b/sonoff/xdrv_16_tuyadimmer.ino @@ -146,9 +146,8 @@ void LightSerialDuty(uint8_t duty) if (duty < 25) { duty = 25; } // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself if (Settings.flag3.tuya_show_dimmer == 0) { - if(Settings.flag3.tuya_dimmer_range_255 == 0) - { - duty = round(duty * (100. / 255.)); + if(Settings.flag3.tuya_dimmer_range_255 == 0) { + duty = changeUIntScale(duty, 0, 255, 0, 100); } AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim value=%d (id=%d)"), duty, Settings.param[P_TUYA_DIMMER_ID]); TuyaSendValue(Settings.param[P_TUYA_DIMMER_ID], duty); @@ -156,9 +155,8 @@ void LightSerialDuty(uint8_t duty) } else { tuya_ignore_dim = false; // reset flag if (Settings.flag3.tuya_show_dimmer == 0) { - if(Settings.flag3.tuya_dimmer_range_255 == 0) - { - duty = round(duty * (100. / 255.)); + if(Settings.flag3.tuya_dimmer_range_255 == 0) { + duty = changeUIntScale(duty, 0, 255, 0, 100); } AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim skipped value=%d"), duty); // due to 0 or already set } @@ -217,13 +215,10 @@ void TuyaPacketProcess(void) AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Autoconfiguring Dimmer ID %d"), tuya_buffer[6]); Settings.param[P_TUYA_DIMMER_ID] = tuya_buffer[6]; } - if(Settings.flag3.tuya_dimmer_range_255 == 0) - { - tuya_new_dim = round(tuya_buffer[13]); - } - else - { - tuya_new_dim = round(tuya_buffer[13] * (100. / 255.)); + if(Settings.flag3.tuya_dimmer_range_255 == 0) { + tuya_new_dim = (uint8_t) tuya_buffer[13]; + } else { + tuya_new_dim = changeUIntScale((uint8_t) tuya_buffer[13], 0, 255, 0, 100); } if ((power || Settings.flag3.tuya_apply_o20) && (tuya_new_dim > 0) && (abs(tuya_new_dim - Settings.light_dimmer) > 1)) { tuya_ignore_dim = true;