diff --git a/CHANGELOG.md b/CHANGELOG.md index ad365fbc21db..2ce0e92f5150 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file. ### Added - Support for Shelly PlusPMMini, Plus1Mini and Plus1PMMini - Matter support for Virtual Devices controllable via Rules or Berry (#19520) +- Berry read and write Counters ### Breaking Changed diff --git a/lib/libesp32/berry_tasmota/src/be_gpio_lib.c b/lib/libesp32/berry_tasmota/src/be_gpio_lib.c index 592861b9c817..e8334753913b 100644 --- a/lib/libesp32/berry_tasmota/src/be_gpio_lib.c +++ b/lib/libesp32/berry_tasmota/src/be_gpio_lib.c @@ -15,6 +15,9 @@ extern int gp_pin_mode(bvm *vm); extern int gp_digital_write(bvm *vm); extern int gp_digital_read(bvm *vm); extern int gp_dac_voltage(bvm *vm); +extern int gp_counter_read(bvm *vm); +extern int gp_counter_set(bvm *vm); +extern int gp_counter_add(bvm *vm); extern int gp_pin_used(bvm *vm); extern int gp_pin(bvm *vm); @@ -31,6 +34,9 @@ module gpio (scope: global) { digital_write, func(gp_digital_write) digital_read, func(gp_digital_read) dac_voltage, func(gp_dac_voltage) + counter_read, func(gp_counter_read) + counter_set, func(gp_counter_set) + counter_add, func(gp_counter_add) pin_used, func(gp_pin_used) pin, func(gp_pin) diff --git a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_gpio.ino b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_gpio.ino index a8815f798eb5..7e514622af14 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_gpio.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_52_3_berry_gpio.ino @@ -241,6 +241,67 @@ extern "C" { analogWritePhase(pin, duty, hpoint); } + // gpio.counter_read(counter:int) -> int or nil + // + // Read counter value, or return nil if counter is not used + int gp_counter_read(bvm *vm); + int gp_counter_read(bvm *vm) { +#ifdef USE_COUNTER + int32_t argc = be_top(vm); // Get the number of arguments + if (argc >= 1 && be_isint(vm, 1)) { + int32_t counter = be_toint(vm, 1); + + // is `index` refering to a counter? + if (CounterPinConfigured(counter)) { + be_pushint(vm, CounterPinRead(counter)); + be_return(vm); + } else { + be_return_nil(vm); + } + } + be_raise(vm, kTypeError, nullptr); +#else + be_return_nil(vm); +#endif + } + + + int gp_counter_set_add(bvm *vm, bool add) { +#ifdef USE_COUNTER + int32_t argc = be_top(vm); // Get the number of arguments + if (argc >= 2 && be_isint(vm, 1) && be_isint(vm, 2)) { + int32_t counter = be_toint(vm, 1); + int32_t value = be_toint(vm, 2); + + // is `index` refering to a counter? + if (CounterPinConfigured(counter)) { + be_pushint(vm, CounterPinSet(counter, value, add)); + be_return(vm); + } else { + be_return_nil(vm); + } + } + be_raise(vm, kTypeError, nullptr); +#else + be_return_nil(vm); +#endif + } + + // gpio.counter_set(counter:int, value:int) -> int or nil + // + // Set the counter value, return the actual value, or return nil if counter is not used + int gp_counter_set(bvm *vm); + int gp_counter_set(bvm *vm) { + return gp_counter_set_add(vm, false); + } + + // gpio.counter_add(counter:int, value:int) -> int or nil + // + // Add to the counter value, return the actual value, or return nil if counter is not used + int gp_counter_add(bvm *vm); + int gp_counter_add(bvm *vm) { + return gp_counter_set_add(vm, true); + } } #endif // USE_BERRY diff --git a/tasmota/tasmota_xsns_sensor/xsns_01_counter.ino b/tasmota/tasmota_xsns_sensor/xsns_01_counter.ino index 183fbb62c21a..245055c609cc 100644 --- a/tasmota/tasmota_xsns_sensor/xsns_01_counter.ino +++ b/tasmota/tasmota_xsns_sensor/xsns_01_counter.ino @@ -127,6 +127,40 @@ bool CounterPinState(void) return false; } +// is this GPIO configured as a counter +// this encapsulates the logic and avoids exposing internals to Berry +bool CounterPinConfigured(int32_t counter) { + if ((counter > 0) && (counter <= MAX_COUNTERS) && (PinUsed(GPIO_CNTR1, counter - 1))) { + return true; + } else { + return false; + } +} + +// return counter value for this GPIO +// this encapsulates the logic and avoids exposing internals to Berry +uint32_t CounterPinRead(int32_t counter) { + if (CounterPinConfigured(counter)) { + return RtcSettings.pulse_counter[counter - 1]; + } + return 0; +} + +// set the value, add offset if `add` is true, return value +// this encapsulates the logic and avoids exposing internals to Berry +uint32_t CounterPinSet(int32_t counter, int32_t value, bool add) { + if (CounterPinConfigured(counter)) { + if (add) { + RtcSettings.pulse_counter[counter - 1] += value; + } else { + RtcSettings.pulse_counter[counter - 1] = value; + } + return RtcSettings.pulse_counter[counter - 1]; + } + return 0; +} + + void CounterInit(void) {