Merge branch 'development' into prerelease-14.0.0

This commit is contained in:
Theo Arends 2024-05-14 11:07:06 +02:00
commit ba2ad90384
14 changed files with 368 additions and 193 deletions

View File

@ -40,6 +40,8 @@ All notable changes to this project will be documented in this file.
- TLS Letsencrypt replace R3 CA with long-term ISRG_Root_X1 CA, which works with R3 and R10-R14 (#21352)
- GPIOViewer from v1.5.0 to v1.5.2
- ESP32 Core3 platform update from 2024.05.10 to 2024.05.11 (#21381)
- Berry `Leds` uses native WS2812 driver by default (#21406)
- Command ``Pixels`` initiates a restart before activation due to changed NeoPixelBus library (#21406)
### Fixed
- HASPmota `align` attribute and expand PNG cache (#21228)
@ -56,6 +58,7 @@ All notable changes to this project will be documented in this file.
- Avoid unwanted OTA upgrade when safeboot starts for the first time (#21360)
- Matter broken NOCStruct types preventing pairing with HA (#21365)
- jpeg compile core3 (#21387)
- Berry `gpio.dac_voltage()` (#21403)
### Removed
- LVGL disabled vector graphics (#21242)

View File

@ -40,10 +40,10 @@ This release will be supported from ESP32/Arduino library Core version **3.0.0**
Support of ESP8266 Core versions before 2.7.6 and ESP32 Core versions before 3.0.0 have been removed.
### Known issues
### Known issues with v14.0.0
Due to the change from ESP32 Arduino Core2/IDF4 to Arduino Core3/IDF5 not all functionality has been restored. The following features are known not to work on ESP32:
- Wifi Range Extender
- Wifi Range Extender [#21200](https://github.com/arendst/Tasmota/issues/21200)
## Support of TLS
@ -177,6 +177,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm
- GPIOViewer from v1.5.0 to v1.5.2
- Seriallog set to `SERIAL_LOG_LEVEL` at boot [#21363](https://github.com/arendst/Tasmota/issues/21363)
- TLS Letsencrypt replace R3 CA with long-term ISRG_Root_X1 CA, which works with R3 and R10-R14 [#21352](https://github.com/arendst/Tasmota/issues/21352)
- Command ``Pixels`` initiates a restart before activation due to changed NeoPixelBus library [#21406](https://github.com/arendst/Tasmota/issues/21406)
- Command ``EthType`` option selection [#21317](https://github.com/arendst/Tasmota/issues/21317)
- Refactor Platformio script `post_esp32.py` [#20966](https://github.com/arendst/Tasmota/issues/20966)
- SGP4x Domoticz air quality value from raw to computed [#18880](https://github.com/arendst/Tasmota/issues/18880)
@ -194,6 +195,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm
- ESP32 WiFi phy modes 11n and 11ax represented as HT20, HT40 and HE20 [#19350](https://github.com/arendst/Tasmota/issues/19350)
- berry.exe (pre-compiled for Windows) updated to latest Berry patches [#21024](https://github.com/arendst/Tasmota/issues/21024)
- Berry class `int64` made immutable [#20727](https://github.com/arendst/Tasmota/issues/20727)
- Berry `Leds` uses native WS2812 driver by default [#21406](https://github.com/arendst/Tasmota/issues/21406)
- Matter reduce memory usage when reading with wildcards [#20809](https://github.com/arendst/Tasmota/issues/20809)
- LVGL make lv_touch_3_buttons more responsive [#20728](https://github.com/arendst/Tasmota/issues/20728)
- LVGL optimize fonts and add icons [#20880](https://github.com/arendst/Tasmota/issues/20880)
@ -228,6 +230,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm
- Berry walrus bug when assigning to self [#21015](https://github.com/arendst/Tasmota/issues/21015)
- Berry `web_add_handler` called before `Webserver` is initialized [#21272](https://github.com/arendst/Tasmota/issues/21272)
- Berry `math.inf`, `math.isinf()` and fixed json ouput for `inf` and `nan` [#21304](https://github.com/arendst/Tasmota/issues/21304)
- Berry `gpio.dac_voltage()` [#21403](https://github.com/arendst/Tasmota/issues/21403)
- Matter broken NOCStruct types preventing pairing with HA [#21365](https://github.com/arendst/Tasmota/issues/21365)
- LVGL restore `lv_palette` functions [#21232](https://github.com/arendst/Tasmota/issues/21232)
- LVGL fix memory allocation of flush buffers [#21256](https://github.com/arendst/Tasmota/issues/21256)

View File

@ -33,23 +33,27 @@ class Leds : Leds_ntv
# typ:int (optional) = Type of LED, defaults to WS2812 RGB
# rmt:int (optional) = RMT hardware channel to use, leave default unless you have a good reason
def init(leds, gpio_phy, typ, rmt) # rmt is optional
import gpio
self.gamma = true # gamma is enabled by default, it should be disabled explicitly if needed
self.leds = int(leds)
self.bri = 127 # 50% brightness by default
if (gpio_phy == nil) || (gpio_phy == gpio.pin(gpio.WS2812, 0))
# use native driver
self.ctor() # no parameters
self.leds = self.pixel_count()
import light
self.bri = light.get()['bri']
else
# use pure Berry driver
self.leds = int(leds)
self.bri = 127 # 50% brightness by default
# if no GPIO, abort
if gpio_phy == nil
raise "valuer_error", "no GPIO specified for neopixelbus"
# initialize the structure
self.ctor(self.leds, gpio_phy, typ, rmt)
end
# initialize the structure
self.ctor(self.leds, gpio_phy, typ, rmt)
if self._p == nil raise "internal_error", "couldn't not initialize noepixelbus" end
# call begin
self.begin()
end
# assign RMT
@ -106,13 +110,17 @@ class Leds : Leds_ntv
end
def ctor(leds, gpio_phy, typ, rmt)
if typ == nil
typ = self.WS2812_GRB
if gpio_phy == nil
self.call_native(0) # native driver
else
if typ == nil
typ = self.WS2812_GRB
end
if rmt == nil
rmt = self.assign_rmt(gpio_phy)
end
self.call_native(0, leds, gpio_phy, typ, rmt)
end
if rmt == nil
rmt = self.assign_rmt(gpio_phy)
end
self.call_native(0, leds, gpio_phy, typ, rmt)
end
def begin()
self.call_native(1)

View File

@ -649,7 +649,7 @@ be_local_closure(Leds_clear, /* name */
********************************************************************/
be_local_closure(Leds_init, /* name */
be_nested_proto(
11, /* nstack */
12, /* nstack */
5, /* argc */
2, /* varg */
0, /* has upvals */
@ -657,47 +657,69 @@ be_local_closure(Leds_init, /* name */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[10]) { /* constants */
/* K0 */ be_nested_str(gamma),
/* K1 */ be_nested_str(leds),
/* K2 */ be_nested_str(bri),
/* K3 */ be_nested_str(valuer_error),
/* K4 */ be_nested_str(no_X20GPIO_X20specified_X20for_X20neopixelbus),
( &(const bvalue[15]) { /* constants */
/* K0 */ be_nested_str(gpio),
/* K1 */ be_nested_str(gamma),
/* K2 */ be_nested_str(pin),
/* K3 */ be_nested_str(WS2812),
/* K4 */ be_const_int(0),
/* K5 */ be_nested_str(ctor),
/* K6 */ be_nested_str(_p),
/* K7 */ be_nested_str(internal_error),
/* K8 */ be_nested_str(couldn_X27t_X20not_X20initialize_X20noepixelbus),
/* K9 */ be_nested_str(begin),
/* K6 */ be_nested_str(leds),
/* K7 */ be_nested_str(pixel_count),
/* K8 */ be_nested_str(light),
/* K9 */ be_nested_str(bri),
/* K10 */ be_nested_str(get),
/* K11 */ be_nested_str(_p),
/* K12 */ be_nested_str(internal_error),
/* K13 */ be_nested_str(couldn_X27t_X20not_X20initialize_X20noepixelbus),
/* K14 */ be_nested_str(begin),
}),
&be_const_str_init,
&be_const_str_solidified,
( &(const binstruction[26]) { /* code */
0x50140200, // 0000 LDBOOL R5 1 0
0x90020005, // 0001 SETMBR R0 K0 R5
0x60140009, // 0002 GETGBL R5 G9
0x5C180200, // 0003 MOVE R6 R1
0x7C140200, // 0004 CALL R5 1
0x90020205, // 0005 SETMBR R0 K1 R5
0x5416007E, // 0006 LDINT R5 127
0x90020405, // 0007 SETMBR R0 K2 R5
0x4C140000, // 0008 LDNIL R5
0x1C140405, // 0009 EQ R5 R2 R5
0x78160000, // 000A JMPF R5 #000C
0xB0060704, // 000B RAISE 1 K3 K4
0x8C140105, // 000C GETMET R5 R0 K5
0x881C0101, // 000D GETMBR R7 R0 K1
0x5C200400, // 000E MOVE R8 R2
0x5C240600, // 000F MOVE R9 R3
0x5C280800, // 0010 MOVE R10 R4
0x7C140A00, // 0011 CALL R5 5
0x88140106, // 0012 GETMBR R5 R0 K6
0x4C180000, // 0013 LDNIL R6
0x1C140A06, // 0014 EQ R5 R5 R6
0x78160000, // 0015 JMPF R5 #0017
0xB0060F08, // 0016 RAISE 1 K7 K8
0x8C140109, // 0017 GETMET R5 R0 K9
0x7C140200, // 0018 CALL R5 1
0x80000000, // 0019 RET 0
( &(const binstruction[43]) { /* code */
0xA4160000, // 0000 IMPORT R5 K0
0x50180200, // 0001 LDBOOL R6 1 0
0x90020206, // 0002 SETMBR R0 K1 R6
0x4C180000, // 0003 LDNIL R6
0x1C180406, // 0004 EQ R6 R2 R6
0x741A0005, // 0005 JMPT R6 #000C
0x8C180B02, // 0006 GETMET R6 R5 K2
0x88200B03, // 0007 GETMBR R8 R5 K3
0x58240004, // 0008 LDCONST R9 K4
0x7C180600, // 0009 CALL R6 3
0x1C180406, // 000A EQ R6 R2 R6
0x781A000A, // 000B JMPF R6 #0017
0x8C180105, // 000C GETMET R6 R0 K5
0x7C180200, // 000D CALL R6 1
0x8C180107, // 000E GETMET R6 R0 K7
0x7C180200, // 000F CALL R6 1
0x90020C06, // 0010 SETMBR R0 K6 R6
0xA41A1000, // 0011 IMPORT R6 K8
0x8C1C0D0A, // 0012 GETMET R7 R6 K10
0x7C1C0200, // 0013 CALL R7 1
0x941C0F09, // 0014 GETIDX R7 R7 K9
0x90021207, // 0015 SETMBR R0 K9 R7
0x7002000B, // 0016 JMP #0023
0x60180009, // 0017 GETGBL R6 G9
0x5C1C0200, // 0018 MOVE R7 R1
0x7C180200, // 0019 CALL R6 1
0x90020C06, // 001A SETMBR R0 K6 R6
0x541A007E, // 001B LDINT R6 127
0x90021206, // 001C SETMBR R0 K9 R6
0x8C180105, // 001D GETMET R6 R0 K5
0x88200106, // 001E GETMBR R8 R0 K6
0x5C240400, // 001F MOVE R9 R2
0x5C280600, // 0020 MOVE R10 R3
0x5C2C0800, // 0021 MOVE R11 R4
0x7C180A00, // 0022 CALL R6 5
0x8818010B, // 0023 GETMBR R6 R0 K11
0x4C1C0000, // 0024 LDNIL R7
0x1C180C07, // 0025 EQ R6 R6 R7
0x781A0000, // 0026 JMPF R6 #0028
0xB006190D, // 0027 RAISE 1 K12 K13
0x8C18010E, // 0028 GETMET R6 R0 K14
0x7C180200, // 0029 CALL R6 1
0x80000000, // 002A RET 0
})
)
);
@ -2061,33 +2083,40 @@ be_local_closure(Leds_ctor, /* name */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 4]) { /* constants */
/* K0 */ be_nested_str(WS2812_GRB),
/* K1 */ be_nested_str(assign_rmt),
/* K2 */ be_nested_str(call_native),
/* K3 */ be_const_int(0),
/* K0 */ be_nested_str(call_native),
/* K1 */ be_const_int(0),
/* K2 */ be_nested_str(WS2812_GRB),
/* K3 */ be_nested_str(assign_rmt),
}),
&be_const_str_ctor,
&be_const_str_solidified,
( &(const binstruction[19]) { /* code */
( &(const binstruction[26]) { /* code */
0x4C140000, // 0000 LDNIL R5
0x1C140605, // 0001 EQ R5 R3 R5
0x78160000, // 0002 JMPF R5 #0004
0x880C0100, // 0003 GETMBR R3 R0 K0
0x4C140000, // 0004 LDNIL R5
0x1C140805, // 0005 EQ R5 R4 R5
0x78160003, // 0006 JMPF R5 #000B
0x8C140101, // 0007 GETMET R5 R0 K1
0x5C1C0400, // 0008 MOVE R7 R2
0x7C140400, // 0009 CALL R5 2
0x5C100A00, // 000A MOVE R4 R5
0x8C140102, // 000B GETMET R5 R0 K2
0x581C0003, // 000C LDCONST R7 K3
0x5C200200, // 000D MOVE R8 R1
0x5C240400, // 000E MOVE R9 R2
0x5C280600, // 000F MOVE R10 R3
0x5C2C0800, // 0010 MOVE R11 R4
0x7C140C00, // 0011 CALL R5 6
0x80000000, // 0012 RET 0
0x1C140405, // 0001 EQ R5 R2 R5
0x78160003, // 0002 JMPF R5 #0007
0x8C140100, // 0003 GETMET R5 R0 K0
0x581C0001, // 0004 LDCONST R7 K1
0x7C140400, // 0005 CALL R5 2
0x70020011, // 0006 JMP #0019
0x4C140000, // 0007 LDNIL R5
0x1C140605, // 0008 EQ R5 R3 R5
0x78160000, // 0009 JMPF R5 #000B
0x880C0102, // 000A GETMBR R3 R0 K2
0x4C140000, // 000B LDNIL R5
0x1C140805, // 000C EQ R5 R4 R5
0x78160003, // 000D JMPF R5 #0012
0x8C140103, // 000E GETMET R5 R0 K3
0x5C1C0400, // 000F MOVE R7 R2
0x7C140400, // 0010 CALL R5 2
0x5C100A00, // 0011 MOVE R4 R5
0x8C140100, // 0012 GETMET R5 R0 K0
0x581C0001, // 0013 LDCONST R7 K1
0x5C200200, // 0014 MOVE R8 R1
0x5C240400, // 0015 MOVE R9 R2
0x5C280600, // 0016 MOVE R10 R3
0x5C2C0800, // 0017 MOVE R11 R4
0x7C140C00, // 0018 CALL R5 6
0x80000000, // 0019 RET 0
})
)
);

View File

@ -36,6 +36,7 @@ build_flags = ${esp_defaults.build_flags}
-Wl,--wrap=panicHandler -Wl,--wrap=xt_unhandled_exception
-Wl,--wrap=_Z11analogWritehi ; `analogWrite(unsigned char, int)` use the Tasmota version of analogWrite for deeper integration and phase control
-Wl,--wrap=ledcReadFreq ; `uint32_t ledcReadFreq(uint8_t chan)`
-Wl,--wrap=delay ; void delay(uint32_t ms)
lib_ignore =
HTTPUpdateServer
USB

View File

@ -1122,6 +1122,8 @@ https://rya.nc/tasmota-fingerprint.html"
#ifdef ESP32
// #define USE_ESP32_WDT // Enable Watchdog for ESP32, trigger a restart if loop has not responded for 5s, and if `yield();` was not called
#define SET_ESP32_STACK_SIZE (8 * 1024) // Set the stack size for Tasmota. The default value is 8192 for Arduino, some builds might need to increase it
#ifdef SOC_TOUCH_VERSION_1 // ESP32

View File

@ -411,6 +411,10 @@ void setup(void) {
#endif // CONFIG_IDF_TARGET_ESP32
#endif // ESP32
#ifdef USE_ESP32_WDT
enableLoopWDT(); // enabled WDT Watchdog on Arduino `loop()` - must return before 5s or called `feedLoopWDT();` - included in `yield()`
#endif // USE_ESP32_WDT
RtcPreInit();
SettingsInit();

View File

@ -21,6 +21,30 @@ extern "C" {
extern struct rst_info resetInfo;
}
/*********************************************************************************************\
* ESP32 Watchdog
\*********************************************************************************************/
#ifdef ESP32
// Watchdog - yield() resets the watchdog
#ifdef USE_ESP32_WDT
extern "C"
void yield(void) {
vPortYield(); // was originally in `__yield`
feedLoopWDT();
}
// patching delay(uint32_t ms)
extern "C" void __real_delay(uint32_t ms);
extern "C" void __wrap_delay(uint32_t ms) {
__real_delay(ms);
feedLoopWDT();
}
#endif // USE_ESP32_WDT
#endif // ESP32
/*********************************************************************************************\
* Watchdog extension (https://github.com/esp8266/Arduino/issues/1532)
\*********************************************************************************************/

View File

@ -384,7 +384,7 @@ bool ArtNetStart(void) {
if ((Settings->light_pixels != artnet_conf.rows * artnet_conf.cols + artnet_conf.offs) || (Settings->light_rotation != 0)) {
Settings->light_pixels = artnet_conf.rows * artnet_conf.cols + artnet_conf.offs;
Settings->light_rotation = 0;
Ws2812ReinitStrip();
Ws2812InitStrip();
} else {
Ws2812Clear();
}

View File

@ -110,6 +110,7 @@ void BrTimeoutStart(void) {
if (0 == berry.timeout) {
berry.timeout = 1; // rare case when value accidentally computes to zero
}
yield();
}
void BrTimeoutYield(void) {

View File

@ -40,6 +40,9 @@
extern "C" {
#include "berry/include/be_gpio_defines.h"
#if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S2)
#include "soc/dac_channel.h"
#endif // defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S2)
// virtual member
int gp_member(bvm *vm);
@ -62,44 +65,11 @@ extern "C" {
// synthetic mode
if (-1 == mode) {
// DAC
#if defined(CONFIG_IDF_TARGET_ESP32)
if (25 == pin || 26 == pin) {
#if ESP_IDF_VERSION_MAJOR >= 5
dac_oneshot_handle_t channel_handle;
const dac_channel_t channel = (25 == pin) ? DAC_CHAN_0 : DAC_CHAN_1;
dac_oneshot_config_t channel_cfg = {
.chan_id = channel,
};
esp_err_t err = dac_oneshot_new_channel(&channel_cfg, &channel_handle);
#else
dac_channel_t channel = (25 == pin) ? DAC_CHANNEL_1 : DAC_CHANNEL_2;
esp_err_t err = dac_output_enable(channel);
#endif
if (err) {
be_raisef(vm, "value_error", "Error: dac_output_enable(%i) -> %i", channel, err);
}
} else {
be_raise(vm, "value_error", "DAC only supported on GPIO25-26");
}
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
if (17 == pin || 18 == pin) {
#if ESP_IDF_VERSION_MAJOR >= 5
dac_oneshot_handle_t channel_handle;
const dac_channel_t channel = (17 == pin) ? DAC_CHAN_0 : DAC_CHAN_1;
dac_oneshot_config_t channel_cfg = {
.chan_id = channel,
};
esp_err_t err = dac_oneshot_new_channel(&channel_cfg, &channel_handle);
#else
dac_channel_t channel = (17 == pin) ? DAC_CHANNEL_1 : DAC_CHANNEL_2;
esp_err_t err = dac_output_enable(channel);
#endif
if (err) {
be_raisef(vm, "value_error", "Error: dac_output_enable(%i) -> %i", channel, err);
}
} else {
be_raise(vm, "value_error", "DAC only supported on GPIO17-18");
#if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S2)
if (pin != DAC_CHAN0_GPIO_NUM && pin != DAC_CHAN1_GPIO_NUM) {
be_raisef(vm, "value_error", "DAC only supported on GPIO%i-%i", DAC_CHAN0_GPIO_NUM, DAC_CHAN1_GPIO_NUM);
}
// DEPRECATED - this is not needed anymore, the GPIO is configured when first write occurs
#else
be_raise(vm, "value_error", "DAC unsupported in this chip");
#endif
@ -143,59 +113,26 @@ extern "C" {
int gp_dac_voltage(bvm *vm);
int gp_dac_voltage(bvm *vm) {
#if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S2)
int32_t argc = be_top(vm); // Get the number of arguments
if (argc == 2 && be_isint(vm, 1) && be_isint(vm, 2)) {
if (argc == 2 && be_isint(vm, 1) && be_isnumber(vm, 2)) {
int32_t pin = be_toint(vm, 1);
int32_t mV = be_toint(vm, 2);
if (pin != DAC_CHAN0_GPIO_NUM && pin != DAC_CHAN1_GPIO_NUM) {
be_raisef(vm, "value_error", "DAC only supported on GPIO%i-%i", DAC_CHAN0_GPIO_NUM, DAC_CHAN1_GPIO_NUM);
}
if (mV < 0) { mV = 0; }
uint32_t dac_value = changeUIntScale(mV, 0, 3300, 0, 255); // convert from 0..3300 ms to 0..255
#if defined(CONFIG_IDF_TARGET_ESP32)
if (25 == pin || 26 == pin) {
#if ESP_IDF_VERSION_MAJOR >= 5
dac_oneshot_handle_t channel_handle;
const dac_channel_t channel = (25 == pin) ? DAC_CHAN_0 : DAC_CHAN_1;
dac_oneshot_config_t channel_cfg = {
.chan_id = channel,
};
esp_err_t err = dac_oneshot_new_channel(&channel_cfg, &channel_handle);
#else
dac_channel_t channel = (25 == pin) ? DAC_CHANNEL_1 : DAC_CHANNEL_2;
esp_err_t err = dac_output_voltage(channel, dac_value);
// err = dac_output_enable(channel);
#endif
if (err) {
be_raisef(vm, "internal_error", "Error: esp_err_tdac_output_voltage(%i, %i) -> %i", channel, dac_value, err);
}
} else {
be_raise(vm, "value_error", "DAC only supported on GPIO25-26");
if (!dacWrite(pin, dac_value)) {
be_raise(vm, "value_error", "Error: dacWrite failed");
}
#elif defined(CONFIG_IDF_TARGET_ESP32S2)
if (17 == pin || 18 == pin) {
#if ESP_IDF_VERSION_MAJOR >= 5
dac_oneshot_handle_t channel_handle;
const dac_channel_t channel = (17 == pin) ? DAC_CHAN_0 : DAC_CHAN_1;
dac_oneshot_config_t channel_cfg = {
.chan_id = channel,
};
esp_err_t err = dac_oneshot_new_channel(&channel_cfg, &channel_handle);
#else
dac_channel_t channel = (17 == pin) ? DAC_CHANNEL_1 : DAC_CHANNEL_2;
esp_err_t err = dac_output_voltage(channel, dac_value);
// err = dac_output_enable(channel);
#endif
if (err) {
be_raisef(vm, "internal_error", "Error: esp_err_tdac_output_voltage(%i, %i) -> %i", channel, dac_value, err);
}
} else {
be_raise(vm, "value_error", "DAC only supported on GPIO17-18");
}
#else
be_raise(vm, "value_error", "DAC unsupported in this chip");
#endif
be_pushint(vm, changeUIntScale(dac_value, 0, 255, 0, 3300));
be_pushint(vm, changeUIntScale(dac_value, 0, 255, 0, 3300)); // convert back to mV to indicate the actual value
be_return(vm);
}
be_raise(vm, kTypeError, nullptr);
#else // defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S2)
be_raise(vm, "value_error", "DAC unsupported in this chip");
#endif // defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S2)
}
// Tasmota specific

View File

@ -41,6 +41,23 @@ typedef NeoPixelBus<NeoGrbFeature, NeoEsp32RmtN800KbpsMethod> neopixel_ws2812_gr
typedef NeoPixelBus<NeoGrbwFeature, NeoEsp32RmtNSk6812Method> neopixel_sk6812_grbw_t;
#endif
/*********************************************************************************************\
* Functions from Tasmota WS2812 driver
*
\*********************************************************************************************/
extern void *Ws2812GetStrip(void);
extern void Ws2812Begin(void);
extern void Ws2812Show(void);
extern uint32_t Ws2812PixelsSize(void);
extern bool Ws2812CanShow(void);
extern bool Ws2812IsDirty(void);
extern void Ws2812Dirty(void);
extern uint8_t * Ws2812Pixels(void);
extern size_t Ws2812PixelSize(void);
extern size_t Ws2812PixelCount(void);
extern void Ws2812ClearTo(uint8_t r, uint8_t g, uint8_t b, uint8_t w, int32_t from, int32_t to);
extern void Ws2812SetPixelColor(uint32_t idx, uint8_t r, uint8_t g, uint8_t b, uint8_t w);
extern uint32_t Ws2812GetPixelColor(uint32_t idx);
/*********************************************************************************************\
* Native functions mapped to Berry functions
@ -82,7 +99,7 @@ extern "C" {
be_getmember(vm, 1, "_t");
int32_t type = be_toint(vm, -1);
be_pop(vm, 1);
if (type <= 0 || type >= neopixel_type_end) {
if (type < 0 || type >= neopixel_type_end) {
be_raise(vm, "internal_error", "invalid leds type");
}
return type;
@ -95,30 +112,46 @@ extern "C" {
int32_t cmd = be_toint(vm, 2);
if (0 == cmd) { // 00 : ctor (leds:int, gpio:int) -> void
if (!(argc >= 6 && be_isint(vm, 3) && be_isint(vm, 4) && be_isint(vm, 5) && be_isint(vm, 6))) {
if ((argc != 2) && !(argc >= 6 && be_isint(vm, 3) && be_isint(vm, 4) && be_isint(vm, 5) && be_isint(vm, 6))) {
be_raise(vm, "value_error", "bad arguments for neopixelbus:ctor");
}
int32_t leds = be_toint(vm, 3);
int32_t gpio = be_toint(vm, 4);
int32_t neopixel_type = be_toint(vm, 5);
int32_t rmt = be_toint(vm, 6);
if (neopixel_type < 1) { neopixel_type = 1; }
if (neopixel_type >= neopixel_type_end) { neopixel_type = neopixel_type_end - 1; }
if (rmt < 0) { rmt = 0; }
if (rmt >= MAX_RMT) { rmt = MAX_RMT - 1; }
int32_t leds = -1;
int32_t gpio = -1;
int32_t neopixel_type = 0;
int32_t rmt = 0;
void * strip = nullptr;
if (argc > 2) {
leds = be_toint(vm, 3);
gpio = be_toint(vm, 4);
neopixel_type = be_toint(vm, 5);
rmt = be_toint(vm, 6);
}
if (-1 == gpio) {
// if GPIO is '-1'
neopixel_type = 0;
Ws2812InitStrip(); // ensure the NeoPixelbus object is initialized, because Berry code runs before the driver is initialized
strip = Ws2812GetStrip();
} else {
// allocate a new RMT
if (neopixel_type < 1) { neopixel_type = 1; }
if (neopixel_type >= neopixel_type_end) { neopixel_type = neopixel_type_end - 1; }
if (rmt < 0) { rmt = 0; }
if (rmt >= MAX_RMT) { rmt = MAX_RMT - 1; }
switch (neopixel_type) {
case ws2812_grb: strip = new neopixel_ws2812_grb_t(leds, gpio, (NeoBusChannel) rmt);
break;
case sk6812_grbw: strip = new neopixel_sk6812_grbw_t(leds, gpio, (NeoBusChannel) rmt);
break;
}
}
// store type in attribute `_t`
be_pushint(vm, neopixel_type);
be_setmember(vm, 1, "_t");
be_pop(vm, 1);
void * strip = nullptr;
switch (neopixel_type) {
case ws2812_grb: strip = new neopixel_ws2812_grb_t(leds, gpio, (NeoBusChannel) rmt);
break;
case sk6812_grbw: strip = new neopixel_sk6812_grbw_t(leds, gpio, (NeoBusChannel) rmt);
break;
}
be_pushcomptr(vm, (void*) strip);
be_setmember(vm, 1, "_p");
be_pop(vm, 1);
@ -130,11 +163,14 @@ extern "C" {
// initialize all possible variants
neopixel_ws2812_grb_t * s_ws2812_grb = (leds_type == ws2812_grb) ? (neopixel_ws2812_grb_t*) s : nullptr;
neopixel_sk6812_grbw_t * s_sk6812_grbw = (leds_type == sk6812_grbw) ? (neopixel_sk6812_grbw_t*) s : nullptr;
// detect native driver
bool native = (leds_type == 0);
be_pushnil(vm); // push a default `nil` return value
switch (cmd) {
case 1: // # 01 : begin void -> void
if (native) Ws2812Begin();
if (s_ws2812_grb) s_ws2812_grb->Begin();
if (s_sk6812_grbw) s_sk6812_grbw->Begin();
break;
@ -159,6 +195,7 @@ extern "C" {
}
}
uint32_t pixels_size; // number of bytes to push
if (native) { Ws2812Show(); pixels_size = Ws2812PixelsSize(); }
if (s_ws2812_grb) { s_ws2812_grb->Show(); pixels_size = s_ws2812_grb->PixelsSize(); }
if (s_sk6812_grbw) { s_sk6812_grbw->Show(); pixels_size = s_sk6812_grbw->PixelsSize(); }
@ -168,20 +205,24 @@ extern "C" {
}
break;
case 3: // # 03 : CanShow void -> bool
if (native) be_pushbool(vm, Ws2812CanShow());
if (s_ws2812_grb) be_pushbool(vm, s_ws2812_grb->CanShow());
if (s_sk6812_grbw) be_pushbool(vm, s_sk6812_grbw->CanShow());
break;
case 4: // # 04 : IsDirty void -> bool
if (native) be_pushbool(vm, Ws2812IsDirty());
if (s_ws2812_grb) be_pushbool(vm, s_ws2812_grb->IsDirty());
if (s_sk6812_grbw) be_pushbool(vm, s_sk6812_grbw->IsDirty());
break;
case 5: // # 05 : Dirty void -> void
if (native) Ws2812Dirty();
if (s_ws2812_grb) s_ws2812_grb->Dirty();
if (s_sk6812_grbw) s_sk6812_grbw->Dirty();
break;
case 6: // # 06 : Pixels void -> bytes() (mapped to the buffer)
{
uint8_t * pixels;
if (native) pixels = Ws2812Pixels();
if (s_ws2812_grb) pixels = s_ws2812_grb->Pixels();
if (s_sk6812_grbw) pixels = s_sk6812_grbw->Pixels();
@ -189,10 +230,12 @@ extern "C" {
}
break;
case 7: // # 07 : PixelSize void -> int
if (native) be_pushint(vm, Ws2812PixelSize());
if (s_ws2812_grb) be_pushint(vm, s_ws2812_grb->PixelSize());
if (s_sk6812_grbw) be_pushint(vm, s_sk6812_grbw->PixelSize());
break;
case 8: // # 08 : PixelCount void -> int
if (native) be_pushint(vm, Ws2812PixelCount());
if (s_ws2812_grb) be_pushint(vm, s_ws2812_grb->PixelCount());
if (s_sk6812_grbw) be_pushint(vm, s_sk6812_grbw->PixelCount());
break;
@ -204,11 +247,16 @@ extern "C" {
uint8_t g = (rgbw >> 8) & 0xFF;
uint8_t b = (rgbw ) & 0xFF;
if (argc >= 5 && be_isint(vm, 4) && be_isint(vm, 5)) {
uint32_t from = be_toint(vm, 4);
uint32_t len = be_toint(vm, 5);
int32_t from = be_toint(vm, 4);
int32_t len = be_toint(vm, 5);
if (from < 0) { from = 0; }
if (len < 0) { len = 0; }
if (native) Ws2812ClearTo(r, g, b, w, from, from + len - 1);
if (s_ws2812_grb) s_ws2812_grb->ClearTo(RgbColor(r, g, b), from, from + len - 1);
if (s_sk6812_grbw) s_sk6812_grbw->ClearTo(RgbwColor(r, g, b, w), from, from + len - 1);
} else {
if (native) Ws2812ClearTo(r, g, b, w, -1, -1);
if (s_ws2812_grb) s_ws2812_grb->ClearTo(RgbColor(r, g, b));
if (s_sk6812_grbw) s_sk6812_grbw->ClearTo(RgbwColor(r, g, b, w));
}
@ -222,6 +270,7 @@ extern "C" {
uint8_t r = (rgbw >> 16) & 0xFF;
uint8_t g = (rgbw >> 8) & 0xFF;
uint8_t b = (rgbw ) & 0xFF;
if (native) Ws2812SetPixelColor(idx, r, g, b, w);
if (s_ws2812_grb) s_ws2812_grb->SetPixelColor(idx, RgbColor(r, g, b));
if (s_sk6812_grbw) s_sk6812_grbw->SetPixelColor(idx, RgbwColor(r, g, b, w));
}
@ -229,15 +278,17 @@ extern "C" {
case 11: // # 11 : GetPixelColor (idx:int) -> color:??
{
int32_t idx = be_toint(vm, 3);
RgbColor rgb;
if (native) {
be_pushint(vm, Ws2812GetPixelColor(idx));
}
if (s_ws2812_grb) {
RgbColor rgb = s_ws2812_grb->GetPixelColor(idx);
be_pushint(vm, (rgb.R << 16) | (rgb.G << 8) | rgb.B);
}
if (s_sk6812_grbw) {
RgbwColor rgbw = s_sk6812_grbw->GetPixelColor(idx);
be_pushint(vm, (rgbw.W << 24) | (rgb.R << 16) | (rgb.G << 8) | rgb.B);
be_pushint(vm, (rgbw.W << 24) | (rgbw.R << 16) | (rgbw.G << 8) | rgbw.B);
}
}
break;

View File

@ -404,7 +404,8 @@ extern "C" {
// ESP object
int32_t l_yield(bvm *vm);
int32_t l_yield(bvm *vm) {
return be_call_c_func(vm, (void*) &BrTimeoutYield, NULL, "-");
BrTimeoutYield();
be_return_nil(vm);
}
// Berry: tasmota.scale_uint(int * 5) -> int

View File

@ -681,16 +681,10 @@ void Ws2812ShowScheme(void)
}
}
bool Ws2812ReinitStrip(void)
bool Ws2812InitStrip(void)
{
if (strip != nullptr) {
Ws2812Clear();
if (!strip->CanShow()) {
// we're doing DMA, so wait for a decent amount of time
delay(10);
}
delete strip;
strip = nullptr;
return true;
}
#if (USE_WS2812_HARDWARE == NEO_HW_P9813)
@ -711,7 +705,7 @@ bool Ws2812ReinitStrip(void)
void Ws2812ModuleSelected(void)
{
if (Ws2812ReinitStrip()) {
if (Ws2812InitStrip()) {
Ws2812.scheme_offset = Light.max_scheme +1;
Light.max_scheme += WS2812_SCHEMES;
@ -728,6 +722,117 @@ void Ws2812ModuleSelected(void)
}
}
#ifdef ESP32
#ifdef USE_BERRY
/********************************************************************************************/
// Callbacks for Berry driver
//
// Since we dont' want to export all the template stuff, we need to encapsulate the calls
// in plain functions
//
void *Ws2812GetStrip(void) {
return strip;
}
void Ws2812Begin(void) {
if (strip) { strip->Begin(); }
}
void Ws2812Show(void) {
if (strip) { strip->Show(); }
}
uint32_t Ws2812PixelsSize(void) {
if (strip) { return strip->PixelCount(); }
return 0;
}
bool Ws2812CanShow(void) {
if (strip) { return strip->CanShow(); }
return false;
}
bool Ws2812IsDirty(void) {
if (strip) { return strip->IsDirty(); }
return false;
}
void Ws2812Dirty(void) {
if (strip) { strip->Dirty(); }
}
uint8_t * Ws2812Pixels(void) {
if (strip) { return strip->Pixels(); }
return nullptr;
}
size_t Ws2812PixelSize(void) {
if (strip) { return strip->PixelSize(); }
return 0;
}
size_t Ws2812PixelCount(void) {
if (strip) { return strip->PixelCount(); }
return 0;
}
void Ws2812ClearTo(uint8_t r, uint8_t g, uint8_t b, uint8_t w, int32_t from, int32_t to) {
#if (USE_WS2812_CTYPE > NEO_3LED)
RgbwColor lcolor;
lcolor.W = w;
#else
RgbColor lcolor;
#endif
lcolor.R = r;
lcolor.G = g;
lcolor.B = b;
if (strip) {
if (from < 0) {
strip->ClearTo(lcolor);
} else {
strip->ClearTo(lcolor, from, to);
}
}
}
void Ws2812SetPixelColor(uint32_t idx, uint8_t r, uint8_t g, uint8_t b, uint8_t w)
{
#if (USE_WS2812_CTYPE > NEO_3LED)
RgbwColor lcolor;
lcolor.W = w;
#else
RgbColor lcolor;
#endif
lcolor.R = r;
lcolor.G = g;
lcolor.B = b;
if (strip) {
strip->SetPixelColor(idx, lcolor);
}
}
uint32_t Ws2812GetPixelColor(uint32_t idx) {
#if (USE_WS2812_CTYPE > NEO_3LED)
RgbwColor lcolor;
#else
RgbColor lcolor;
#endif
if (strip) {
lcolor = strip->GetPixelColor(idx);
#if (USE_WS2812_CTYPE > NEO_3LED)
return (lcolor.W << 24) | (lcolor.R << 16) | (lcolor.G << 8) | lcolor.B;
#else
return (lcolor.R << 16) | (lcolor.G << 8) | lcolor.B;
#endif
}
return 0;
}
#endif // ESP32
#endif // USE_BERRY
/********************************************************************************************/
void CmndLed(void)
@ -756,10 +861,16 @@ void CmndLed(void)
void CmndPixels(void)
{
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= WS2812_MAX_LEDS)) {
/*
Settings->light_pixels = XdrvMailbox.payload;
Settings->light_rotation = 0;
Ws2812ReinitStrip();
Ws2812ReinitStrip(); -- does not work with latest NeoPixelBus driver
Light.update = true;
*/
Ws2812Clear(); // Clear all known pixels
Settings->light_pixels = XdrvMailbox.payload;
Settings->light_rotation = 0;
TasmotaGlobal.restart_flag = 2; // reboot instead
}
ResponseCmndNumber(Settings->light_pixels);
}
@ -768,7 +879,7 @@ void CmndStepPixels(void)
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 255)) {
Settings->light_step_pixels = (XdrvMailbox.payload > WS2812_MAX_LEDS) ? WS2812_MAX_LEDS : XdrvMailbox.payload;
Ws2812ReinitStrip();
// Ws2812ReinitStrip(); -- not sure it's actually needed
Light.update = true;
}
ResponseCmndNumber(Settings->light_step_pixels);