From 1c605270995d2f0bc78c89ba3189ffe88433b8f8 Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Thu, 23 Nov 2023 11:31:26 +0100 Subject: [PATCH] Berry `scale_int`, equivalent of `scale_uint` for signed integers (#20090) --- CHANGELOG.md | 1 + .../berry_tasmota/src/be_tasmota_lib.c | 2 ++ tasmota/tasmota_support/support_float.ino | 36 +++++++++++++++++-- .../xdrv_52_3_berry_tasmota.ino | 18 ++++++++++ 4 files changed, 55 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32293cd29..15e2886dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ All notable changes to this project will be documented in this file. - NeoPool store settings on unified file system (#19973) - NeoPool command ``NPBoost`` (#19973) - ESP32 Partition Wizard can be loaded dynamically (#19980) +- Berry `scale_int`, equivalent of `scale_uint` for signed integers ### Breaking Changed diff --git a/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c b/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c index e4962d731..9bd9120b7 100644 --- a/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_tasmota_lib.c @@ -34,6 +34,7 @@ extern int l_yield(bvm *vm); extern int l_delay(bvm *vm); extern int l_delay_microseconds(bvm *vm); extern int l_scaleuint(bvm *vm); +extern int l_scaleint(bvm *vm); extern int l_logInfo(bvm *vm); extern int l_loglevel(bvm *vm); extern int l_save(bvm *vm); @@ -118,6 +119,7 @@ class be_class_tasmota (scope: global, name: Tasmota) { delay, func(l_delay) delay_microseconds, func(l_delay_microseconds) scale_uint, static_func(l_scaleuint) + scale_int, static_func(l_scaleint) log, func(l_logInfo) loglevel, func(l_loglevel) save, func(l_save) diff --git a/tasmota/tasmota_support/support_float.ino b/tasmota/tasmota_support/support_float.ino index c72978a5c..ac7527302 100644 --- a/tasmota/tasmota_support/support_float.ino +++ b/tasmota/tasmota_support/support_float.ino @@ -376,8 +376,8 @@ float sqrt1(const float x) // // New version, you don't need the "to_min < to_max" precondition anymore // -// PRE-CONDITIONS (if not satisfied, you may 'halt and catch fire') -// from_min < from_max (not checked) +// PRE-CONDITIONS (if not satisfied, returns the smallest between to_min and to_max') +// from_min < from_max (checked) // from_min <= num <= from_max (checked) // POST-CONDITIONS // to_min <= result <= to_max @@ -427,6 +427,38 @@ uint16_t changeUIntScale(uint16_t inum, uint16_t ifrom_min, uint16_t ifrom_max, return (uint32_t) (result > to_max ? to_max : (result < to_min ? to_min : result)); } +// +// changeIntScale +// Change a value for range a..b to c..d, for signed ints (16 bits max to avoid overflow) +// +// PRE-CONDITIONS (if not satisfied, returns the smallest between to_min and to_max') +// from_min < from_max (checked) +// from_min <= num <= from_max (checked) +// POST-CONDITIONS +// to_min <= result <= to_max +// +int16_t changeIntScale(int16_t num, int16_t from_min, int16_t from_max, + int16_t to_min, int16_t to_max) { + + // guard-rails + if (from_min >= from_max) { + return (to_min > to_max ? to_max : to_min); // invalid input, return arbitrary value + } + int32_t from_offset = 0; + if (from_min < 0) { + from_offset = - from_min; + } + int32_t to_offset = 0; + if (to_min < 0) { + to_offset = - to_min; + } + if (to_max < (- to_offset)) { + to_offset = - to_max; + } + + return changeUIntScale(num + from_offset, from_min + from_offset, from_max + from_offset, to_min + to_offset, to_max + to_offset) - to_offset; +} + // Force a float value between two ranges, and adds or substract the range until we fit float ModulusRangef(float f, float a, float b) { if (b <= a) { return a; } // inconsistent, do what we can diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino index 498d80b15..320023b34 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_tasmota.ino @@ -409,6 +409,24 @@ extern "C" { be_raise(vm, kTypeError, nullptr); } + // Berry: tasmota.scale_int(int * 5) -> int + // + int32_t l_scaleint(struct bvm *vm); + int32_t l_scaleint(struct bvm *vm) { + int32_t top = be_top(vm); // Get the number of arguments + if (top == 5 && be_isint(vm, 1) && be_isint(vm, 2) && be_isint(vm, 3) && be_isint(vm, 4) && be_isint(vm, 5)) { + int32_t val = be_toint(vm, 1); + int32_t from_min = be_toint(vm, 2); + int32_t from_max = be_toint(vm, 3); + int32_t to_min = be_toint(vm, 4); + int32_t to_max = be_toint(vm, 5); + int32_t scaled = changeIntScale(val, from_min, from_max, to_min, to_max); + be_pushint(vm, scaled); + be_return(vm); + } + be_raise(vm, kTypeError, nullptr); + } + int32_t l_respCmnd(bvm *vm); int32_t l_respCmnd(bvm *vm) { int32_t top = be_top(vm); // Get the number of arguments