From 7ec0c417b38869809abe07cff0acfd2034d4b333 Mon Sep 17 00:00:00 2001
From: Milenko Mitrovic
Date: Sat, 30 Oct 2021 11:19:44 +0200
Subject: [PATCH 001/355] Added support for Mi Scale V1
---
tasmota/xsns_62_esp32_mi_ble.ino | 174 ++++++++++++++++++++++++++++++-
1 file changed, 170 insertions(+), 4 deletions(-)
diff --git a/tasmota/xsns_62_esp32_mi_ble.ino b/tasmota/xsns_62_esp32_mi_ble.ino
index cb9548e6e..a1f520aec 100644
--- a/tasmota/xsns_62_esp32_mi_ble.ino
+++ b/tasmota/xsns_62_esp32_mi_ble.ino
@@ -261,6 +261,36 @@ struct PVVXPacket_t {
uint8_t flags;
};
+struct MiScaleV1Packet_t {
+ //uint8_t size; // = 14
+ //uint8_t uid; // = 0x16, 16-bit UUID
+ //uint16_t UUID; // = 0x181D
+ uint8_t status; // bit 0 lbs, 4 jin, 5, stabilized, 7, weight removed
+ uint16_t weight;
+ uint16_t year;
+ uint8_t month;
+ uint8_t day;
+ uint8_t hour;
+ uint8_t minute;
+ uint8_t second;
+};
+
+struct MiScaleV2Packet_t {
+ //uint8_t size; // = 17
+ //uint8_t uid; // = 0x16, 16-bit UUID
+ //uint16_t UUID; // = 0x181B
+ uint8_t weight_unit;
+ uint8_t status;
+ uint16_t year;
+ uint8_t month;
+ uint8_t day;
+ uint8_t hour;
+ uint8_t minute;
+ uint8_t second;
+ uint16_t impedance;
+ uint16_t weight;
+};
+
#pragma pack(0)
struct mi_sensor_t{
@@ -286,6 +316,7 @@ struct mi_sensor_t{
uint32_t events:1;
uint32_t pairing:1;
uint32_t light:1; // binary light sensor
+ uint32_t scale:1;
};
uint32_t raw;
} feature;
@@ -304,6 +335,7 @@ struct mi_sensor_t{
uint32_t Btn:1;
uint32_t PairBtn:1;
uint32_t light:1; // binary light sensor
+ uint32_t scale:1;
};
uint32_t raw;
} eventType;
@@ -333,6 +365,16 @@ struct mi_sensor_t{
union {
uint8_t bat; // many values seem to be hard-coded garbage (LYWSD0x, GCD1)
};
+ union {
+ struct {
+ uint8_t has_impedance;
+ uint8_t stabilized;
+ uint8_t weight_removed;
+ char weight_unit[4]; // kg, lbs, jin or empty when unknown
+ float weight;
+ uint16_t impedance;
+ };
+ };
};
struct MAC_t {
@@ -380,8 +422,10 @@ void (*const MI32_Commands[])(void) PROGMEM = {
#define MI_MHOC303 12
#define MI_ATC 13
#define MI_DOOR 14
+#define MI_SCALE_V1 15
+#define MI_SCALE_V2 16
-#define MI_MI32_TYPES 14 //count this manually
+#define MI_MI32_TYPES 16 //count this manually
const uint16_t kMI32DeviceID[MI_MI32_TYPES]={
0x0000, // Unkown
@@ -396,8 +440,10 @@ const uint16_t kMI32DeviceID[MI_MI32_TYPES]={
0x0153, // yee-rc
0x0387, // MHO-C401
0x06d3, // MHO-C303
- 0x0a1c, // ATC -> this is a fake ID
- 0x098b // door/window sensor
+ 0x0a1c, // ATC -> this is a fake ID
+ 0x098b, // door/window sensor
+ 0x181d, // Mi Scale V1
+ 0x181b // Mi Scale V2
};
const char kMI32DeviceType0[] PROGMEM = "Unknown";
@@ -414,7 +460,9 @@ const char kMI32DeviceType10[] PROGMEM ="MHOC401";
const char kMI32DeviceType11[] PROGMEM ="MHOC303";
const char kMI32DeviceType12[] PROGMEM ="ATC";
const char kMI32DeviceType13[] PROGMEM ="DOOR";
-const char * kMI32DeviceType[] PROGMEM = {kMI32DeviceType0,kMI32DeviceType1,kMI32DeviceType2,kMI32DeviceType3,kMI32DeviceType4,kMI32DeviceType5,kMI32DeviceType6,kMI32DeviceType7,kMI32DeviceType8,kMI32DeviceType9,kMI32DeviceType10,kMI32DeviceType11,kMI32DeviceType12,kMI32DeviceType13};
+const char kMI32DeviceType14[] PROGMEM ="MISCALEV1";
+const char kMI32DeviceType15[] PROGMEM ="MISCALEV2";
+const char * kMI32DeviceType[] PROGMEM = {kMI32DeviceType0,kMI32DeviceType1,kMI32DeviceType2,kMI32DeviceType3,kMI32DeviceType4,kMI32DeviceType5,kMI32DeviceType6,kMI32DeviceType7,kMI32DeviceType8,kMI32DeviceType9,kMI32DeviceType10,kMI32DeviceType11,kMI32DeviceType12,kMI32DeviceType13,kMI32DeviceType14,kMI32DeviceType15};
typedef int BATREAD_FUNCTION(int slot);
typedef int UNITWRITE_FUNCTION(int slot, int unit);
@@ -987,6 +1035,11 @@ int MI32advertismentCallback(BLE_ESP32::ble_advertisment_t *pStruct)
case 0x181a: { //ATC
MI32ParseATCPacket(ServiceData, ServiceDataLength, addr, RSSI);
} break;
+ case 0x181d: // Mi Scale V1
+ case 0x181b: // Mi Scale V2
+ {
+ MI32ParseMiScalePacket(ServiceData, ServiceDataLength, addr, RSSI, UUID);
+ } break;
default:{
} break;
@@ -1438,6 +1491,10 @@ uint32_t MIBLEgetSensorSlot(const uint8_t *mac, uint16_t _type, uint8_t counter)
_newSensor.feature.light=1;
_newSensor.feature.bat=1;
break;
+ case MI_SCALE_V1:
+ case MI_SCALE_V2:
+ _newSensor.feature.scale=1;
+ break;
default:
_newSensor.hum=NAN;
_newSensor.feature.temp=1;
@@ -1639,6 +1696,87 @@ void MI32ParseATCPacket(const uint8_t * _buf, uint32_t length, const uint8_t *ad
}
}
+void MI32ParseMiScalePacket(const uint8_t * _buf, uint32_t length, const uint8_t *addr, int RSSI, int UUID){
+ MiScaleV1Packet_t *_packetV1 = (MiScaleV1Packet_t*)_buf;
+ MiScaleV2Packet_t *_packetV2 = (MiScaleV2Packet_t*)_buf;
+
+ // Mi Scale V1
+ if (length == 10 && UUID == 0x181d){ // 14-1-1-2
+ uint32_t _slot = MIBLEgetSensorSlot(addr, UUID, 0);
+ if(_slot==0xff) return;
+
+ if ((_slot >= 0) && (_slot < MIBLEsensors.size())){
+ if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s: at slot %u"), kMI32DeviceType[MIBLEsensors[_slot].type-1],_slot);
+ MIBLEsensors[_slot].RSSI=RSSI;
+ MIBLEsensors[_slot].needkey=KEY_NOT_REQUIRED;
+ MIBLEsensors[_slot].eventType.scale = 1;
+
+ MIBLEsensors[_slot].stabilized = (_packetV1->status & (1 << 5)) ? 1 : 0;
+ MIBLEsensors[_slot].weight_removed = (_packetV1->status & (1 << 7)) ? 1 : 0;
+
+ if (_packetV1->status & (1 << 0)) {
+ strcpy(MIBLEsensors[_slot].weight_unit, PSTR("lbs"));
+ MIBLEsensors[_slot].weight = (float)_packetV1->weight / 100.0f;
+ } else if(_packetV1->status & (1 << 4)) {
+ strcpy(MIBLEsensors[_slot].weight_unit, PSTR("jin"));
+ MIBLEsensors[_slot].weight = (float)_packetV1->weight / 100.0f;
+ } else {
+ strcpy(MIBLEsensors[_slot].weight_unit, PSTR("kg"));
+ MIBLEsensors[_slot].weight = (float)_packetV1->weight / 200.0f;
+ }
+
+ if (MIBLEsensors[_slot].weight_removed) {
+ MIBLEsensors[_slot].weight = 0.0f;
+ }
+
+ if(MI32.option.directBridgeMode) {
+ MIBLEsensors[_slot].shallSendMQTT = 1;
+ MI32.mode.shallTriggerTele = 1;
+ }
+ }
+ }
+
+ // Mi Scale V2
+ else if (length == 13 && UUID == 0x181b){ // 17-1-1-2
+ uint32_t _slot = MIBLEgetSensorSlot(addr, UUID, 0);
+ if(_slot==0xff) return;
+
+ if ((_slot >= 0) && (_slot < MIBLEsensors.size())){
+ if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s: at slot %u"), kMI32DeviceType[MIBLEsensors[_slot].type-1],_slot);
+ MIBLEsensors[_slot].RSSI=RSSI;
+ MIBLEsensors[_slot].needkey=KEY_NOT_REQUIRED;
+ MIBLEsensors[_slot].eventType.scale = 1;
+
+ MIBLEsensors[_slot].has_impedance = (_packetV2->status & (1 << 1)) ? 1 : 0;
+ MIBLEsensors[_slot].stabilized = (_packetV2->status & (1 << 5)) ? 1 : 0;
+ MIBLEsensors[_slot].weight_removed = (_packetV2->status & (1 << 7)) ? 1 : 0;
+
+ if (_packetV2->weight_unit & (1 << 4)) {
+ strcpy(MIBLEsensors[_slot].weight_unit, PSTR("jin"));
+ MIBLEsensors[_slot].weight = (float)_packetV2->weight / 100.0f;
+ } else if(_packetV2->weight_unit == 3) {
+ strcpy(MIBLEsensors[_slot].weight_unit, PSTR("lbs"));
+ MIBLEsensors[_slot].weight = (float)_packetV2->weight / 100.0f;
+ } else if(_packetV2->weight_unit == 2) {
+ strcpy(MIBLEsensors[_slot].weight_unit, PSTR("kg"));
+ MIBLEsensors[_slot].weight = (float)_packetV2->weight / 200.0f;
+ } else {
+ strcpy(MIBLEsensors[_slot].weight_unit, PSTR(""));
+ MIBLEsensors[_slot].weight = (float)_packetV2->weight / 100.0f;
+ }
+
+ if (MIBLEsensors[_slot].weight_removed) {
+ MIBLEsensors[_slot].weight = 0.0f;
+ }
+
+ if(MI32.option.directBridgeMode) {
+ MIBLEsensors[_slot].shallSendMQTT = 1;
+ MI32.mode.shallTriggerTele = 1;
+ }
+ }
+ }
+}
+
////////////////////////////////////////////////////////////
// this SHOULD parse any MI payload.
int MI32parseMiPayload(int _slot, struct mi_beacon_data_t *parsed){
@@ -2380,6 +2518,10 @@ const char HTTP_NMT[] PROGMEM = "{s}%s No motion{m}> %u seconds{e}";
const char HTTP_MI32_FLORA_DATA[] PROGMEM = "{s}%s" " Fertility" "{m}%u us/cm{e}";
const char HTTP_MI32_HL[] PROGMEM = "{s}
{m}
{e}";
const char HTTP_MI32_LIGHT[] PROGMEM = "{s}%s" " Light" "{m}%d{e}";
+const char HTTP_MISCALE_WEIGHT[] PROGMEM = "{s}%s" " Weight" "{m}%*_f %s{e}";
+const char HTTP_MISCALE_IMPEDANCE[] PROGMEM = "{s}%s" " Impedance" "{m}%u{e}";
+const char HTTP_MISCALE_WEIGHT_REMOVED[] PROGMEM = "{s}%s" " Weight removed" "{m}%s{e}";
+const char HTTP_MISCALE_STABILIZED[] PROGMEM = "{s}%s" " Stabilized" "{m}%s{e}";
//const char HTTP_NEEDKEY[] PROGMEM = "{s}%s feature.scale){
+ if(p->eventType.scale || !MI32.mode.triggeredTele || MI32.option.allwaysAggregate
+#ifdef USE_HOME_ASSISTANT
+ ||(hass_mode==2)
+#endif //USE_HOME_ASSISTANT
+ ){
+ ResponseAppend_P(PSTR(",\"weight_removed\":%u"), p->weight_removed);
+ ResponseAppend_P(PSTR(",\"stabilized\":%u"), p->stabilized);
+ ResponseAppend_P(PSTR(",\"weight_unit\":\"%s\""), p->weight_unit);
+ ResponseAppend_P(PSTR(",\"weight\":%*_f"),
+ Settings->flag2.weight_resolution, &p->weight);
+ if (p->has_impedance){
+ ResponseAppend_P(PSTR(",\"impedance\":%u"), p->impedance);
+ }
+ }
+ }
if (p->feature.Btn){
if(p->eventType.Btn || !MI32.mode.triggeredTele || MI32.option.allwaysAggregate
#ifdef USE_HOME_ASSISTANT
@@ -3205,6 +3363,14 @@ void MI32Show(bool json)
if (p->feature.light){
WSContentSend_PD(HTTP_MI32_LIGHT, typeName, p->light);
}
+ if (p->feature.scale){
+ WSContentSend_PD(HTTP_MISCALE_WEIGHT, typeName, Settings->flag2.weight_resolution, &p->weight, p->weight_unit);
+ if (p->has_impedance) {
+ WSContentSend_PD(HTTP_MISCALE_IMPEDANCE, typeName, p->impedance);
+ }
+ WSContentSend_PD(HTTP_MISCALE_WEIGHT_REMOVED, typeName, p->weight_removed? PSTR("yes") : PSTR("no"));
+ WSContentSend_PD(HTTP_MISCALE_STABILIZED, typeName, p->stabilized ? PSTR("yes") : PSTR("no"));
+ }
if(p->bat!=0x00){
WSContentSend_PD(HTTP_BATTERY, typeName, p->bat);
From 2a53f3ba1dbfbee2489fd5419634192a01adb769 Mon Sep 17 00:00:00 2001
From: Milenko Mitrovic
Date: Thu, 16 Dec 2021 00:44:49 +0100
Subject: [PATCH 002/355] Use only stabilized weight packets when
directBridgeMode is disabled
---
tasmota/xsns_62_esp32_mi_ble.ino | 60 ++++++++++++++++++++------------
1 file changed, 38 insertions(+), 22 deletions(-)
diff --git a/tasmota/xsns_62_esp32_mi_ble.ino b/tasmota/xsns_62_esp32_mi_ble.ino
index bb42778c3..abbfeee69 100644
--- a/tasmota/xsns_62_esp32_mi_ble.ino
+++ b/tasmota/xsns_62_esp32_mi_ble.ino
@@ -1700,23 +1700,30 @@ void MI32ParseATCPacket(const uint8_t * _buf, uint32_t length, const uint8_t *ad
}
}
-void MI32ParseMiScalePacket(const uint8_t * _buf, uint32_t length, const uint8_t *addr, int RSSI, int UUID){
+void MI32ParseMiScalePacket(const uint8_t * _buf, uint32_t length, const uint8_t *addr, int RSSI, int UUID) {
MiScaleV1Packet_t *_packetV1 = (MiScaleV1Packet_t*)_buf;
MiScaleV2Packet_t *_packetV2 = (MiScaleV2Packet_t*)_buf;
+ uint8_t stabilized = 0;
+ uint8_t weight_removed = 0;
// Mi Scale V1
- if (length == 10 && UUID == 0x181d){ // 14-1-1-2
- uint32_t _slot = MIBLEgetSensorSlot(addr, UUID, 0);
- if(_slot==0xff) return;
+ if (length == 10 && UUID == 0x181d) { // 14-1-1-2
+ stabilized = (_packetV1->status & (1 << 5)) ? 1 : 0;
+ weight_removed = (_packetV1->status & (1 << 7)) ? 1 : 0;
+ if (!MI32.option.directBridgeMode && (!stabilized || weight_removed))
+ return;
- if ((_slot >= 0) && (_slot < MIBLEsensors.size())){
+ uint32_t _slot = MIBLEgetSensorSlot(addr, UUID, 0);
+ if (_slot==0xff) return;
+
+ if ((_slot >= 0) && (_slot < MIBLEsensors.size())) {
if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s: at slot %u"), kMI32DeviceType[MIBLEsensors[_slot].type-1],_slot);
- MIBLEsensors[_slot].RSSI=RSSI;
- MIBLEsensors[_slot].needkey=KEY_NOT_REQUIRED;
+ MIBLEsensors[_slot].RSSI = RSSI;
+ MIBLEsensors[_slot].needkey = KEY_NOT_REQUIRED;
MIBLEsensors[_slot].eventType.scale = 1;
- MIBLEsensors[_slot].stabilized = (_packetV1->status & (1 << 5)) ? 1 : 0;
- MIBLEsensors[_slot].weight_removed = (_packetV1->status & (1 << 7)) ? 1 : 0;
+ MIBLEsensors[_slot].stabilized = stabilized;
+ MIBLEsensors[_slot].weight_removed = weight_removed;
if (_packetV1->status & (1 << 0)) {
strcpy(MIBLEsensors[_slot].weight_unit, PSTR("lbs"));
@@ -1741,19 +1748,24 @@ void MI32ParseMiScalePacket(const uint8_t * _buf, uint32_t length, const uint8_t
}
// Mi Scale V2
- else if (length == 13 && UUID == 0x181b){ // 17-1-1-2
- uint32_t _slot = MIBLEgetSensorSlot(addr, UUID, 0);
- if(_slot==0xff) return;
+ else if (length == 13 && UUID == 0x181b) { // 17-1-1-2
+ stabilized = (_packetV2->status & (1 << 5)) ? 1 : 0;
+ weight_removed = (_packetV2->status & (1 << 7)) ? 1 : 0;
+ if (!MI32.option.directBridgeMode && (!stabilized || weight_removed))
+ return;
- if ((_slot >= 0) && (_slot < MIBLEsensors.size())){
+ uint32_t _slot = MIBLEgetSensorSlot(addr, UUID, 0);
+ if (_slot==0xff) return;
+
+ if ((_slot >= 0) && (_slot < MIBLEsensors.size())) {
if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s: at slot %u"), kMI32DeviceType[MIBLEsensors[_slot].type-1],_slot);
- MIBLEsensors[_slot].RSSI=RSSI;
- MIBLEsensors[_slot].needkey=KEY_NOT_REQUIRED;
+ MIBLEsensors[_slot].RSSI = RSSI;
+ MIBLEsensors[_slot].needkey = KEY_NOT_REQUIRED;
MIBLEsensors[_slot].eventType.scale = 1;
MIBLEsensors[_slot].has_impedance = (_packetV2->status & (1 << 1)) ? 1 : 0;
- MIBLEsensors[_slot].stabilized = (_packetV2->status & (1 << 5)) ? 1 : 0;
- MIBLEsensors[_slot].weight_removed = (_packetV2->status & (1 << 7)) ? 1 : 0;
+ MIBLEsensors[_slot].stabilized = stabilized;
+ MIBLEsensors[_slot].weight_removed = weight_removed;
if (_packetV2->weight_unit & (1 << 4)) {
strcpy(MIBLEsensors[_slot].weight_unit, PSTR("jin"));
@@ -2731,8 +2743,10 @@ void MI32GetOneSensorJson(int slot, int hidename){
||(hass_mode==2)
#endif //USE_HOME_ASSISTANT
){
- ResponseAppend_P(PSTR(",\"weight_removed\":%u"), p->weight_removed);
- ResponseAppend_P(PSTR(",\"stabilized\":%u"), p->stabilized);
+ if (MI32.option.directBridgeMode) {
+ ResponseAppend_P(PSTR(",\"weight_removed\":%u"), p->weight_removed);
+ ResponseAppend_P(PSTR(",\"stabilized\":%u"), p->stabilized);
+ }
ResponseAppend_P(PSTR(",\"weight_unit\":\"%s\""), p->weight_unit);
ResponseAppend_P(PSTR(",\"weight\":%*_f"),
Settings->flag2.weight_resolution, &p->weight);
@@ -3369,8 +3383,10 @@ void MI32Show(bool json)
if (p->has_impedance) {
WSContentSend_PD(HTTP_MISCALE_IMPEDANCE, typeName, p->impedance);
}
- WSContentSend_PD(HTTP_MISCALE_WEIGHT_REMOVED, typeName, p->weight_removed? PSTR("yes") : PSTR("no"));
- WSContentSend_PD(HTTP_MISCALE_STABILIZED, typeName, p->stabilized ? PSTR("yes") : PSTR("no"));
+ if (MI32.option.directBridgeMode) {
+ WSContentSend_PD(HTTP_MISCALE_WEIGHT_REMOVED, typeName, p->weight_removed? PSTR("yes") : PSTR("no"));
+ WSContentSend_PD(HTTP_MISCALE_STABILIZED, typeName, p->stabilized ? PSTR("yes") : PSTR("no"));
+ }
}
if(p->bat!=0x00){
@@ -3438,4 +3454,4 @@ bool Xsns62(uint8_t function)
#endif // CONFIG_IDF_TARGET_ESP32 or CONFIG_IDF_TARGET_ESP32C3
#endif // ESP32
-#endif
+#endif
\ No newline at end of file
From dc1fa0e50d87ccad3ae61ea345d7ba7d37c20785 Mon Sep 17 00:00:00 2001
From: Milenko Mitrovic
Date: Sat, 18 Dec 2021 20:43:17 +0100
Subject: [PATCH 003/355] Added feature.impedance for V2 to separate impedance
and impedance_stabilized value from V1 and changed stabilized/has_impedance
to weight_stabilized/impedance_stabilized
---
tasmota/xsns_62_esp32_mi_ble.ino | 54 ++++++++++++++++++++------------
1 file changed, 34 insertions(+), 20 deletions(-)
diff --git a/tasmota/xsns_62_esp32_mi_ble.ino b/tasmota/xsns_62_esp32_mi_ble.ino
index abbfeee69..1c37323d1 100644
--- a/tasmota/xsns_62_esp32_mi_ble.ino
+++ b/tasmota/xsns_62_esp32_mi_ble.ino
@@ -280,7 +280,7 @@ struct MiScaleV2Packet_t {
//uint8_t uid; // = 0x16, 16-bit UUID
//uint16_t UUID; // = 0x181B
uint8_t weight_unit;
- uint8_t status;
+ uint8_t status; // bit 14 impedance stabilized
uint16_t year;
uint8_t month;
uint8_t day;
@@ -317,6 +317,7 @@ struct mi_sensor_t{
uint32_t pairing:1;
uint32_t light:1; // binary light sensor
uint32_t scale:1;
+ uint32_t impedance:1;
};
uint32_t raw;
} feature;
@@ -367,11 +368,11 @@ struct mi_sensor_t{
};
union {
struct {
- uint8_t has_impedance;
- uint8_t stabilized;
+ uint8_t weight_stabilized;
uint8_t weight_removed;
char weight_unit[4]; // kg, lbs, jin or empty when unknown
float weight;
+ uint8_t impedance_stabilized;
uint16_t impedance;
};
};
@@ -1492,8 +1493,11 @@ uint32_t MIBLEgetSensorSlot(const uint8_t *mac, uint16_t _type, uint8_t counter)
_newSensor.feature.bat=1;
break;
case MI_SCALE_V1:
+ _newSensor.feature.scale=1;
+ break;
case MI_SCALE_V2:
_newSensor.feature.scale=1;
+ _newSensor.feature.impedance=1;
break;
default:
_newSensor.hum=NAN;
@@ -1703,14 +1707,15 @@ void MI32ParseATCPacket(const uint8_t * _buf, uint32_t length, const uint8_t *ad
void MI32ParseMiScalePacket(const uint8_t * _buf, uint32_t length, const uint8_t *addr, int RSSI, int UUID) {
MiScaleV1Packet_t *_packetV1 = (MiScaleV1Packet_t*)_buf;
MiScaleV2Packet_t *_packetV2 = (MiScaleV2Packet_t*)_buf;
- uint8_t stabilized = 0;
+ uint8_t weight_stabilized = 0;
uint8_t weight_removed = 0;
+ uint8_t impedance_stabilized = 0;
// Mi Scale V1
if (length == 10 && UUID == 0x181d) { // 14-1-1-2
- stabilized = (_packetV1->status & (1 << 5)) ? 1 : 0;
+ weight_stabilized = (_packetV1->status & (1 << 5)) ? 1 : 0;
weight_removed = (_packetV1->status & (1 << 7)) ? 1 : 0;
- if (!MI32.option.directBridgeMode && (!stabilized || weight_removed))
+ if (!MI32.option.directBridgeMode && (!weight_stabilized || weight_removed))
return;
uint32_t _slot = MIBLEgetSensorSlot(addr, UUID, 0);
@@ -1722,7 +1727,7 @@ void MI32ParseMiScalePacket(const uint8_t * _buf, uint32_t length, const uint8_t
MIBLEsensors[_slot].needkey = KEY_NOT_REQUIRED;
MIBLEsensors[_slot].eventType.scale = 1;
- MIBLEsensors[_slot].stabilized = stabilized;
+ MIBLEsensors[_slot].weight_stabilized = weight_stabilized;
MIBLEsensors[_slot].weight_removed = weight_removed;
if (_packetV1->status & (1 << 0)) {
@@ -1749,9 +1754,10 @@ void MI32ParseMiScalePacket(const uint8_t * _buf, uint32_t length, const uint8_t
// Mi Scale V2
else if (length == 13 && UUID == 0x181b) { // 17-1-1-2
- stabilized = (_packetV2->status & (1 << 5)) ? 1 : 0;
+ weight_stabilized = (_packetV2->status & (1 << 5)) ? 1 : 0;
weight_removed = (_packetV2->status & (1 << 7)) ? 1 : 0;
- if (!MI32.option.directBridgeMode && (!stabilized || weight_removed))
+ impedance_stabilized = (_packetV2->status & (1 << 1)) ? 1 : 0;
+ if (!MI32.option.directBridgeMode && (!weight_stabilized || weight_removed /* || !impedance_stabilized */))
return;
uint32_t _slot = MIBLEgetSensorSlot(addr, UUID, 0);
@@ -1763,9 +1769,10 @@ void MI32ParseMiScalePacket(const uint8_t * _buf, uint32_t length, const uint8_t
MIBLEsensors[_slot].needkey = KEY_NOT_REQUIRED;
MIBLEsensors[_slot].eventType.scale = 1;
- MIBLEsensors[_slot].has_impedance = (_packetV2->status & (1 << 1)) ? 1 : 0;
- MIBLEsensors[_slot].stabilized = stabilized;
+ MIBLEsensors[_slot].weight_stabilized = weight_stabilized;
MIBLEsensors[_slot].weight_removed = weight_removed;
+ MIBLEsensors[_slot].impedance_stabilized = impedance_stabilized;
+ MIBLEsensors[_slot].impedance = _packetV2->impedance;
if (_packetV2->weight_unit & (1 << 4)) {
strcpy(MIBLEsensors[_slot].weight_unit, PSTR("jin"));
@@ -1783,6 +1790,7 @@ void MI32ParseMiScalePacket(const uint8_t * _buf, uint32_t length, const uint8_t
if (MIBLEsensors[_slot].weight_removed) {
MIBLEsensors[_slot].weight = 0.0f;
+ MIBLEsensors[_slot].impedance = 0;
}
if(MI32.option.directBridgeMode) {
@@ -2535,9 +2543,10 @@ const char HTTP_MI32_FLORA_DATA[] PROGMEM = "{s}%s" " Fertility" "{m}%u us/cm{e}
const char HTTP_MI32_HL[] PROGMEM = "{s}
{m}
{e}";
const char HTTP_MI32_LIGHT[] PROGMEM = "{s}%s" " Light" "{m}%d{e}";
const char HTTP_MISCALE_WEIGHT[] PROGMEM = "{s}%s" " Weight" "{m}%*_f %s{e}";
-const char HTTP_MISCALE_IMPEDANCE[] PROGMEM = "{s}%s" " Impedance" "{m}%u{e}";
const char HTTP_MISCALE_WEIGHT_REMOVED[] PROGMEM = "{s}%s" " Weight removed" "{m}%s{e}";
-const char HTTP_MISCALE_STABILIZED[] PROGMEM = "{s}%s" " Stabilized" "{m}%s{e}";
+const char HTTP_MISCALE_WEIGHT_STABILIZED[] PROGMEM = "{s}%s" " Weight stabilized" "{m}%s{e}";
+const char HTTP_MISCALE_IMPEDANCE[] PROGMEM = "{s}%s" " Impedance" "{m}%u{e}";
+const char HTTP_MISCALE_IMPEDANCE_STABILIZED[] PROGMEM = "{s}%s" " Impedance stabilized" "{m}%s{e}";
//const char HTTP_NEEDKEY[] PROGMEM = "{s}%s weight_removed);
- ResponseAppend_P(PSTR(",\"stabilized\":%u"), p->stabilized);
+ ResponseAppend_P(PSTR(",\"weight_stabilized\":%u"), p->weight_stabilized);
}
ResponseAppend_P(PSTR(",\"weight_unit\":\"%s\""), p->weight_unit);
ResponseAppend_P(PSTR(",\"weight\":%*_f"),
Settings->flag2.weight_resolution, &p->weight);
- if (p->has_impedance){
+ if (p->feature.impedance) {
+ if (MI32.option.directBridgeMode) {
+ ResponseAppend_P(PSTR(",\"impedance_stabilized\":%u"), p->impedance_stabilized);
+ }
ResponseAppend_P(PSTR(",\"impedance\":%u"), p->impedance);
}
}
@@ -3380,15 +3392,17 @@ void MI32Show(bool json)
}
if (p->feature.scale){
WSContentSend_PD(HTTP_MISCALE_WEIGHT, typeName, Settings->flag2.weight_resolution, &p->weight, p->weight_unit);
- if (p->has_impedance) {
- WSContentSend_PD(HTTP_MISCALE_IMPEDANCE, typeName, p->impedance);
- }
if (MI32.option.directBridgeMode) {
WSContentSend_PD(HTTP_MISCALE_WEIGHT_REMOVED, typeName, p->weight_removed? PSTR("yes") : PSTR("no"));
- WSContentSend_PD(HTTP_MISCALE_STABILIZED, typeName, p->stabilized ? PSTR("yes") : PSTR("no"));
+ WSContentSend_PD(HTTP_MISCALE_WEIGHT_STABILIZED, typeName, p->weight_stabilized ? PSTR("yes") : PSTR("no"));
+ }
+ if (p->feature.impedance) {
+ WSContentSend_PD(HTTP_MISCALE_IMPEDANCE, typeName, p->impedance);
+ if (MI32.option.directBridgeMode) {
+ WSContentSend_PD(HTTP_MISCALE_IMPEDANCE_STABILIZED, typeName, p->impedance_stabilized? PSTR("yes") : PSTR("no"));
+ }
}
}
-
if(p->bat!=0x00){
WSContentSend_PD(HTTP_BATTERY, typeName, p->bat);
}
From ecb3a07d2f3aa0180a1283533f882ce6a3f81fcf Mon Sep 17 00:00:00 2001
From: Milenko Mitrovic
Date: Sun, 19 Dec 2021 11:58:41 +0100
Subject: [PATCH 004/355] Changed json property names to better match the other
properties
---
tasmota/xsns_62_esp32_mi_ble.ino | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/tasmota/xsns_62_esp32_mi_ble.ino b/tasmota/xsns_62_esp32_mi_ble.ino
index 1c37323d1..5b4fa8eed 100644
--- a/tasmota/xsns_62_esp32_mi_ble.ino
+++ b/tasmota/xsns_62_esp32_mi_ble.ino
@@ -2753,17 +2753,17 @@ void MI32GetOneSensorJson(int slot, int hidename){
#endif //USE_HOME_ASSISTANT
){
if (MI32.option.directBridgeMode) {
- ResponseAppend_P(PSTR(",\"weight_removed\":%u"), p->weight_removed);
- ResponseAppend_P(PSTR(",\"weight_stabilized\":%u"), p->weight_stabilized);
+ ResponseAppend_P(PSTR(",\"WeightRemoved\":%u"), p->weight_removed);
+ ResponseAppend_P(PSTR(",\"WeightStabilized\":%u"), p->weight_stabilized);
}
- ResponseAppend_P(PSTR(",\"weight_unit\":\"%s\""), p->weight_unit);
- ResponseAppend_P(PSTR(",\"weight\":%*_f"),
+ ResponseAppend_P(PSTR(",\"WeightUnit\":\"%s\""), p->weight_unit);
+ ResponseAppend_P(PSTR(",\"Weight\":%*_f"),
Settings->flag2.weight_resolution, &p->weight);
if (p->feature.impedance) {
if (MI32.option.directBridgeMode) {
- ResponseAppend_P(PSTR(",\"impedance_stabilized\":%u"), p->impedance_stabilized);
+ ResponseAppend_P(PSTR(",\"ImpedanceStabilized\":%u"), p->impedance_stabilized);
}
- ResponseAppend_P(PSTR(",\"impedance\":%u"), p->impedance);
+ ResponseAppend_P(PSTR(",\"Impedance\":%u"), p->impedance);
}
}
}
From a0ba50d38db43c869de92c5b2f8ab300527b87f9 Mon Sep 17 00:00:00 2001
From: Milenko Mitrovic
Date: Sun, 19 Dec 2021 11:59:49 +0100
Subject: [PATCH 005/355] Added Weight and Impedance support to Home Assistant
auto discovery
---
tasmota/xsns_62_esp32_mi_ble.ino | 26 +++++++++++++++++++++++---
1 file changed, 23 insertions(+), 3 deletions(-)
diff --git a/tasmota/xsns_62_esp32_mi_ble.ino b/tasmota/xsns_62_esp32_mi_ble.ino
index 5b4fa8eed..841de87a0 100644
--- a/tasmota/xsns_62_esp32_mi_ble.ino
+++ b/tasmota/xsns_62_esp32_mi_ble.ino
@@ -3012,6 +3012,16 @@ const char *classes[] = {
"", //- empty device class
"Firmware",
"",
+
+ // 11
+ "", //- empty device class
+ "Weight",
+ "", // Will be set to p->weight_unit
+
+ // 12
+ "", //- empty device class
+ "Impedance",
+ "Ohm",
};
@@ -3123,6 +3133,16 @@ void MI32DiscoveryOneMISensor(){
continue;
}
break;
+ case 11: // weight
+ if (!p->feature.scale){ // Mi Scale V1 and V2 only
+ continue;
+ }
+ break;
+ case 12: // impedance
+ if (!p->feature.impedance){ // Mi Scale V2 only
+ continue;
+ }
+ break;
}
/*
@@ -3157,9 +3177,9 @@ void MI32DiscoveryOneMISensor(){
//"\"uniq_id\":\"%s_%s\"," - unique for this data,
id, classes[i+1],
//"\"unit_of_meas\":\"%s\"," - the measure of this type of data
- (classes[i+2][0]?"\"unit_of_meas\":\"":""),
- classes[i+2],
- (classes[i+2][0]?"\",":""),
+ ((i/3==11)||classes[i+2][0]?"\"unit_of_meas\":\"":""),
+ (i/3==11)?p->weight_unit:classes[i+2],
+ ((i/3==11)||classes[i+2][0]?"\",":""),
//"\"val_tpl\":\"{{ %s%s }}") // e.g. Temperature
// inverted binary - {{ 'off' if value_json.posn else 'on' }}
// binary - {{ 'on' if value_json.posn else 'off' }}
From d13381f1306661dcca687721ecbcb977720d1e38 Mon Sep 17 00:00:00 2001
From: Milenko Mitrovic
Date: Sun, 30 Jan 2022 00:25:22 +0100
Subject: [PATCH 006/355] Send MQTT message when weight/impedance is stabilized
or direct bridge mode is enabled. Fixed impedance measurement on V2 scale.
---
tasmota/xsns_62_esp32_mi_ble.ino | 30 +++++++++++++++++-------------
1 file changed, 17 insertions(+), 13 deletions(-)
diff --git a/tasmota/xsns_62_esp32_mi_ble.ino b/tasmota/xsns_62_esp32_mi_ble.ino
index 841de87a0..2ee034c06 100644
--- a/tasmota/xsns_62_esp32_mi_ble.ino
+++ b/tasmota/xsns_62_esp32_mi_ble.ino
@@ -1729,7 +1729,7 @@ void MI32ParseMiScalePacket(const uint8_t * _buf, uint32_t length, const uint8_t
MIBLEsensors[_slot].weight_stabilized = weight_stabilized;
MIBLEsensors[_slot].weight_removed = weight_removed;
-
+
if (_packetV1->status & (1 << 0)) {
strcpy(MIBLEsensors[_slot].weight_unit, PSTR("lbs"));
MIBLEsensors[_slot].weight = (float)_packetV1->weight / 100.0f;
@@ -1745,10 +1745,8 @@ void MI32ParseMiScalePacket(const uint8_t * _buf, uint32_t length, const uint8_t
MIBLEsensors[_slot].weight = 0.0f;
}
- if(MI32.option.directBridgeMode) {
- MIBLEsensors[_slot].shallSendMQTT = 1;
- MI32.mode.shallTriggerTele = 1;
- }
+ MIBLEsensors[_slot].shallSendMQTT = 1;
+ MI32.mode.shallTriggerTele = 1;
}
}
@@ -1757,7 +1755,7 @@ void MI32ParseMiScalePacket(const uint8_t * _buf, uint32_t length, const uint8_t
weight_stabilized = (_packetV2->status & (1 << 5)) ? 1 : 0;
weight_removed = (_packetV2->status & (1 << 7)) ? 1 : 0;
impedance_stabilized = (_packetV2->status & (1 << 1)) ? 1 : 0;
- if (!MI32.option.directBridgeMode && (!weight_stabilized || weight_removed /* || !impedance_stabilized */))
+ if (!MI32.option.directBridgeMode && (!weight_stabilized || weight_removed))
return;
uint32_t _slot = MIBLEgetSensorSlot(addr, UUID, 0);
@@ -1771,8 +1769,6 @@ void MI32ParseMiScalePacket(const uint8_t * _buf, uint32_t length, const uint8_t
MIBLEsensors[_slot].weight_stabilized = weight_stabilized;
MIBLEsensors[_slot].weight_removed = weight_removed;
- MIBLEsensors[_slot].impedance_stabilized = impedance_stabilized;
- MIBLEsensors[_slot].impedance = _packetV2->impedance;
if (_packetV2->weight_unit & (1 << 4)) {
strcpy(MIBLEsensors[_slot].weight_unit, PSTR("jin"));
@@ -1788,15 +1784,23 @@ void MI32ParseMiScalePacket(const uint8_t * _buf, uint32_t length, const uint8_t
MIBLEsensors[_slot].weight = (float)_packetV2->weight / 100.0f;
}
- if (MIBLEsensors[_slot].weight_removed) {
+ if (weight_removed) {
MIBLEsensors[_slot].weight = 0.0f;
- MIBLEsensors[_slot].impedance = 0;
}
- if(MI32.option.directBridgeMode) {
- MIBLEsensors[_slot].shallSendMQTT = 1;
- MI32.mode.shallTriggerTele = 1;
+ MIBLEsensors[_slot].impedance = 0;
+ if (MI32.option.directBridgeMode || impedance_stabilized)
+ {
+ MIBLEsensors[_slot].impedance_stabilized = impedance_stabilized;
+ MIBLEsensors[_slot].impedance = _packetV2->impedance;
+
+ if (weight_removed) {
+ MIBLEsensors[_slot].impedance = 0;
+ }
}
+
+ MIBLEsensors[_slot].shallSendMQTT = 1;
+ MI32.mode.shallTriggerTele = 1;
}
}
}
From 3679ec4c088a05fe4d21043d0164e807942b0453 Mon Sep 17 00:00:00 2001
From: SteWers
Date: Tue, 8 Feb 2022 20:55:57 +0100
Subject: [PATCH 007/355] [Solax X1] Rework request and respond processing
Complete rework of the request cycle and the respond processing. This is more reliable and reusable for more and further requests.
Right now the serial number of the converter is requested and displayed in the WebUI.
---
tasmota/xnrg_12_solaxX1.ino | 316 ++++++++++++++++--------------------
1 file changed, 139 insertions(+), 177 deletions(-)
diff --git a/tasmota/xnrg_12_solaxX1.ino b/tasmota/xnrg_12_solaxX1.ino
index fa925e519..6f26bf4f6 100644
--- a/tasmota/xnrg_12_solaxX1.ino
+++ b/tasmota/xnrg_12_solaxX1.ino
@@ -1,7 +1,8 @@
/*
xnrg_12_solaxX1.ino - Solax X1 inverter RS485 support for Tasmota
- Copyright (C) 2021 Pablo Zerón
+ Copyright (C) 2021 by Pablo Zerón
+ Copyright (C) 2022 by Stefan Wershoven
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -35,12 +36,6 @@
#include
-enum solaxX1_Error
-{
- solaxX1_ERR_NO_ERROR,
- solaxX1_ERR_CRC_ERROR
-};
-
union {
uint32_t ErrMessage;
struct {
@@ -90,10 +85,6 @@ const char kSolaxError[] PROGMEM =
D_SOLAX_ERROR_0 "|" D_SOLAX_ERROR_1 "|" D_SOLAX_ERROR_2 "|" D_SOLAX_ERROR_3 "|" D_SOLAX_ERROR_4 "|" D_SOLAX_ERROR_5 "|"
D_SOLAX_ERROR_6 "|" D_SOLAX_ERROR_7 "|" D_SOLAX_ERROR_8;
-/*********************************************************************************************/
-
-TasmotaSerial *solaxX1Serial;
-
struct SOLAXX1 {
int16_t temperature = 0;
float energy_today = 0;
@@ -104,25 +95,10 @@ struct SOLAXX1 {
uint32_t runtime_total = 0;
float dc1_power = 0;
float dc2_power = 0;
-
int16_t runMode = 0;
uint32_t errorCode = 0;
} solaxX1;
-union {
- uint8_t status;
- struct {
- uint8_t freeBit7:1; // Bit7
- uint8_t freeBit6:1; // Bit6
- uint8_t freeBit5:1; // Bit5
- uint8_t queryOffline:1; // Bit4
- uint8_t queryOfflineSend:1; // Bit3
- uint8_t hasAddress:1; // Bit2
- uint8_t inverterAddressSend:1; // Bit1
- uint8_t inverterSnReceived:1; // Bit0
- };
-} protocolStatus;
-
uint8_t header[2] = {0xAA, 0x55};
uint8_t source[2] = {0x00, 0x00};
uint8_t destination[2] = {0x00, 0x00};
@@ -131,15 +107,16 @@ uint8_t functionCode[1] = {0x00};
uint8_t dataLength[1] = {0x00};
uint8_t data[16] = {0};
+TasmotaSerial *solaxX1Serial;
uint8_t message[30];
+bool AddressAssigned = true;
+uint8_t solaxX1_send_retry = 20;
+uint8_t solaxX1_queryData_count = 0;
+uint8_t solaxX1_QueryID_count = 240;
+uint8_t solaxX1SerialNumber[16] = {0x6e, 0x2f, 0x61}; // "n/a"
/*********************************************************************************************/
-bool solaxX1_RS485ReceiveReady(void)
-{
- return (solaxX1Serial->available() > 1);
-}
-
void solaxX1_RS485Send(uint16_t msgLen)
{
memcpy(message, header, 2);
@@ -151,8 +128,7 @@ void solaxX1_RS485Send(uint16_t msgLen)
memcpy(message + 9, data, sizeof(data));
uint16_t crc = solaxX1_calculateCRC(message, msgLen); // calculate out crc bytes
- while (solaxX1Serial->available() > 0)
- { // read serial if any old data is available
+ while (solaxX1Serial->available() > 0) { // read serial if any old data is available
solaxX1Serial->read();
}
@@ -171,12 +147,11 @@ void solaxX1_RS485Send(uint16_t msgLen)
AddLogBuffer(LOG_LEVEL_DEBUG_MORE, message, msgLen);
}
-uint8_t solaxX1_RS485Receive(uint8_t *value)
+bool solaxX1_RS485Receive(uint8_t *value)
{
uint8_t len = 0;
- while (solaxX1Serial->available() > 0)
- {
+ while (solaxX1Serial->available() > 0) {
value[len++] = (uint8_t)solaxX1Serial->read();
}
@@ -184,14 +159,7 @@ uint8_t solaxX1_RS485Receive(uint8_t *value)
uint16_t crc = solaxX1_calculateCRC(value, len - 2); // calculate out crc bytes
- if (value[len - 1] == lowByte(crc) && value[len - 2] == highByte(crc))
- { // check calc crc with received crc
- return solaxX1_ERR_NO_ERROR;
- }
- else
- {
- return solaxX1_ERR_CRC_ERROR;
- }
+ return !(value[len - 1] == lowByte(crc) && value[len - 2] == highByte(crc));
}
uint16_t solaxX1_calculateCRC(uint8_t *bExternTxPackage, uint8_t bLen)
@@ -200,13 +168,23 @@ uint16_t solaxX1_calculateCRC(uint8_t *bExternTxPackage, uint8_t bLen)
uint16_t wChkSum;
wChkSum = 0;
- for (i = 0; i < bLen; i++)
- {
+ for (i = 0; i < bLen; i++) {
wChkSum = wChkSum + bExternTxPackage[i];
}
return wChkSum;
}
+void solaxX1_QueryOfflineInverters(void)
+{
+ source[0] = 0x01;
+ destination[0] = 0x00;
+ destination[1] = 0x00;
+ controlCode[0] = 0x10;
+ functionCode[0] = 0x00;
+ dataLength[0] = 0x00;
+ solaxX1_RS485Send(9);
+}
+
void solaxX1_SendInverterAddress(void)
{
source[0] = 0x00;
@@ -230,6 +208,17 @@ void solaxX1_QueryLiveData(void)
solaxX1_RS485Send(9);
}
+void solaxX1_QueryIDData(void)
+{
+ source[0] = 0x01;
+ destination[0] = 0x00;
+ destination[1] = INVERTER_ADDRESS;
+ controlCode[0] = 0x11;
+ functionCode[0] = 0x03;
+ dataLength[0] = 0x00;
+ solaxX1_RS485Send(9);
+}
+
uint8_t solaxX1_ParseErrorCode(uint32_t code){
ErrCode.ErrMessage = code;
@@ -247,152 +236,124 @@ uint8_t solaxX1_ParseErrorCode(uint32_t code){
/*********************************************************************************************/
-uint8_t solaxX1_send_retry = 20;
-uint8_t solaxX1_queryData_count = 0;
-
void solaxX1250MSecond(void) // Every 250 milliseconds
{
- uint8_t value[61] = {0};
- bool data_ready = solaxX1_RS485ReceiveReady();
+ uint8_t value[70] = {0};
+ uint8_t i;
- if (data_ready)
- {
- if (protocolStatus.hasAddress)
- {
- uint8_t error = solaxX1_RS485Receive(value);
- if (error)
- {
- DEBUG_SENSOR_LOG(PSTR("SX1: Data response CRC error"));
- }
- else
- {
- solaxX1_send_retry = 20;
- Energy.data_valid[0] = 0;
-
- solaxX1.temperature = (value[9] << 8) | value[10]; // Temperature
- solaxX1.energy_today = (float)((value[11] << 8) | value[12]) * 0.1f; // Energy Today
- solaxX1.dc1_voltage = (float)((value[13] << 8) | value[14]) * 0.1f; // PV1 Voltage
- solaxX1.dc2_voltage = (float)((value[15] << 8) | value[16]) * 0.1f; // PV2 Voltage
- solaxX1.dc1_current = (float)((value[17] << 8) | value[18]) * 0.1f; // PV1 Current
- solaxX1.dc2_current = (float)((value[19] << 8) | value[20]) * 0.1f; // PV2 Current
- Energy.current[0] = (float)((value[21] << 8) | value[22]) * 0.1f; // AC Current
- Energy.voltage[0] = (float)((value[23] << 8) | value[24]) * 0.1f; // AC Voltage
- Energy.frequency[0] = (float)((value[25] << 8) | value[26]) * 0.01f; // AC Frequency
- Energy.active_power[0] = (float)((value[27] << 8) | value[28]); // AC Power
- //temporal = (float)((value[29] << 8) | value[30]) * 0.1f; // Not Used
- Energy.import_active[0] = (float)((value[31] << 24) | (value[32] << 16) | (value[33] << 8) | value[34]) * 0.1f; // Energy Total
- solaxX1.runtime_total = ((value[35] << 24) | (value[36] << 16) | (value[37] << 8) | value[38]); // Work Time Total
- solaxX1.runMode = (value[39] << 8) | value[40]; // Work mode
- //temporal = (float)((value[41] << 8) | value[42]); // Grid voltage fault value 0.1V
- //temporal = (float)((value[43] << 8) | value[44]); // Gird frequency fault value 0.01Hz
- //temporal = (float)((value[45] << 8) | value[46]); // Dc injection fault value 1mA
- //temporal = (float)((value[47] << 8) | value[48]); // Temperature fault value
- //temporal = (float)((value[49] << 8) | value[50]); // Pv1 voltage fault value 0.1V
- //temporal = (float)((value[51] << 8) | value[52]); // Pv2 voltage fault value 0.1V
- //temporal = (float)((value[53] << 8) | value[54]); // GFC fault value
- solaxX1.errorCode = (value[58] << 24) | (value[57] << 16) | (value[56] << 8) | value[55]; // Error Code
-
- solaxX1.dc1_power = solaxX1.dc1_voltage * solaxX1.dc1_current;
- solaxX1.dc2_power = solaxX1.dc2_voltage * solaxX1.dc2_current;
-
- EnergyUpdateTotal(); // 484.708 kWh
- }
- } else { // end hasAddress
- // check address confirmation from inverter
- if (protocolStatus.inverterAddressSend)
- {
- uint8_t error = solaxX1_RS485Receive(value);
- if (error)
- {
- DEBUG_SENSOR_LOG(PSTR("SX1: Address confirmation response CRC error"));
- }
- else
- {
- if (value[6] == 0x10 && value[7] == 0x81 && value[9] == 0x06)
- {
- DEBUG_SENSOR_LOG(PSTR("SX1: Set hasAddress"));
- protocolStatus.status = 0b00100000; // hasAddress
- }
- }
- }
-
- // Check inverter serial number and send the set address request
- if (protocolStatus.queryOfflineSend)
- {
- uint8_t error = solaxX1_RS485Receive(value);
- if (error)
- {
- DEBUG_SENSOR_LOG(PSTR("SX1: Query Offline response CRC error"));
- }
- else
- {
- // Serial number from query response
- if (value[6] == 0x10 && value[7] == 0x80 && protocolStatus.inverterSnReceived == false)
- {
- for (uint8_t i = 9; i <= 22; i++)
- {
- data[i - 9] = value[i];
- }
- solaxX1_SendInverterAddress();
- protocolStatus.status = 0b1100000; // inverterSnReceived and inverterAddressSend
- DEBUG_SENSOR_LOG(PSTR("SX1: Set inverterSnReceived and inverterAddressSend"));
- }
- }
- }
+ if (solaxX1Serial->available()) {
+ if (solaxX1_RS485Receive(value)) { // CRC-error -> no further action
+ DEBUG_SENSOR_LOG(PSTR("SX1: Data response CRC error"));
+ return;
}
- }
+
+ solaxX1_send_retry = 20; // Inverter is responding
- if (protocolStatus.hasAddress) {
- if (solaxX1_queryData_count <= 0) {
+ if (value[0] != 0xAA || value[1] != 0x55) { // Check for header
+ DEBUG_SENSOR_LOG(PSTR("SX1: Check for header failed"));
+ return;
+ }
+
+ if (value[6] == 0x11 && value[7] == 0x82) { // received "Response for query (live data)"
+ Energy.data_valid[0] = 0;
+
+ solaxX1.temperature = (value[9] << 8) | value[10]; // Temperature
+ solaxX1.energy_today = (float)((value[11] << 8) | value[12]) * 0.1f; // Energy Today
+ solaxX1.dc1_voltage = (float)((value[13] << 8) | value[14]) * 0.1f; // PV1 Voltage
+ solaxX1.dc2_voltage = (float)((value[15] << 8) | value[16]) * 0.1f; // PV2 Voltage
+ solaxX1.dc1_current = (float)((value[17] << 8) | value[18]) * 0.1f; // PV1 Current
+ solaxX1.dc2_current = (float)((value[19] << 8) | value[20]) * 0.1f; // PV2 Current
+ Energy.current[0] = (float)((value[21] << 8) | value[22]) * 0.1f; // AC Current
+ Energy.voltage[0] = (float)((value[23] << 8) | value[24]) * 0.1f; // AC Voltage
+ Energy.frequency[0] = (float)((value[25] << 8) | value[26]) * 0.01f; // AC Frequency
+ Energy.active_power[0] = (float)((value[27] << 8) | value[28]); // AC Power
+ //temporal = (float)((value[29] << 8) | value[30]) * 0.1f; // Not Used
+ Energy.import_active[0] = (float)((value[31] << 24) | (value[32] << 16) | (value[33] << 8) | value[34]) * 0.1f; // Energy Total
+ solaxX1.runtime_total = ((value[35] << 24) | (value[36] << 16) | (value[37] << 8) | value[38]); // Work Time Total
+ solaxX1.runMode = (value[39] << 8) | value[40]; // Work mode
+ //temporal = (float)((value[41] << 8) | value[42]); // Grid voltage fault value 0.1V
+ //temporal = (float)((value[43] << 8) | value[44]); // Gird frequency fault value 0.01Hz
+ //temporal = (float)((value[45] << 8) | value[46]); // Dc injection fault value 1mA
+ //temporal = (float)((value[47] << 8) | value[48]); // Temperature fault value
+ //temporal = (float)((value[49] << 8) | value[50]); // Pv1 voltage fault value 0.1V
+ //temporal = (float)((value[51] << 8) | value[52]); // Pv2 voltage fault value 0.1V
+ //temporal = (float)((value[53] << 8) | value[54]); // GFC fault value
+ solaxX1.errorCode = (value[58] << 24) | (value[57] << 16) | (value[56] << 8) | value[55]; // Error Code
+
+ solaxX1.dc1_power = solaxX1.dc1_voltage * solaxX1.dc1_current;
+ solaxX1.dc2_power = solaxX1.dc2_voltage * solaxX1.dc2_current;
+
+ EnergyUpdateTotal(); // 484.708 kWh
+ DEBUG_SENSOR_LOG(PSTR("SX1: received live data"));
+ return;
+ } // end received "Response for query (live data)"
+
+ if (value[6] == 0x11 && value[7] == 0x83) { // received "Response for query (ID data)"
+ for (i = 49; i <= 62; i++) { // get "real" serial number
+ solaxX1SerialNumber[i - 49] = value[i];
+ }
+ AddLog(LOG_LEVEL_INFO, PSTR("SX1: Inverter serial number: %s"),(char*)solaxX1SerialNumber);
+ DEBUG_SENSOR_LOG(PSTR("SX1: received ID data"));
+ return;
+ } // end received "Response for query (ID data)"
+
+ if (value[6] == 0x10 && value[7] == 0x80) { // received "register request"
+ solaxX1_queryData_count = 5; // give time for next query
+ for (i = 9; i <= 22; i++) { // store serial number for register
+ data[i - 9] = value[i];
+ }
+ DEBUG_SENSOR_LOG(PSTR("SX1: received register request and send register address"));
+ solaxX1_SendInverterAddress(); // "send register address"
+ return;
+ }
+
+ if (value[6] == 0x10 && value[7] == 0x81 && value[9] == 0x06) { // received "address confirm (ACK)"
+ solaxX1_queryData_count = 5; // give time for next query
+ AddressAssigned = true;
+ DEBUG_SENSOR_LOG(PSTR("SX1: received \"address confirm (ACK)\""));
+ return;
+ }
+
+ } // end solaxX1Serial->available()
+
+// DEBUG_SENSOR_LOG(PSTR("SX1: AddressAssigned: %d, solaxX1_queryData_count: %d, solaxX1_send_retry: %d, solaxX1_QueryID_count: %d"), AddressAssigned, solaxX1_queryData_count, solaxX1_send_retry, solaxX1_QueryID_count);
+ if (AddressAssigned) {
+ if (!solaxX1_queryData_count) { // normal periodically query
solaxX1_queryData_count = 5;
- DEBUG_SENSOR_LOG(PSTR("SX1: Send Retry count: %d"), solaxX1_send_retry);
- solaxX1_QueryLiveData();
- }
+ if (solaxX1_QueryID_count) { // normal live query
+ DEBUG_SENSOR_LOG(PSTR("SX1: Send periodically live query"));
+ solaxX1_QueryLiveData();
+ } else { // normal ID query
+ DEBUG_SENSOR_LOG(PSTR("SX1: Send periodically ID query"));
+ solaxX1_QueryIDData();
+ }
+ solaxX1_QueryID_count++; // query ID every 256th time
+ } // end normal periodically query
solaxX1_queryData_count--;
- }
-
- // request to the inverter the serial number if offline
- if (protocolStatus.queryOffline)
- {
- // We sent the message to query inverters in offline status
- source[0] = 0x01;
- destination[1] = 0x00;
- controlCode[0] = 0x10;
- functionCode[0] = 0x00;
- dataLength[0] = 0x00;
- solaxX1_RS485Send(9);
- protocolStatus.status = 0b00010000; // queryOfflineSend
- solaxX1_send_retry = 20;
- DEBUG_SENSOR_LOG(PSTR("SX1: Query Offline Send"));
- }
-
- if (solaxX1_send_retry == 0) {
- if (protocolStatus.hasAddress) {
- protocolStatus.status = 0b00001000; // queryOffline
+ if (!solaxX1_send_retry) { // Inverter went "off"
+ solaxX1_send_retry = 20;
+ DEBUG_SENSOR_LOG(PSTR("SX1: Inverter went \"off\""));
Energy.data_valid[0] = ENERGY_WATCHDOG;
-
solaxX1.temperature = solaxX1.dc1_voltage = solaxX1.dc2_voltage = solaxX1.dc1_current = solaxX1.dc2_current = solaxX1.dc1_power = 0;
solaxX1.dc2_power = Energy.current[0] = Energy.voltage[0] = Energy.frequency[0] = Energy.active_power[0] = 0;
solaxX1.runMode = -1; // off(line)
- } else {
- if (protocolStatus.queryOfflineSend) {
- protocolStatus.status = 0b00001000; // queryOffline
- DEBUG_SENSOR_LOG(PSTR("SX1: Set Query Offline"));
- }
+ AddressAssigned = false;
+ } // end Inverter went "off"
+ } else { // sent query for inverters in offline status
+ if (!solaxX1_send_retry) {
solaxX1_send_retry = 20;
+ DEBUG_SENSOR_LOG(PSTR("SX1: Sent query for inverters in offline state"));
+ solaxX1_QueryOfflineInverters();
}
}
+ solaxX1_send_retry--;
- if (!data_ready && solaxX1_send_retry > 0) { solaxX1_send_retry--; }
+return;
}
void solaxX1SnsInit(void)
{
- AddLog(LOG_LEVEL_DEBUG, PSTR("SX1: Solax X1 Inverter Init"));
- AddLog(LOG_LEVEL_DEBUG, PSTR("SX1: RX-pin: %d, TX-pin: %d, RTS-pin: %d"), Pin(GPIO_SOLAXX1_RX), Pin(GPIO_SOLAXX1_TX), Pin(GPIO_SOLAXX1_RTS));
-// DEBUG_SENSOR_LOG(PSTR("SX1: RX pin: %d, TX pin: %d"), Pin(GPIO_SOLAXX1_RX), Pin(GPIO_SOLAXX1_TX));
- protocolStatus.status = 0b00100000; // hasAddress
-
+ AddLog(LOG_LEVEL_INFO, PSTR("SX1: Init - RX-pin: %d, TX-pin: %d, RTS-pin: %d"), Pin(GPIO_SOLAXX1_RX), Pin(GPIO_SOLAXX1_TX), Pin(GPIO_SOLAXX1_RTS));
solaxX1Serial = new TasmotaSerial(Pin(GPIO_SOLAXX1_RX), Pin(GPIO_SOLAXX1_TX), 1);
if (solaxX1Serial->begin(SOLAXX1_SPEED)) {
if (solaxX1Serial->hardwareSerial()) { ClaimSerial(); }
@@ -426,7 +387,8 @@ const char HTTP_SNS_solaxX1_DATA2[] PROGMEM =
const char HTTP_SNS_solaxX1_DATA3[] PROGMEM =
"{s}" D_SOLAX_X1 " " D_UPTIME "{m}%s " D_UNIT_HOUR "{e}"
"{s}" D_SOLAX_X1 " " D_STATUS "{m}%s"
- "{s}" D_SOLAX_X1 " " D_ERROR "{m}%s";
+ "{s}" D_SOLAX_X1 " " D_ERROR "{m}%s"
+ "{s}" D_SOLAX_X1 " Inverter SN{m}%s";
#endif // USE_WEBSERVER
void solaxX1Show(bool json)
@@ -452,8 +414,7 @@ void solaxX1Show(bool json)
char status[33];
GetTextIndexed(status, sizeof(status), solaxX1.runMode + 1, kSolaxMode);
- if (json)
- {
+ if (json) {
ResponseAppend_P(PSTR(",\"" D_JSON_SOLAR_POWER "\":%s,\"" D_JSON_PV1_VOLTAGE "\":%s,\"" D_JSON_PV1_CURRENT "\":%s,\"" D_JSON_PV1_POWER "\":%s"),
solar_power, pv1_voltage, pv1_current, pv1_power);
#ifdef SOLAXX1_PV2
@@ -477,7 +438,8 @@ void solaxX1Show(bool json)
WSContentSend_Temp(D_SOLAX_X1, solaxX1.temperature);
char errorCodeString[33];
WSContentSend_PD(HTTP_SNS_solaxX1_DATA3, runtime, status,
- GetTextIndexed(errorCodeString, sizeof(errorCodeString), solaxX1_ParseErrorCode(solaxX1.errorCode), kSolaxError));
+ GetTextIndexed(errorCodeString, sizeof(errorCodeString), solaxX1_ParseErrorCode(solaxX1.errorCode), kSolaxError),
+ solaxX1SerialNumber);
#endif // USE_WEBSERVER
}
}
From 9f752b92305d8ec36548626d0d723b95b5cdfa29 Mon Sep 17 00:00:00 2001
From: Roberto Bonacina
Date: Sat, 5 Feb 2022 16:56:21 +0100
Subject: [PATCH 008/355] Adafruit_BusIO: bump library to version 1.11.0
The previous included version (1.0.10) was failing to read more than
32 bytes of data from I2C devices (tested on AMG8833 which typically
reads 128 bytes -whose support is in progress-).
The problem was fixed in version 1.9.0.
Currently, this library is required and used just by the
Adafruit_VEML7700 library.
The VEML7700 sensor has been tested and proved to correctly work.
Signed-off-by: Roberto Bonacina
---
.../Adafruit_BusIO_Register.cpp | 235 ++++++++---
.../Adafruit_BusIO/Adafruit_BusIO_Register.h | 102 +++--
.../Adafruit_BusIO/Adafruit_I2CDevice.cpp | 154 ++++---
.../Adafruit_BusIO/Adafruit_I2CDevice.h | 31 +-
.../Adafruit_BusIO/Adafruit_I2CRegister.h | 4 +-
.../Adafruit_BusIO/Adafruit_SPIDevice.cpp | 398 +++++++++++++-----
.../Adafruit_BusIO/Adafruit_SPIDevice.h | 103 +++--
lib/lib_i2c/Adafruit_BusIO/CMakeLists.txt | 11 +
lib/lib_i2c/Adafruit_BusIO/README.md | 5 +-
lib/lib_i2c/Adafruit_BusIO/component.mk | 1 +
.../i2corspi_register/i2corspi_register.ino | 4 +-
.../spi_register_bits/spi_register_bits.ino | 192 +++++++++
.../examples/spi_registers/spi_registers.ino | 6 +-
lib/lib_i2c/Adafruit_BusIO/library.properties | 2 +-
14 files changed, 952 insertions(+), 296 deletions(-)
create mode 100644 lib/lib_i2c/Adafruit_BusIO/CMakeLists.txt
create mode 100644 lib/lib_i2c/Adafruit_BusIO/component.mk
create mode 100644 lib/lib_i2c/Adafruit_BusIO/examples/spi_register_bits/spi_register_bits.ino
diff --git a/lib/lib_i2c/Adafruit_BusIO/Adafruit_BusIO_Register.cpp b/lib/lib_i2c/Adafruit_BusIO/Adafruit_BusIO_Register.cpp
index 2c2b22e00..f8025257d 100644
--- a/lib/lib_i2c/Adafruit_BusIO/Adafruit_BusIO_Register.cpp
+++ b/lib/lib_i2c/Adafruit_BusIO/Adafruit_BusIO_Register.cpp
@@ -1,86 +1,133 @@
#include
+#if !defined(SPI_INTERFACES_COUNT) || \
+ (defined(SPI_INTERFACES_COUNT) && (SPI_INTERFACES_COUNT > 0))
+
/*!
- * @brief Create a register we access over an I2C Device (which defines the bus and address)
+ * @brief Create a register we access over an I2C Device (which defines the
+ * bus and address)
* @param i2cdevice The I2CDevice to use for underlying I2C access
- * @param reg_addr The address pointer value for the I2C/SMBus register, can be 8 or 16 bits
+ * @param reg_addr The address pointer value for the I2C/SMBus register, can
+ * be 8 or 16 bits
* @param width The width of the register data itself, defaults to 1 byte
- * @param bitorder The bit order of the register (used when width is > 1), defaults to LSBFIRST
- * @param address_width The width of the register address itself, defaults to 1 byte
+ * @param byteorder The byte order of the register (used when width is > 1),
+ * defaults to LSBFIRST
+ * @param address_width The width of the register address itself, defaults
+ * to 1 byte
*/
-Adafruit_BusIO_Register::Adafruit_BusIO_Register(Adafruit_I2CDevice *i2cdevice, uint16_t reg_addr,
- uint8_t width, uint8_t bitorder, uint8_t address_width) {
+Adafruit_BusIO_Register::Adafruit_BusIO_Register(Adafruit_I2CDevice *i2cdevice,
+ uint16_t reg_addr,
+ uint8_t width,
+ uint8_t byteorder,
+ uint8_t address_width) {
_i2cdevice = i2cdevice;
_spidevice = NULL;
_addrwidth = address_width;
_address = reg_addr;
- _bitorder = bitorder;
+ _byteorder = byteorder;
_width = width;
}
/*!
- * @brief Create a register we access over an SPI Device (which defines the bus and CS pin)
- * @param spidevice The SPIDevice to use for underlying I2C access
- * @param reg_addr The address pointer value for the I2C/SMBus register, can be 8 or 16 bits
- * @param type The method we use to read/write data to SPI (which is not as well defined as I2C)
+ * @brief Create a register we access over an SPI Device (which defines the
+ * bus and CS pin)
+ * @param spidevice The SPIDevice to use for underlying SPI access
+ * @param reg_addr The address pointer value for the SPI register, can
+ * be 8 or 16 bits
+ * @param type The method we use to read/write data to SPI (which is not
+ * as well defined as I2C)
* @param width The width of the register data itself, defaults to 1 byte
- * @param bitorder The bit order of the register (used when width is > 1), defaults to LSBFIRST
- * @param address_width The width of the register address itself, defaults to 1 byte
+ * @param byteorder The byte order of the register (used when width is > 1),
+ * defaults to LSBFIRST
+ * @param address_width The width of the register address itself, defaults
+ * to 1 byte
*/
-Adafruit_BusIO_Register::Adafruit_BusIO_Register(Adafruit_SPIDevice *spidevice, uint16_t reg_addr,
- Adafruit_BusIO_SPIRegType type,
- uint8_t width, uint8_t bitorder, uint8_t address_width) {
+Adafruit_BusIO_Register::Adafruit_BusIO_Register(Adafruit_SPIDevice *spidevice,
+ uint16_t reg_addr,
+ Adafruit_BusIO_SPIRegType type,
+ uint8_t width,
+ uint8_t byteorder,
+ uint8_t address_width) {
_spidevice = spidevice;
_spiregtype = type;
_i2cdevice = NULL;
_addrwidth = address_width;
_address = reg_addr;
- _bitorder = bitorder;
+ _byteorder = byteorder;
_width = width;
}
/*!
- * @brief Create a register we access over an I2C or SPI Device. This is a handy function because we
- * can pass in NULL for the unused interface, allowing libraries to mass-define all the registers
- * @param i2cdevice The I2CDevice to use for underlying I2C access, if NULL we use SPI
- * @param spidevice The SPIDevice to use for underlying I2C access, if NULL we use I2C
- * @param reg_addr The address pointer value for the I2C/SMBus register, can be 8 or 16 bits
- * @param type The method we use to read/write data to SPI (which is not as well defined as I2C)
+ * @brief Create a register we access over an I2C or SPI Device. This is a
+ * handy function because we can pass in NULL for the unused interface, allowing
+ * libraries to mass-define all the registers
+ * @param i2cdevice The I2CDevice to use for underlying I2C access, if NULL
+ * we use SPI
+ * @param spidevice The SPIDevice to use for underlying SPI access, if NULL
+ * we use I2C
+ * @param reg_addr The address pointer value for the I2C/SMBus/SPI register,
+ * can be 8 or 16 bits
+ * @param type The method we use to read/write data to SPI (which is not
+ * as well defined as I2C)
* @param width The width of the register data itself, defaults to 1 byte
- * @param bitorder The bit order of the register (used when width is > 1), defaults to LSBFIRST
- * @param address_width The width of the register address itself, defaults to 1 byte
+ * @param byteorder The byte order of the register (used when width is > 1),
+ * defaults to LSBFIRST
+ * @param address_width The width of the register address itself, defaults
+ * to 1 byte
*/
-Adafruit_BusIO_Register::Adafruit_BusIO_Register(Adafruit_I2CDevice *i2cdevice, Adafruit_SPIDevice *spidevice,
- Adafruit_BusIO_SPIRegType type, uint16_t reg_addr,
- uint8_t width, uint8_t bitorder, uint8_t address_width) {
+Adafruit_BusIO_Register::Adafruit_BusIO_Register(
+ Adafruit_I2CDevice *i2cdevice, Adafruit_SPIDevice *spidevice,
+ Adafruit_BusIO_SPIRegType type, uint16_t reg_addr, uint8_t width,
+ uint8_t byteorder, uint8_t address_width) {
_spidevice = spidevice;
_i2cdevice = i2cdevice;
_spiregtype = type;
_addrwidth = address_width;
_address = reg_addr;
- _bitorder = bitorder;
+ _byteorder = byteorder;
_width = width;
}
-
/*!
* @brief Write a buffer of data to the register location
* @param buffer Pointer to data to write
* @param len Number of bytes to write
- * @return True on successful write (only really useful for I2C as SPI is uncheckable)
+ * @return True on successful write (only really useful for I2C as SPI is
+ * uncheckable)
*/
bool Adafruit_BusIO_Register::write(uint8_t *buffer, uint8_t len) {
- uint8_t addrbuffer[2] = {(uint8_t)(_address & 0xFF), (uint8_t)(_address>>8)};
+ uint8_t addrbuffer[2] = {(uint8_t)(_address & 0xFF),
+ (uint8_t)(_address >> 8)};
if (_i2cdevice) {
return _i2cdevice->write(buffer, len, true, addrbuffer, _addrwidth);
}
if (_spidevice) {
+ if (_spiregtype == ADDRESSED_OPCODE_BIT0_LOW_TO_WRITE) {
+ // very special case!
+
+ // pass the special opcode address which we set as the high byte of the
+ // regaddr
+ addrbuffer[0] =
+ (uint8_t)(_address >> 8) & ~0x01; // set bottom bit low to write
+ // the 'actual' reg addr is the second byte then
+ addrbuffer[1] = (uint8_t)(_address & 0xFF);
+ // the address appears to be a byte longer
+ return _spidevice->write(buffer, len, addrbuffer, _addrwidth + 1);
+ }
+
if (_spiregtype == ADDRBIT8_HIGH_TOREAD) {
addrbuffer[0] &= ~0x80;
}
- return _spidevice->write( buffer, len, addrbuffer, _addrwidth);
+ if (_spiregtype == ADDRBIT8_HIGH_TOWRITE) {
+ addrbuffer[0] |= 0x80;
+ }
+ if (_spiregtype == AD8_HIGH_TOREAD_AD7_HIGH_TOINC) {
+ addrbuffer[0] &= ~0x80;
+ addrbuffer[0] |= 0x40;
+ }
+ return _spidevice->write(buffer, len, addrbuffer, _addrwidth);
}
return false;
}
@@ -89,7 +136,8 @@ bool Adafruit_BusIO_Register::write(uint8_t *buffer, uint8_t len) {
* @brief Write up to 4 bytes of data to the register location
* @param value Data to write
* @param numbytes How many bytes from 'value' to write
- * @return True on successful write (only really useful for I2C as SPI is uncheckable)
+ * @return True on successful write (only really useful for I2C as SPI is
+ * uncheckable)
*/
bool Adafruit_BusIO_Register::write(uint32_t value, uint8_t numbytes) {
if (numbytes == 0) {
@@ -99,11 +147,14 @@ bool Adafruit_BusIO_Register::write(uint32_t value, uint8_t numbytes) {
return false;
}
- for (int i=0; i>= 8;
}
@@ -111,45 +162,72 @@ bool Adafruit_BusIO_Register::write(uint32_t value, uint8_t numbytes) {
}
/*!
- * @brief Read data from the register location. This does not do any error checking!
+ * @brief Read data from the register location. This does not do any error
+ * checking!
* @return Returns 0xFFFFFFFF on failure, value otherwise
*/
uint32_t Adafruit_BusIO_Register::read(void) {
- if (! read(_buffer, _width)) {
+ if (!read(_buffer, _width)) {
return -1;
}
uint32_t value = 0;
- for (int i=0; i < _width; i++) {
- value <<= 8;
- if (_bitorder == LSBFIRST) {
- value |= _buffer[_width-i-1];
- } else {
- value |= _buffer[i];
- }
- }
+ for (int i = 0; i < _width; i++) {
+ value <<= 8;
+ if (_byteorder == LSBFIRST) {
+ value |= _buffer[_width - i - 1];
+ } else {
+ value |= _buffer[i];
+ }
+ }
- return value;
+ return value;
}
+/*!
+ * @brief Read cached data from last time we wrote to this register
+ * @return Returns 0xFFFFFFFF on failure, value otherwise
+ */
+uint32_t Adafruit_BusIO_Register::readCached(void) { return _cached; }
/*!
* @brief Read a buffer of data from the register location
* @param buffer Pointer to data to read into
* @param len Number of bytes to read
- * @return True on successful write (only really useful for I2C as SPI is uncheckable)
+ * @return True on successful write (only really useful for I2C as SPI is
+ * uncheckable)
*/
bool Adafruit_BusIO_Register::read(uint8_t *buffer, uint8_t len) {
- uint8_t addrbuffer[2] = {(uint8_t)(_address & 0xFF), (uint8_t)(_address>>8)};
+ uint8_t addrbuffer[2] = {(uint8_t)(_address & 0xFF),
+ (uint8_t)(_address >> 8)};
if (_i2cdevice) {
return _i2cdevice->write_then_read(addrbuffer, _addrwidth, buffer, len);
}
if (_spidevice) {
+ if (_spiregtype == ADDRESSED_OPCODE_BIT0_LOW_TO_WRITE) {
+ // very special case!
+
+ // pass the special opcode address which we set as the high byte of the
+ // regaddr
+ addrbuffer[0] =
+ (uint8_t)(_address >> 8) | 0x01; // set bottom bit high to read
+ // the 'actual' reg addr is the second byte then
+ addrbuffer[1] = (uint8_t)(_address & 0xFF);
+ // the address appears to be a byte longer
+ return _spidevice->write_then_read(addrbuffer, _addrwidth + 1, buffer,
+ len);
+ }
if (_spiregtype == ADDRBIT8_HIGH_TOREAD) {
addrbuffer[0] |= 0x80;
}
+ if (_spiregtype == ADDRBIT8_HIGH_TOWRITE) {
+ addrbuffer[0] &= ~0x80;
+ }
+ if (_spiregtype == AD8_HIGH_TOREAD_AD7_HIGH_TOINC) {
+ addrbuffer[0] |= 0x80 | 0x40;
+ }
return _spidevice->write_then_read(addrbuffer, _addrwidth, buffer, len);
}
return false;
@@ -158,14 +236,15 @@ bool Adafruit_BusIO_Register::read(uint8_t *buffer, uint8_t len) {
/*!
* @brief Read 2 bytes of data from the register location
* @param value Pointer to uint16_t variable to read into
- * @return True on successful write (only really useful for I2C as SPI is uncheckable)
+ * @return True on successful write (only really useful for I2C as SPI is
+ * uncheckable)
*/
bool Adafruit_BusIO_Register::read(uint16_t *value) {
- if (! read(_buffer, 2)) {
+ if (!read(_buffer, 2)) {
return false;
}
- if (_bitorder == LSBFIRST) {
+ if (_byteorder == LSBFIRST) {
*value = _buffer[1];
*value <<= 8;
*value |= _buffer[0];
@@ -180,10 +259,11 @@ bool Adafruit_BusIO_Register::read(uint16_t *value) {
/*!
* @brief Read 1 byte of data from the register location
* @param value Pointer to uint8_t variable to read into
- * @return True on successful write (only really useful for I2C as SPI is uncheckable)
+ * @return True on successful write (only really useful for I2C as SPI is
+ * uncheckable)
*/
bool Adafruit_BusIO_Register::read(uint8_t *value) {
- if (! read(_buffer, 1)) {
+ if (!read(_buffer, 1)) {
return false;
}
@@ -197,7 +277,8 @@ bool Adafruit_BusIO_Register::read(uint8_t *value) {
*/
void Adafruit_BusIO_Register::print(Stream *s) {
uint32_t val = read();
- s->print("0x"); s->print(val, HEX);
+ s->print("0x");
+ s->print(val, HEX);
}
/*!
@@ -209,14 +290,15 @@ void Adafruit_BusIO_Register::println(Stream *s) {
s->println();
}
-
/*!
- * @brief Create a slice of the register that we can address without touching other bits
+ * @brief Create a slice of the register that we can address without
+ * touching other bits
* @param reg The Adafruit_BusIO_Register which defines the bus/register
* @param bits The number of bits wide we are slicing
* @param shift The number of bits that our bit-slice is shifted from LSB
*/
-Adafruit_BusIO_RegisterBits::Adafruit_BusIO_RegisterBits(Adafruit_BusIO_Register *reg, uint8_t bits, uint8_t shift) {
+Adafruit_BusIO_RegisterBits::Adafruit_BusIO_RegisterBits(
+ Adafruit_BusIO_Register *reg, uint8_t bits, uint8_t shift) {
_register = reg;
_bits = bits;
_shift = shift;
@@ -232,12 +314,13 @@ uint32_t Adafruit_BusIO_RegisterBits::read(void) {
return val & ((1 << (_bits)) - 1);
}
-
/*!
* @brief Write 4 bytes of data to the register
* @param data The 4 bytes to write
+ * @return True on successful write (only really useful for I2C as SPI is
+ * uncheckable)
*/
-void Adafruit_BusIO_RegisterBits::write(uint32_t data) {
+bool Adafruit_BusIO_RegisterBits::write(uint32_t data) {
uint32_t val = _register->read();
// mask off the data before writing
@@ -245,10 +328,10 @@ void Adafruit_BusIO_RegisterBits::write(uint32_t data) {
data &= mask;
mask <<= _shift;
- val &= ~mask; // remove the current data at that spot
+ val &= ~mask; // remove the current data at that spot
val |= data << _shift; // and add in the new data
-
- _register->write(val, _register->width());
+
+ return _register->write(val, _register->width());
}
/*!
@@ -256,3 +339,27 @@ void Adafruit_BusIO_RegisterBits::write(uint32_t data) {
* @returns The data width used when initializing the register
*/
uint8_t Adafruit_BusIO_Register::width(void) { return _width; }
+
+/*!
+ * @brief Set the default width of data
+ * @param width the default width of data read from register
+ */
+void Adafruit_BusIO_Register::setWidth(uint8_t width) { _width = width; }
+
+/*!
+ * @brief Set register address
+ * @param address the address from register
+ */
+void Adafruit_BusIO_Register::setAddress(uint16_t address) {
+ _address = address;
+}
+
+/*!
+ * @brief Set the width of register address
+ * @param address_width the width for register address
+ */
+void Adafruit_BusIO_Register::setAddressWidth(uint16_t address_width) {
+ _addrwidth = address_width;
+}
+
+#endif // SPI exists
diff --git a/lib/lib_i2c/Adafruit_BusIO/Adafruit_BusIO_Register.h b/lib/lib_i2c/Adafruit_BusIO/Adafruit_BusIO_Register.h
index 45ae1e146..c6d58de60 100644
--- a/lib/lib_i2c/Adafruit_BusIO/Adafruit_BusIO_Register.h
+++ b/lib/lib_i2c/Adafruit_BusIO/Adafruit_BusIO_Register.h
@@ -1,69 +1,105 @@
-#include
-#include
-#include
-
-
#ifndef Adafruit_BusIO_Register_h
#define Adafruit_BusIO_Register_h
+#include
+
+#if !defined(SPI_INTERFACES_COUNT) || \
+ (defined(SPI_INTERFACES_COUNT) && (SPI_INTERFACES_COUNT > 0))
+
+#include
+#include
+
typedef enum _Adafruit_BusIO_SPIRegType {
ADDRBIT8_HIGH_TOREAD = 0,
+ /*!<
+ * ADDRBIT8_HIGH_TOREAD
+ * When reading a register you must actually send the value 0x80 + register
+ * address to the device. e.g. To read the register 0x0B the register value
+ * 0x8B is sent and to write 0x0B is sent.
+ */
+ AD8_HIGH_TOREAD_AD7_HIGH_TOINC = 1,
+
+ /*!<
+ * ADDRBIT8_HIGH_TOWRITE
+ * When writing to a register you must actually send the value 0x80 +
+ * the register address to the device. e.g. To write to the register 0x19 the
+ * register value 0x99 is sent and to read 0x19 is sent.
+ */
+ ADDRBIT8_HIGH_TOWRITE = 2,
+
+ /*!<
+ * ADDRESSED_OPCODE_LOWBIT_TO_WRITE
+ * Used by the MCP23S series, we send 0x40 |'rd with the opcode
+ * Then set the lowest bit to write
+ */
+ ADDRESSED_OPCODE_BIT0_LOW_TO_WRITE = 3,
+
} Adafruit_BusIO_SPIRegType;
/*!
- * @brief The class which defines a device register (a location to read/write data from)
+ * @brief The class which defines a device register (a location to read/write
+ * data from)
*/
class Adafruit_BusIO_Register {
- public:
- Adafruit_BusIO_Register(Adafruit_I2CDevice *i2cdevice, uint16_t reg_addr,
- uint8_t width=1, uint8_t bitorder=LSBFIRST,
- uint8_t address_width=1);
- Adafruit_BusIO_Register(Adafruit_SPIDevice *spidevice, uint16_t reg_addr,
- Adafruit_BusIO_SPIRegType type,
- uint8_t width=1, uint8_t bitorder=LSBFIRST,
- uint8_t address_width=1);
+public:
+ Adafruit_BusIO_Register(Adafruit_I2CDevice *i2cdevice, uint16_t reg_addr,
+ uint8_t width = 1, uint8_t byteorder = LSBFIRST,
+ uint8_t address_width = 1);
+
+ Adafruit_BusIO_Register(Adafruit_SPIDevice *spidevice, uint16_t reg_addr,
+ Adafruit_BusIO_SPIRegType type, uint8_t width = 1,
+ uint8_t byteorder = LSBFIRST,
+ uint8_t address_width = 1);
Adafruit_BusIO_Register(Adafruit_I2CDevice *i2cdevice,
- Adafruit_SPIDevice *spidevice,
- Adafruit_BusIO_SPIRegType type,
- uint16_t reg_addr,
- uint8_t width=1, uint8_t bitorder=LSBFIRST,
- uint8_t address_width=1);
+ Adafruit_SPIDevice *spidevice,
+ Adafruit_BusIO_SPIRegType type, uint16_t reg_addr,
+ uint8_t width = 1, uint8_t byteorder = LSBFIRST,
+ uint8_t address_width = 1);
bool read(uint8_t *buffer, uint8_t len);
bool read(uint8_t *value);
bool read(uint16_t *value);
uint32_t read(void);
+ uint32_t readCached(void);
bool write(uint8_t *buffer, uint8_t len);
- bool write(uint32_t value, uint8_t numbytes=0);
+ bool write(uint32_t value, uint8_t numbytes = 0);
uint8_t width(void);
- void print(Stream *s=&Serial);
- void println(Stream *s=&Serial);
+ void setWidth(uint8_t width);
+ void setAddress(uint16_t address);
+ void setAddressWidth(uint16_t address_width);
- private:
+ void print(Stream *s = &Serial);
+ void println(Stream *s = &Serial);
+
+private:
Adafruit_I2CDevice *_i2cdevice;
Adafruit_SPIDevice *_spidevice;
Adafruit_BusIO_SPIRegType _spiregtype;
uint16_t _address;
- uint8_t _width, _addrwidth, _bitorder;
- uint8_t _buffer[4]; // we wont support anything larger than uint32 for non-buffered read
+ uint8_t _width, _addrwidth, _byteorder;
+ uint8_t _buffer[4]; // we won't support anything larger than uint32 for
+ // non-buffered read
+ uint32_t _cached = 0;
};
-
/*!
- * @brief The class which defines a slice of bits from within a device register (a location to read/write data from)
+ * @brief The class which defines a slice of bits from within a device register
+ * (a location to read/write data from)
*/
class Adafruit_BusIO_RegisterBits {
- public:
- Adafruit_BusIO_RegisterBits(Adafruit_BusIO_Register *reg, uint8_t bits, uint8_t shift);
- void write(uint32_t value);
+public:
+ Adafruit_BusIO_RegisterBits(Adafruit_BusIO_Register *reg, uint8_t bits,
+ uint8_t shift);
+ bool write(uint32_t value);
uint32_t read(void);
- private:
+
+private:
Adafruit_BusIO_Register *_register;
uint8_t _bits, _shift;
};
-
-#endif //BusIO_Register_h
+#endif // SPI exists
+#endif // BusIO_Register_h
diff --git a/lib/lib_i2c/Adafruit_BusIO/Adafruit_I2CDevice.cpp b/lib/lib_i2c/Adafruit_BusIO/Adafruit_I2CDevice.cpp
index 7813a6df7..716fe1eaf 100644
--- a/lib/lib_i2c/Adafruit_BusIO/Adafruit_I2CDevice.cpp
+++ b/lib/lib_i2c/Adafruit_BusIO/Adafruit_I2CDevice.cpp
@@ -1,5 +1,4 @@
-#include
-#include
+#include "Adafruit_I2CDevice.h"
//#define DEBUG_SERIAL Serial
@@ -21,20 +20,37 @@ Adafruit_I2CDevice::Adafruit_I2CDevice(uint8_t addr, TwoWire *theWire) {
/*!
* @brief Initializes and does basic address detection
- * @param addr_detect Whether we should attempt to detect the I2C address with a scan.
- * 99% of sensors/devices don't mind but once in a while, they spaz on a scan!
+ * @param addr_detect Whether we should attempt to detect the I2C address
+ * with a scan. 99% of sensors/devices don't mind but once in a while, they spaz
+ * on a scan!
* @return True if I2C initialized and a device with the addr found
*/
bool Adafruit_I2CDevice::begin(bool addr_detect) {
_wire->begin();
_begun = true;
-
+
if (addr_detect) {
return detected();
}
return true;
}
+/*!
+ * @brief De-initialize device, turn off the Wire interface
+ */
+void Adafruit_I2CDevice::end(void) {
+ // Not all port implement Wire::end(), such as
+ // - ESP8266
+ // - AVR core without WIRE_HAS_END
+ // - ESP32: end() is implemented since 2.0.1 which is latest at the moment.
+ // Temporarily disable for now to give time for user to update.
+#if !(defined(ESP8266) || \
+ (defined(ARDUINO_ARCH_AVR) && !defined(WIRE_HAS_END)) || \
+ defined(ARDUINO_ARCH_ESP32))
+ _wire->end();
+ _begun = false;
+#endif
+}
/*!
* @brief Scans I2C for the address - note will give a false-positive
@@ -49,24 +65,35 @@ bool Adafruit_I2CDevice::detected(void) {
// A basic scanner, see if it ACK's
_wire->beginTransmission(_addr);
- if (_wire->endTransmission () == 0) {
+ if (_wire->endTransmission() == 0) {
+#ifdef DEBUG_SERIAL
+ DEBUG_SERIAL.println(F("Detected"));
+#endif
return true;
}
+#ifdef DEBUG_SERIAL
+ DEBUG_SERIAL.println(F("Not detected"));
+#endif
return false;
}
/*!
- * @brief Write a buffer or two to the I2C device. Cannot be more than maxBufferSize() bytes.
- * @param buffer Pointer to buffer of data to write
+ * @brief Write a buffer or two to the I2C device. Cannot be more than
+ * maxBufferSize() bytes.
+ * @param buffer Pointer to buffer of data to write. This is const to
+ * ensure the content of this buffer doesn't change.
* @param len Number of bytes from buffer to write
- * @param prefix_buffer Pointer to optional array of data to write before buffer.
- * Cannot be more than maxBufferSize() bytes.
+ * @param prefix_buffer Pointer to optional array of data to write before
+ * buffer. Cannot be more than maxBufferSize() bytes. This is const to
+ * ensure the content of this buffer doesn't change.
* @param prefix_len Number of bytes from prefix buffer to write
* @param stop Whether to send an I2C STOP signal on write
* @return True if write was successful, otherwise false.
*/
-bool Adafruit_I2CDevice::write(uint8_t *buffer, size_t len, bool stop, uint8_t *prefix_buffer, size_t prefix_len) {
- if ((len+prefix_len) > maxBufferSize()) {
+bool Adafruit_I2CDevice::write(const uint8_t *buffer, size_t len, bool stop,
+ const uint8_t *prefix_buffer,
+ size_t prefix_len) {
+ if ((len + prefix_len) > maxBufferSize()) {
// currently not guaranteed to work if more than 32 bytes!
// we will need to find out if some platforms have larger
// I2C buffer sizes :/
@@ -97,45 +124,47 @@ bool Adafruit_I2CDevice::write(uint8_t *buffer, size_t len, bool stop, uint8_t *
}
#ifdef DEBUG_SERIAL
- DEBUG_SERIAL.print(F("\tI2CDevice Wrote: "));
+
+ DEBUG_SERIAL.print(F("\tI2CWRITE @ 0x"));
+ DEBUG_SERIAL.print(_addr, HEX);
+ DEBUG_SERIAL.print(F(" :: "));
if ((prefix_len != 0) && (prefix_buffer != NULL)) {
- for (uint16_t i=0; iendTransmission(stop) == 0) {
#ifdef DEBUG_SERIAL
- DEBUG_SERIAL.println("Sent!");
+ DEBUG_SERIAL.println();
+ // DEBUG_SERIAL.println("Sent!");
#endif
return true;
} else {
#ifdef DEBUG_SERIAL
- DEBUG_SERIAL.println("Failed to send!");
+ DEBUG_SERIAL.println("\tFailed to send!");
#endif
return false;
}
}
-
/*!
- * @brief Read from I2C into a buffer from the I2C device.
+ * @brief Read from I2C into a buffer from the I2C device.
* Cannot be more than maxBufferSize() bytes.
* @param buffer Pointer to buffer of data to read into
* @param len Number of bytes from buffer to read.
@@ -143,17 +172,25 @@ bool Adafruit_I2CDevice::write(uint8_t *buffer, size_t len, bool stop, uint8_t *
* @return True if read was successful, otherwise false.
*/
bool Adafruit_I2CDevice::read(uint8_t *buffer, size_t len, bool stop) {
- if (len > maxBufferSize()) {
- // currently not guaranteed to work if more than 32 bytes!
- // we will need to find out if some platforms have larger
- // I2C buffer sizes :/
-#ifdef DEBUG_SERIAL
- DEBUG_SERIAL.println(F("\tI2CDevice could not read such a large buffer"));
-#endif
- return false;
+ size_t pos = 0;
+ while (pos < len) {
+ size_t read_len =
+ ((len - pos) > maxBufferSize()) ? maxBufferSize() : (len - pos);
+ bool read_stop = (pos < (len - read_len)) ? false : stop;
+ if (!_read(buffer + pos, read_len, read_stop))
+ return false;
+ pos += read_len;
}
+ return true;
+}
+bool Adafruit_I2CDevice::_read(uint8_t *buffer, size_t len, bool stop) {
+#if defined(TinyWireM_h)
+ size_t recv = _wire->requestFrom((uint8_t)_addr, (uint8_t)len);
+#else
size_t recv = _wire->requestFrom((uint8_t)_addr, (uint8_t)len, (uint8_t)stop);
+#endif
+
if (recv != len) {
// Not enough data available to fulfill our obligation!
#ifdef DEBUG_SERIAL
@@ -163,15 +200,17 @@ bool Adafruit_I2CDevice::read(uint8_t *buffer, size_t len, bool stop) {
return false;
}
- for (uint16_t i=0; iread();
}
#ifdef DEBUG_SERIAL
- DEBUG_SERIAL.print(F("\tI2CDevice Read: "));
- for (uint16_t i=0; i= 157) && !defined(ARDUINO_STM32_FEATHER) && !defined(TinyWireM_h)
+ _wire->setClock(desiredclk);
+ return true;
+#else
+ (void)desiredclk;
+ return false;
+#endif
}
diff --git a/lib/lib_i2c/Adafruit_BusIO/Adafruit_I2CDevice.h b/lib/lib_i2c/Adafruit_BusIO/Adafruit_I2CDevice.h
index be0a6c962..5baa6fda8 100644
--- a/lib/lib_i2c/Adafruit_BusIO/Adafruit_I2CDevice.h
+++ b/lib/lib_i2c/Adafruit_BusIO/Adafruit_I2CDevice.h
@@ -1,29 +1,36 @@
-#include
-
#ifndef Adafruit_I2CDevice_h
#define Adafruit_I2CDevice_h
+#include
+#include
+
///< The class which defines how we will talk to this device over I2C
class Adafruit_I2CDevice {
- public:
- Adafruit_I2CDevice(uint8_t addr, TwoWire *theWire=&Wire);
+public:
+ Adafruit_I2CDevice(uint8_t addr, TwoWire *theWire = &Wire);
uint8_t address(void);
- bool begin(bool addr_detect=true);
+ bool begin(bool addr_detect = true);
+ void end(void);
bool detected(void);
- bool read(uint8_t *buffer, size_t len, bool stop=true);
- bool write(uint8_t *buffer, size_t len, bool stop=true, uint8_t *prefix_buffer=NULL, size_t prefix_len=0);
- bool write_then_read(uint8_t *write_buffer, size_t write_len, uint8_t *read_buffer, size_t read_len, bool stop=false);
+ bool read(uint8_t *buffer, size_t len, bool stop = true);
+ bool write(const uint8_t *buffer, size_t len, bool stop = true,
+ const uint8_t *prefix_buffer = NULL, size_t prefix_len = 0);
+ bool write_then_read(const uint8_t *write_buffer, size_t write_len,
+ uint8_t *read_buffer, size_t read_len,
+ bool stop = false);
+ bool setSpeed(uint32_t desiredclk);
/*! @brief How many bytes we can read in a transaction
- * @return The size of the Wire receive/transmit buffer */
- uint16_t maxBufferSize() { return _maxBufferSize; }
+ * @return The size of the Wire receive/transmit buffer */
+ size_t maxBufferSize() { return _maxBufferSize; }
- private:
+private:
uint8_t _addr;
TwoWire *_wire;
bool _begun;
- uint16_t _maxBufferSize;
+ size_t _maxBufferSize;
+ bool _read(uint8_t *buffer, size_t len, bool stop);
};
#endif // Adafruit_I2CDevice_h
diff --git a/lib/lib_i2c/Adafruit_BusIO/Adafruit_I2CRegister.h b/lib/lib_i2c/Adafruit_BusIO/Adafruit_I2CRegister.h
index 703e93b76..186850fa6 100644
--- a/lib/lib_i2c/Adafruit_BusIO/Adafruit_I2CRegister.h
+++ b/lib/lib_i2c/Adafruit_BusIO/Adafruit_I2CRegister.h
@@ -1,7 +1,9 @@
-#include "Adafruit_BusIO_Register.h"
#ifndef _ADAFRUIT_I2C_REGISTER_H_
#define _ADAFRUIT_I2C_REGISTER_H_
+#include
+#include
+
typedef Adafruit_BusIO_Register Adafruit_I2CRegister;
typedef Adafruit_BusIO_RegisterBits Adafruit_I2CRegisterBits;
diff --git a/lib/lib_i2c/Adafruit_BusIO/Adafruit_SPIDevice.cpp b/lib/lib_i2c/Adafruit_BusIO/Adafruit_SPIDevice.cpp
index 1d599bb11..fdd50c0e8 100644
--- a/lib/lib_i2c/Adafruit_BusIO/Adafruit_SPIDevice.cpp
+++ b/lib/lib_i2c/Adafruit_BusIO/Adafruit_SPIDevice.cpp
@@ -1,17 +1,22 @@
-#include
-#include
+#include "Adafruit_SPIDevice.h"
+
+#if !defined(SPI_INTERFACES_COUNT) || \
+ (defined(SPI_INTERFACES_COUNT) && (SPI_INTERFACES_COUNT > 0))
//#define DEBUG_SERIAL Serial
/*!
- * @brief Create an SPI device with the given CS pin and settins
+ * @brief Create an SPI device with the given CS pin and settings
* @param cspin The arduino pin number to use for chip select
* @param freq The SPI clock frequency to use, defaults to 1MHz
- * @param dataOrder The SPI data order to use for bits within each byte, defaults to SPI_BITORDER_MSBFIRST
+ * @param dataOrder The SPI data order to use for bits within each byte,
+ * defaults to SPI_BITORDER_MSBFIRST
* @param dataMode The SPI mode to use, defaults to SPI_MODE0
* @param theSPI The SPI bus to use, defaults to &theSPI
*/
-Adafruit_SPIDevice::Adafruit_SPIDevice(int8_t cspin, uint32_t freq, BitOrder dataOrder, uint8_t dataMode, SPIClass *theSPI) {
+Adafruit_SPIDevice::Adafruit_SPIDevice(int8_t cspin, uint32_t freq,
+ BusIOBitOrder dataOrder,
+ uint8_t dataMode, SPIClass *theSPI) {
_cs = cspin;
_sck = _mosi = _miso = -1;
_spi = theSPI;
@@ -23,21 +28,42 @@ Adafruit_SPIDevice::Adafruit_SPIDevice(int8_t cspin, uint32_t freq, BitOrder dat
}
/*!
- * @brief Create an SPI device with the given CS pin and settins
+ * @brief Create an SPI device with the given CS pin and settings
* @param cspin The arduino pin number to use for chip select
* @param sckpin The arduino pin number to use for SCK
- * @param misopin The arduino pin number to use for MISO, set to -1 if not used
- * @param mosipin The arduino pin number to use for MOSI, set to -1 if not used
+ * @param misopin The arduino pin number to use for MISO, set to -1 if not
+ * used
+ * @param mosipin The arduino pin number to use for MOSI, set to -1 if not
+ * used
* @param freq The SPI clock frequency to use, defaults to 1MHz
- * @param dataOrder The SPI data order to use for bits within each byte, defaults to SPI_BITORDER_MSBFIRST
+ * @param dataOrder The SPI data order to use for bits within each byte,
+ * defaults to SPI_BITORDER_MSBFIRST
* @param dataMode The SPI mode to use, defaults to SPI_MODE0
*/
-Adafruit_SPIDevice::Adafruit_SPIDevice(int8_t cspin, int8_t sckpin, int8_t misopin, int8_t mosipin,
- uint32_t freq, BitOrder dataOrder, uint8_t dataMode) {
+Adafruit_SPIDevice::Adafruit_SPIDevice(int8_t cspin, int8_t sckpin,
+ int8_t misopin, int8_t mosipin,
+ uint32_t freq, BusIOBitOrder dataOrder,
+ uint8_t dataMode) {
_cs = cspin;
_sck = sckpin;
_miso = misopin;
_mosi = mosipin;
+
+#ifdef BUSIO_USE_FAST_PINIO
+ csPort = (BusIO_PortReg *)portOutputRegister(digitalPinToPort(cspin));
+ csPinMask = digitalPinToBitMask(cspin);
+ if (mosipin != -1) {
+ mosiPort = (BusIO_PortReg *)portOutputRegister(digitalPinToPort(mosipin));
+ mosiPinMask = digitalPinToBitMask(mosipin);
+ }
+ if (misopin != -1) {
+ misoPort = (BusIO_PortReg *)portInputRegister(digitalPinToPort(misopin));
+ misoPinMask = digitalPinToBitMask(misopin);
+ }
+ clkPort = (BusIO_PortReg *)portOutputRegister(digitalPinToPort(sckpin));
+ clkPinMask = digitalPinToBitMask(sckpin);
+#endif
+
_freq = freq;
_dataOrder = dataOrder;
_dataMode = dataMode;
@@ -46,24 +72,38 @@ Adafruit_SPIDevice::Adafruit_SPIDevice(int8_t cspin, int8_t sckpin, int8_t misop
_spi = NULL;
}
+/*!
+ * @brief Release memory allocated in constructors
+ */
+Adafruit_SPIDevice::~Adafruit_SPIDevice() {
+ if (_spiSetting) {
+ delete _spiSetting;
+ _spiSetting = nullptr;
+ }
+}
/*!
* @brief Initializes SPI bus and sets CS pin high
- * @return Always returns true because there's no way to test success of SPI init
+ * @return Always returns true because there's no way to test success of SPI
+ * init
*/
bool Adafruit_SPIDevice::begin(void) {
- pinMode(_cs, OUTPUT);
- digitalWrite(_cs, HIGH);
+ if (_cs != -1) {
+ pinMode(_cs, OUTPUT);
+ digitalWrite(_cs, HIGH);
+ }
if (_spi) { // hardware SPI
_spi->begin();
} else {
pinMode(_sck, OUTPUT);
- if (_dataMode==SPI_MODE0) {
- digitalWrite(_sck, HIGH);
- } else {
+ if ((_dataMode == SPI_MODE0) || (_dataMode == SPI_MODE1)) {
+ // idle low on mode 0 and 1
digitalWrite(_sck, LOW);
+ } else {
+ // idle high on mode 2 or 3
+ digitalWrite(_sck, HIGH);
}
if (_mosi != -1) {
pinMode(_mosi, OUTPUT);
@@ -73,12 +113,11 @@ bool Adafruit_SPIDevice::begin(void) {
pinMode(_miso, INPUT);
}
}
-
+
_begun = true;
return true;
}
-
/*!
* @brief Transfer (send/receive) one byte over hard/soft SPI
* @param buffer The buffer to send and receive at the same time
@@ -87,60 +126,135 @@ bool Adafruit_SPIDevice::begin(void) {
void Adafruit_SPIDevice::transfer(uint8_t *buffer, size_t len) {
if (_spi) {
// hardware SPI is easy
+
+#if defined(SPARK)
+ _spi->transfer(buffer, buffer, len, NULL);
+#elif defined(STM32)
+ for (size_t i = 0; i < len; i++) {
+ _spi->transfer(buffer[i]);
+ }
+#else
_spi->transfer(buffer, len);
+#endif
return;
}
+ uint8_t startbit;
+ if (_dataOrder == SPI_BITORDER_LSBFIRST) {
+ startbit = 0x1;
+ } else {
+ startbit = 0x80;
+ }
+
+ bool towrite, lastmosi = !(buffer[0] & startbit);
+ uint8_t bitdelay_us = (1000000 / _freq) / 2;
+
// for softSPI we'll do it by hand
- for (size_t i=0; i> b) & 0x1) << (7-b);
- }
- send = temp;
- }
- for (int b=7; b>=0; b--) {
- reply <<= 1;
- if (_dataMode == SPI_MODE0) {
- digitalWrite(_sck, LOW);
- digitalWrite(_mosi, send & (1< 0x");
+ */
- if (_dataOrder == SPI_BITORDER_LSBFIRST) {
- // LSB is rare, if it happens we'll just flip the bits around for them
- uint8_t temp = 0;
- for (uint8_t b=0; b<8; b++) {
- temp |= ((reply >> b) & 0x1) << (7-b);
- }
- reply = temp;
- }
+ // Serial.print(send, HEX);
+ for (uint8_t b = startbit; b != 0;
+ b = (_dataOrder == SPI_BITORDER_LSBFIRST) ? b << 1 : b >> 1) {
- buffer[i] = reply;
+ if (bitdelay_us) {
+ delayMicroseconds(bitdelay_us);
+ }
+
+ if (_dataMode == SPI_MODE0 || _dataMode == SPI_MODE2) {
+ towrite = send & b;
+ if ((_mosi != -1) && (lastmosi != towrite)) {
+#ifdef BUSIO_USE_FAST_PINIO
+ if (towrite)
+ *mosiPort |= mosiPinMask;
+ else
+ *mosiPort &= ~mosiPinMask;
+#else
+ digitalWrite(_mosi, towrite);
+#endif
+ lastmosi = towrite;
+ }
+
+#ifdef BUSIO_USE_FAST_PINIO
+ *clkPort |= clkPinMask; // Clock high
+#else
+ digitalWrite(_sck, HIGH);
+#endif
+
+ if (bitdelay_us) {
+ delayMicroseconds(bitdelay_us);
+ }
+
+ if (_miso != -1) {
+#ifdef BUSIO_USE_FAST_PINIO
+ if (*misoPort & misoPinMask) {
+#else
+ if (digitalRead(_miso)) {
+#endif
+ reply |= b;
+ }
+ }
+
+#ifdef BUSIO_USE_FAST_PINIO
+ *clkPort &= ~clkPinMask; // Clock low
+#else
+ digitalWrite(_sck, LOW);
+#endif
+ } else { // if (_dataMode == SPI_MODE1 || _dataMode == SPI_MODE3)
+
+#ifdef BUSIO_USE_FAST_PINIO
+ *clkPort |= clkPinMask; // Clock high
+#else
+ digitalWrite(_sck, HIGH);
+#endif
+
+ if (bitdelay_us) {
+ delayMicroseconds(bitdelay_us);
+ }
+
+ if (_mosi != -1) {
+#ifdef BUSIO_USE_FAST_PINIO
+ if (send & b)
+ *mosiPort |= mosiPinMask;
+ else
+ *mosiPort &= ~mosiPinMask;
+#else
+ digitalWrite(_mosi, send & b);
+#endif
+ }
+
+#ifdef BUSIO_USE_FAST_PINIO
+ *clkPort &= ~clkPinMask; // Clock low
+#else
+ digitalWrite(_sck, LOW);
+#endif
+
+ if (_miso != -1) {
+#ifdef BUSIO_USE_FAST_PINIO
+ if (*misoPort & misoPinMask) {
+#else
+ if (digitalRead(_miso)) {
+#endif
+ reply |= b;
+ }
+ }
+ }
+ if (_miso != -1) {
+ buffer[i] = reply;
+ }
+ }
}
return;
}
-
-
/*!
* @brief Transfer (send/receive) one byte over hard/soft SPI
* @param send The byte to send
@@ -152,29 +266,62 @@ uint8_t Adafruit_SPIDevice::transfer(uint8_t send) {
return data;
}
+/*!
+ * @brief Manually begin a transaction (calls beginTransaction if hardware
+ * SPI)
+ */
+void Adafruit_SPIDevice::beginTransaction(void) {
+ if (_spi) {
+ _spi->beginTransaction(*_spiSetting);
+ }
+}
+
+/*!
+ * @brief Manually end a transaction (calls endTransaction if hardware SPI)
+ */
+void Adafruit_SPIDevice::endTransaction(void) {
+ if (_spi) {
+ _spi->endTransaction();
+ }
+}
/*!
* @brief Write a buffer or two to the SPI device.
* @param buffer Pointer to buffer of data to write
* @param len Number of bytes from buffer to write
- * @param prefix_buffer Pointer to optional array of data to write before buffer.
+ * @param prefix_buffer Pointer to optional array of data to write before
+ * buffer.
* @param prefix_len Number of bytes from prefix buffer to write
- * @return Always returns true because there's no way to test success of SPI writes
+ * @return Always returns true because there's no way to test success of SPI
+ * writes
*/
-bool Adafruit_SPIDevice::write(uint8_t *buffer, size_t len, uint8_t *prefix_buffer, size_t prefix_len) {
+bool Adafruit_SPIDevice::write(uint8_t *buffer, size_t len,
+ uint8_t *prefix_buffer, size_t prefix_len) {
if (_spi) {
_spi->beginTransaction(*_spiSetting);
}
- digitalWrite(_cs, LOW);
+ setChipSelect(LOW);
// do the writing
- for (size_t i=0; i 0) {
+ _spi->transferBytes(prefix_buffer, nullptr, prefix_len);
+ }
+ if (len > 0) {
+ _spi->transferBytes(buffer, nullptr, len);
+ }
+ } else
+#endif
+ {
+ for (size_t i = 0; i < prefix_len; i++) {
+ transfer(prefix_buffer[i]);
+ }
+ for (size_t i = 0; i < len; i++) {
+ transfer(buffer[i]);
+ }
}
- for (size_t i=0; iendTransaction();
@@ -183,17 +330,17 @@ bool Adafruit_SPIDevice::write(uint8_t *buffer, size_t len, uint8_t *prefix_buff
#ifdef DEBUG_SERIAL
DEBUG_SERIAL.print(F("\tSPIDevice Wrote: "));
if ((prefix_len != 0) && (prefix_buffer != NULL)) {
- for (uint16_t i=0; ibeginTransaction(*_spiSetting);
}
- digitalWrite(_cs, LOW);
- transfer(buffer, len);
- digitalWrite(_cs, HIGH);
+
+ setChipSelect(LOW);
+ transfer(buffer, len);
+ setChipSelect(HIGH);
if (_spi) {
_spi->endTransaction();
@@ -225,9 +375,9 @@ bool Adafruit_SPIDevice::read(uint8_t *buffer, size_t len, uint8_t sendvalue) {
#ifdef DEBUG_SERIAL
DEBUG_SERIAL.print(F("\tSPIDevice Read: "));
- for (uint16_t i=0; ibeginTransaction(*_spiSetting);
}
- digitalWrite(_cs, LOW);
+ setChipSelect(LOW);
// do the writing
- for (size_t i=0; i 0) {
+ _spi->transferBytes(write_buffer, nullptr, write_len);
+ }
+ } else
+#endif
+ {
+ for (size_t i = 0; i < write_len; i++) {
+ transfer(write_buffer[i]);
+ }
}
#ifdef DEBUG_SERIAL
DEBUG_SERIAL.print(F("\tSPIDevice Wrote: "));
- for (uint16_t i=0; iendTransaction();
@@ -299,3 +463,37 @@ bool Adafruit_SPIDevice::write_then_read(uint8_t *write_buffer, size_t write_len
return true;
}
+
+/*!
+ * @brief Write some data and read some data at the same time from SPI
+ * into the same buffer. This is basicaly a wrapper for transfer() with
+ * CS-pin and transaction management.
+ * This /does/ transmit-receive at the same time!
+ * @param buffer Pointer to buffer of data to write/read to/from
+ * @param len Number of bytes from buffer to write/read.
+ * @return Always returns true because there's no way to test success of SPI
+ * writes
+ */
+bool Adafruit_SPIDevice::write_and_read(uint8_t *buffer, size_t len) {
+ if (_spi) {
+ _spi->beginTransaction(*_spiSetting);
+ }
+
+ setChipSelect(LOW);
+ transfer(buffer, len);
+ setChipSelect(HIGH);
+
+ if (_spi) {
+ _spi->endTransaction();
+ }
+
+ return true;
+}
+
+void Adafruit_SPIDevice::setChipSelect(int value) {
+ if (_cs == -1)
+ return;
+ digitalWrite(_cs, value);
+}
+
+#endif // SPI exists
diff --git a/lib/lib_i2c/Adafruit_BusIO/Adafruit_SPIDevice.h b/lib/lib_i2c/Adafruit_BusIO/Adafruit_SPIDevice.h
index 987cb3f62..8de31d050 100644
--- a/lib/lib_i2c/Adafruit_BusIO/Adafruit_SPIDevice.h
+++ b/lib/lib_i2c/Adafruit_BusIO/Adafruit_SPIDevice.h
@@ -1,62 +1,109 @@
-#include
-
#ifndef Adafruit_SPIDevice_h
#define Adafruit_SPIDevice_h
+#include
+
+#if !defined(SPI_INTERFACES_COUNT) || \
+ (defined(SPI_INTERFACES_COUNT) && (SPI_INTERFACES_COUNT > 0))
+
+#include
+
// some modern SPI definitions don't have BitOrder enum
-#if (defined(__AVR__) && !defined(ARDUINO_ARCH_MEGAAVR)) || defined(ESP8266) || defined(TEENSYDUINO)
+#if (defined(__AVR__) && !defined(ARDUINO_ARCH_MEGAAVR)) || \
+ defined(ESP8266) || defined(TEENSYDUINO) || defined(SPARK) || \
+ defined(ARDUINO_ARCH_SPRESENSE) || defined(MEGATINYCORE) || \
+ defined(DXCORE) || defined(ARDUINO_AVR_ATmega4809) || \
+ defined(ARDUINO_AVR_ATmega4808) || defined(ARDUINO_AVR_ATmega3209) || \
+ defined(ARDUINO_AVR_ATmega3208) || defined(ARDUINO_AVR_ATmega1609) || \
+ defined(ARDUINO_AVR_ATmega1608) || defined(ARDUINO_AVR_ATmega809) || \
+ defined(ARDUINO_AVR_ATmega808) || defined(ARDUINO_ARCH_ARC32)
+
typedef enum _BitOrder {
SPI_BITORDER_MSBFIRST = MSBFIRST,
SPI_BITORDER_LSBFIRST = LSBFIRST,
-} BitOrder;
-#endif
+} BusIOBitOrder;
-// some modern SPI definitions don't have BitOrder enum and have different SPI mode defines
-#if defined(ESP32)
+#elif defined(ESP32) || defined(__ASR6501__) || defined(__ASR6502__)
+
+// some modern SPI definitions don't have BitOrder enum and have different SPI
+// mode defines
typedef enum _BitOrder {
SPI_BITORDER_MSBFIRST = SPI_MSBFIRST,
SPI_BITORDER_LSBFIRST = SPI_LSBFIRST,
-} BitOrder;
-#endif
+} BusIOBitOrder;
+#else
// Some platforms have a BitOrder enum but its named MSBFIRST/LSBFIRST
-#if defined(ARDUINO_ARCH_SAMD) || defined(__SAM3X8E__) || defined(NRF52_SERIES) || defined(ARDUINO_ARCH_ARDUINO_CORE_STM32) || defined(ARDUINO_ARCH_MEGAAVR) || defined(_STM32_DEF_)
- #define SPI_BITORDER_MSBFIRST MSBFIRST
- #define SPI_BITORDER_LSBFIRST LSBFIRST
+#define SPI_BITORDER_MSBFIRST MSBFIRST
+#define SPI_BITORDER_LSBFIRST LSBFIRST
+typedef BitOrder BusIOBitOrder;
#endif
-///< The class which defines how we will talk to this device over SPI
+#if defined(__AVR__) || defined(TEENSYDUINO)
+typedef volatile uint8_t BusIO_PortReg;
+typedef uint8_t BusIO_PortMask;
+#define BUSIO_USE_FAST_PINIO
+
+#elif defined(ESP8266) || defined(ESP32) || defined(__SAM3X8E__) || \
+ defined(ARDUINO_ARCH_SAMD)
+typedef volatile uint32_t BusIO_PortReg;
+typedef uint32_t BusIO_PortMask;
+#define BUSIO_USE_FAST_PINIO
+
+#elif (defined(__arm__) || defined(ARDUINO_FEATHER52)) && \
+ !defined(ARDUINO_ARCH_MBED) && !defined(ARDUINO_ARCH_RP2040)
+typedef volatile uint32_t BusIO_PortReg;
+typedef uint32_t BusIO_PortMask;
+#if !defined(__ASR6501__) && !defined(__ASR6502__)
+#define BUSIO_USE_FAST_PINIO
+#endif
+
+#else
+#undef BUSIO_USE_FAST_PINIO
+#endif
+
+/**! The class which defines how we will talk to this device over SPI **/
class Adafruit_SPIDevice {
- public:
- Adafruit_SPIDevice(int8_t cspin,
- uint32_t freq=1000000,
- BitOrder dataOrder=SPI_BITORDER_MSBFIRST,
- uint8_t dataMode=SPI_MODE0,
- SPIClass *theSPI=&SPI);
+public:
+ Adafruit_SPIDevice(int8_t cspin, uint32_t freq = 1000000,
+ BusIOBitOrder dataOrder = SPI_BITORDER_MSBFIRST,
+ uint8_t dataMode = SPI_MODE0, SPIClass *theSPI = &SPI);
Adafruit_SPIDevice(int8_t cspin, int8_t sck, int8_t miso, int8_t mosi,
- uint32_t freq=1000000,
- BitOrder dataOrder=SPI_BITORDER_MSBFIRST,
- uint8_t dataMode=SPI_MODE0);
+ uint32_t freq = 1000000,
+ BusIOBitOrder dataOrder = SPI_BITORDER_MSBFIRST,
+ uint8_t dataMode = SPI_MODE0);
+ ~Adafruit_SPIDevice();
bool begin(void);
- bool read(uint8_t *buffer, size_t len, uint8_t sendvalue=0xFF);
- bool write(uint8_t *buffer, size_t len, uint8_t *prefix_buffer=NULL, size_t prefix_len=0);
- bool write_then_read(uint8_t *write_buffer, size_t write_len, uint8_t *read_buffer, size_t read_len, uint8_t sendvalue=0xFF);
+ bool read(uint8_t *buffer, size_t len, uint8_t sendvalue = 0xFF);
+ bool write(uint8_t *buffer, size_t len, uint8_t *prefix_buffer = NULL,
+ size_t prefix_len = 0);
+ bool write_then_read(uint8_t *write_buffer, size_t write_len,
+ uint8_t *read_buffer, size_t read_len,
+ uint8_t sendvalue = 0xFF);
+ bool write_and_read(uint8_t *buffer, size_t len);
uint8_t transfer(uint8_t send);
void transfer(uint8_t *buffer, size_t len);
+ void beginTransaction(void);
+ void endTransaction(void);
- private:
-
+private:
SPIClass *_spi;
SPISettings *_spiSetting;
uint32_t _freq;
- BitOrder _dataOrder;
+ BusIOBitOrder _dataOrder;
uint8_t _dataMode;
+ void setChipSelect(int value);
int8_t _cs, _sck, _mosi, _miso;
+#ifdef BUSIO_USE_FAST_PINIO
+ BusIO_PortReg *mosiPort, *clkPort, *misoPort, *csPort;
+ BusIO_PortMask mosiPinMask, misoPinMask, clkPinMask, csPinMask;
+#endif
bool _begun;
};
+#endif // has SPI defined
#endif // Adafruit_SPIDevice_h
diff --git a/lib/lib_i2c/Adafruit_BusIO/CMakeLists.txt b/lib/lib_i2c/Adafruit_BusIO/CMakeLists.txt
new file mode 100644
index 000000000..880b1aa99
--- /dev/null
+++ b/lib/lib_i2c/Adafruit_BusIO/CMakeLists.txt
@@ -0,0 +1,11 @@
+# Adafruit Bus IO Library
+# https://github.com/adafruit/Adafruit_BusIO
+# MIT License
+
+cmake_minimum_required(VERSION 3.5)
+
+idf_component_register(SRCS "Adafruit_I2CDevice.cpp" "Adafruit_BusIO_Register.cpp" "Adafruit_SPIDevice.cpp"
+ INCLUDE_DIRS "."
+ REQUIRES arduino)
+
+project(Adafruit_BusIO)
diff --git a/lib/lib_i2c/Adafruit_BusIO/README.md b/lib/lib_i2c/Adafruit_BusIO/README.md
index a1830809c..1cc06a156 100644
--- a/lib/lib_i2c/Adafruit_BusIO/README.md
+++ b/lib/lib_i2c/Adafruit_BusIO/README.md
@@ -1,6 +1,7 @@
-# Adafruit Bus IO Library [](https://travis-ci.com/adafruit/Adafruit_BusIO)
+# Adafruit Bus IO Library [](https://github.com/adafruit/Adafruit_BusIO/actions)
-This is a helper libary to abstract away I2C & SPI transactions and registers
+
+This is a helper library to abstract away I2C & SPI transactions and registers
Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit!
diff --git a/lib/lib_i2c/Adafruit_BusIO/component.mk b/lib/lib_i2c/Adafruit_BusIO/component.mk
new file mode 100644
index 000000000..049f190ee
--- /dev/null
+++ b/lib/lib_i2c/Adafruit_BusIO/component.mk
@@ -0,0 +1 @@
+COMPONENT_ADD_INCLUDEDIRS = .
diff --git a/lib/lib_i2c/Adafruit_BusIO/examples/i2corspi_register/i2corspi_register.ino b/lib/lib_i2c/Adafruit_BusIO/examples/i2corspi_register/i2corspi_register.ino
index 555cf3b0d..992a2e004 100644
--- a/lib/lib_i2c/Adafruit_BusIO/examples/i2corspi_register/i2corspi_register.ino
+++ b/lib/lib_i2c/Adafruit_BusIO/examples/i2corspi_register/i2corspi_register.ino
@@ -28,11 +28,11 @@ void setup() {
}
Adafruit_BusIO_Register id_reg = Adafruit_BusIO_Register(i2c_dev, spi_dev, ADDRBIT8_HIGH_TOREAD, 0x0F);
- uint8_t id;
+ uint8_t id=0;
id_reg.read(&id);
Serial.print("ID register = 0x"); Serial.println(id, HEX);
}
void loop() {
-}
\ No newline at end of file
+}
diff --git a/lib/lib_i2c/Adafruit_BusIO/examples/spi_register_bits/spi_register_bits.ino b/lib/lib_i2c/Adafruit_BusIO/examples/spi_register_bits/spi_register_bits.ino
new file mode 100644
index 000000000..e70a17b35
--- /dev/null
+++ b/lib/lib_i2c/Adafruit_BusIO/examples/spi_register_bits/spi_register_bits.ino
@@ -0,0 +1,192 @@
+/***************************************************
+
+ This is an example for how to use Adafruit_BusIO_RegisterBits from Adafruit_BusIO library.
+
+ Designed specifically to work with the Adafruit RTD Sensor
+ ----> https://www.adafruit.com/products/3328
+ uisng a MAX31865 RTD-to-Digital Converter
+ ----> https://datasheets.maximintegrated.com/en/ds/MAX31865.pdf
+
+ This sensor uses SPI to communicate, 4 pins are required to
+ interface.
+ A fifth pin helps to detect when a new conversion is ready.
+
+ Adafruit invests time and resources providing this open source code,
+ please support Adafruit and open-source hardware by purchasing
+ products from Adafruit!
+
+ Example written (2020/3) by Andreas Hardtung/AnHard.
+ BSD license, all text above must be included in any redistribution
+ ****************************************************/
+
+#include
+#include
+
+#define MAX31865_SPI_SPEED (5000000)
+#define MAX31865_SPI_BITORDER (SPI_BITORDER_MSBFIRST)
+#define MAX31865_SPI_MODE (SPI_MODE1)
+
+#define MAX31865_SPI_CS (10)
+#define MAX31865_READY_PIN (2)
+
+
+Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice( MAX31865_SPI_CS, MAX31865_SPI_SPEED, MAX31865_SPI_BITORDER, MAX31865_SPI_MODE, &SPI); // Hardware SPI
+// Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice( MAX31865_SPI_CS, 13, 12, 11, MAX31865_SPI_SPEED, MAX31865_SPI_BITORDER, MAX31865_SPI_MODE); // Software SPI
+
+// MAX31865 chip related *********************************************************************************************
+Adafruit_BusIO_Register config_reg = Adafruit_BusIO_Register(&spi_dev, 0x00, ADDRBIT8_HIGH_TOWRITE, 1, MSBFIRST);
+Adafruit_BusIO_RegisterBits bias_bit = Adafruit_BusIO_RegisterBits(&config_reg, 1, 7);
+Adafruit_BusIO_RegisterBits auto_bit = Adafruit_BusIO_RegisterBits(&config_reg, 1, 6);
+Adafruit_BusIO_RegisterBits oneS_bit = Adafruit_BusIO_RegisterBits(&config_reg, 1, 5);
+Adafruit_BusIO_RegisterBits wire_bit = Adafruit_BusIO_RegisterBits(&config_reg, 1, 4);
+Adafruit_BusIO_RegisterBits faultT_bits = Adafruit_BusIO_RegisterBits(&config_reg, 2, 2);
+Adafruit_BusIO_RegisterBits faultR_bit = Adafruit_BusIO_RegisterBits(&config_reg, 1, 1);
+Adafruit_BusIO_RegisterBits fi50hz_bit = Adafruit_BusIO_RegisterBits(&config_reg, 1, 0);
+
+Adafruit_BusIO_Register rRatio_reg = Adafruit_BusIO_Register(&spi_dev, 0x01, ADDRBIT8_HIGH_TOWRITE, 2, MSBFIRST);
+Adafruit_BusIO_RegisterBits rRatio_bits = Adafruit_BusIO_RegisterBits(&rRatio_reg, 15, 1);
+Adafruit_BusIO_RegisterBits fault_bit = Adafruit_BusIO_RegisterBits(&rRatio_reg, 1, 0);
+
+Adafruit_BusIO_Register maxRratio_reg = Adafruit_BusIO_Register(&spi_dev, 0x03, ADDRBIT8_HIGH_TOWRITE, 2, MSBFIRST);
+Adafruit_BusIO_RegisterBits maxRratio_bits = Adafruit_BusIO_RegisterBits(&maxRratio_reg, 15, 1);
+
+Adafruit_BusIO_Register minRratio_reg = Adafruit_BusIO_Register(&spi_dev, 0x05, ADDRBIT8_HIGH_TOWRITE, 2, MSBFIRST);
+Adafruit_BusIO_RegisterBits minRratio_bits = Adafruit_BusIO_RegisterBits(&minRratio_reg, 15, 1);
+
+Adafruit_BusIO_Register fault_reg = Adafruit_BusIO_Register(&spi_dev, 0x07, ADDRBIT8_HIGH_TOWRITE, 1, MSBFIRST);
+Adafruit_BusIO_RegisterBits range_high_fault_bit = Adafruit_BusIO_RegisterBits(&fault_reg, 1, 7);
+Adafruit_BusIO_RegisterBits range_low_fault_bit = Adafruit_BusIO_RegisterBits(&fault_reg, 1, 6);
+Adafruit_BusIO_RegisterBits refin_high_fault_bit = Adafruit_BusIO_RegisterBits(&fault_reg, 1, 5);
+Adafruit_BusIO_RegisterBits refin_low_fault_bit = Adafruit_BusIO_RegisterBits(&fault_reg, 1, 4);
+Adafruit_BusIO_RegisterBits rtdin_low_fault_bit = Adafruit_BusIO_RegisterBits(&fault_reg, 1, 3);
+Adafruit_BusIO_RegisterBits voltage_fault_bit = Adafruit_BusIO_RegisterBits(&fault_reg, 1, 2);
+
+// Print the details of the configuration register.
+void printConfig( void ) {
+ Serial.print("BIAS: "); if (bias_bit.read() ) Serial.print("ON"); else Serial.print("OFF");
+ Serial.print(", AUTO: "); if (auto_bit.read() ) Serial.print("ON"); else Serial.print("OFF");
+ Serial.print(", ONES: "); if (oneS_bit.read() ) Serial.print("ON"); else Serial.print("OFF");
+ Serial.print(", WIRE: "); if (wire_bit.read() ) Serial.print("3"); else Serial.print("2/4");
+ Serial.print(", FAULTCLEAR: "); if (faultR_bit.read() ) Serial.print("ON"); else Serial.print("OFF");
+ Serial.print(", "); if (fi50hz_bit.read() ) Serial.print("50HZ"); else Serial.print("60HZ");
+ Serial.println();
+}
+
+// Check and print faults. Then clear them.
+void checkFaults( void ) {
+ if (fault_bit.read()) {
+ Serial.print("MAX: "); Serial.println(maxRratio_bits.read());
+ Serial.print("VAL: "); Serial.println( rRatio_bits.read());
+ Serial.print("MIN: "); Serial.println(minRratio_bits.read());
+
+ if (range_high_fault_bit.read() ) Serial.println("Range high fault");
+ if ( range_low_fault_bit.read() ) Serial.println("Range low fault");
+ if (refin_high_fault_bit.read() ) Serial.println("REFIN high fault");
+ if ( refin_low_fault_bit.read() ) Serial.println("REFIN low fault");
+ if ( rtdin_low_fault_bit.read() ) Serial.println("RTDIN low fault");
+ if ( voltage_fault_bit.read() ) Serial.println("Voltage fault");
+
+ faultR_bit.write(1); // clear fault
+ }
+}
+
+void setup() {
+ #if (MAX31865_1_READY_PIN != -1)
+ pinMode(MAX31865_READY_PIN ,INPUT_PULLUP);
+ #endif
+
+ while (!Serial) { delay(10); }
+ Serial.begin(115200);
+ Serial.println("SPI Adafruit_BusIO_RegisterBits test on MAX31865");
+
+ if (!spi_dev.begin()) {
+ Serial.println("Could not initialize SPI device");
+ while (1);
+ }
+
+ // Set up for automode 50Hz. We don't care about selfheating. We want the highest possible sampling rate.
+ auto_bit.write(0); // Don't switch filtermode while auto_mode is on.
+ fi50hz_bit.write(1); // Set filter to 50Hz mode.
+ faultR_bit.write(1); // Clear faults.
+ bias_bit.write(1); // In automode we want to have the bias current always on.
+ delay(5); // Wait until bias current settles down.
+ // 10.5 time constants of the input RC network is required.
+ // 10ms worst case for 10kω reference resistor and a 0.1µF capacitor across the RTD inputs.
+ // Adafruit Module has 0.1µF and only 430/4300ω So here 0.43/4.3ms
+ auto_bit.write(1); // Now we can set automode. Automatically starting first conversion.
+
+ // Test the READY_PIN
+ #if (defined( MAX31865_READY_PIN ) && (MAX31865_READY_PIN != -1))
+ int i = 0;
+ while (digitalRead(MAX31865_READY_PIN) && i++ <= 100) { delay(1); }
+ if (i >= 100) {
+ Serial.print("ERROR: Max31865 Pin detection does not work. PIN:");
+ Serial.println(MAX31865_READY_PIN);
+ }
+ #else
+ delay(100);
+ #endif
+
+ // Set ratio range.
+ // Setting the temperatures would need some more calculation - not related to Adafruit_BusIO_RegisterBits.
+ uint16_t ratio = rRatio_bits.read();
+ maxRratio_bits.write( (ratio < 0x8fffu-1000u) ? ratio + 1000u : 0x8fffu );
+ minRratio_bits.write( (ratio > 1000u) ? ratio - 1000u : 0u );
+
+ printConfig();
+ checkFaults();
+}
+
+void loop() {
+ #if (defined( MAX31865_READY_PIN ) && (MAX31865_1_READY_PIN != -1))
+ // Is conversion ready?
+ if (!digitalRead(MAX31865_READY_PIN))
+ #else
+ // Warant conversion is ready.
+ delay(21); // 21ms for 50Hz-mode. 19ms in 60Hz-mode.
+ #endif
+ {
+ // Read ratio, calculate temperature, scale, filter and print.
+ Serial.println( rRatio2C( rRatio_bits.read() ) * 100.0f, 0); // Temperature scaled by 100
+ // Check, print, clear faults.
+ checkFaults();
+ }
+
+ // Do something else.
+ //delay(15000);
+}
+
+
+// Module/Sensor related. Here Adafruit PT100 module with a 2_Wire PT100 Class C *****************************
+float rRatio2C(uint16_t ratio) {
+ // A simple linear conversion.
+ const float R0 = 100.0f;
+ const float Rref = 430.0f;
+ const float alphaPT = 0.003850f;
+ const float ADCmax = (1u << 15) - 1.0f;
+ const float rscale = Rref / ADCmax;
+ // Measured temperature in boiling water 101.08°C with factor a = 1 and b = 0. Rref and MAX at about 22±2°C.
+ // Measured temperature in ice/water bath 0.76°C with factor a = 1 and b = 0. Rref and MAX at about 22±2°C.
+ //const float a = 1.0f / (alphaPT * R0);
+ const float a = (100.0f/101.08f) / (alphaPT * R0);
+ //const float b = 0.0f; // 101.08
+ const float b = -0.76f; // 100.32 > 101.08
+
+ return filterRing( ((ratio * rscale) - R0) * a + b );
+}
+
+// General purpose *********************************************************************************************
+#define RINGLENGTH 250
+float filterRing( float newVal ) {
+ static float ring[RINGLENGTH] = { 0.0 };
+ static uint8_t ringIndex = 0;
+ static bool ringFull = false;
+
+ if ( ringIndex == RINGLENGTH ) { ringFull = true; ringIndex = 0; }
+ ring[ringIndex] = newVal;
+ uint8_t loopEnd = (ringFull) ? RINGLENGTH : ringIndex + 1;
+ float ringSum = 0.0f;
+ for (uint8_t i = 0; i < loopEnd; i++) ringSum += ring[i];
+ ringIndex++;
+ return ringSum / loopEnd;
+}
diff --git a/lib/lib_i2c/Adafruit_BusIO/examples/spi_registers/spi_registers.ino b/lib/lib_i2c/Adafruit_BusIO/examples/spi_registers/spi_registers.ino
index e24f1aa9a..091a35315 100644
--- a/lib/lib_i2c/Adafruit_BusIO/examples/spi_registers/spi_registers.ino
+++ b/lib/lib_i2c/Adafruit_BusIO/examples/spi_registers/spi_registers.ino
@@ -15,12 +15,12 @@ void setup() {
}
Adafruit_BusIO_Register id_reg = Adafruit_BusIO_Register(&spi_dev, 0x0F, ADDRBIT8_HIGH_TOREAD);
- uint8_t id;
+ uint8_t id = 0;
id_reg.read(&id);
Serial.print("ID register = 0x"); Serial.println(id, HEX);
Adafruit_BusIO_Register thresh_reg = Adafruit_BusIO_Register(&spi_dev, 0x0C, ADDRBIT8_HIGH_TOREAD, 2, LSBFIRST);
- uint16_t thresh;
+ uint16_t thresh = 0;
thresh_reg.read(&thresh);
Serial.print("Initial threshold register = 0x"); Serial.println(thresh, HEX);
@@ -31,4 +31,4 @@ void setup() {
void loop() {
-}
\ No newline at end of file
+}
diff --git a/lib/lib_i2c/Adafruit_BusIO/library.properties b/lib/lib_i2c/Adafruit_BusIO/library.properties
index f63425a7d..68cd6259b 100644
--- a/lib/lib_i2c/Adafruit_BusIO/library.properties
+++ b/lib/lib_i2c/Adafruit_BusIO/library.properties
@@ -1,5 +1,5 @@
name=Adafruit BusIO
-version=1.0.10
+version=1.11.0
author=Adafruit
maintainer=Adafruit
sentence=This is a library for abstracting away UART, I2C and SPI interfacing
From 1022c91b7cbaa2650ac45a19545c134518460fd3 Mon Sep 17 00:00:00 2001
From: Theo Arends <11044339+arendst@users.noreply.github.com>
Date: Sat, 12 Feb 2022 16:00:19 +0100
Subject: [PATCH 009/355] Bump dev version to v11.0.0.1
---
CHANGELOG.md | 15 ++++++----
RELEASENOTES.md | 63 +--------------------------------------
tasmota/tasmota_version.h | 2 +-
3 files changed, 12 insertions(+), 68 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8b5ad650e..88c4aa9e9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,15 +2,22 @@
All notable changes to this project will be documented in this file.
## [Unreleased] - Development
-
-## [10.1.0.8]
+## [11.0.0.1]
### Added
### Changed
-- From Calendar Versioning (CalVer) back to Semantic Versioning (SemVer) for better major change indication and future support
### Fixed
+## [Released]
+
+## [11.0.0] 20220212
+- Release Olivia
+
+## [10.1.0.8] 20220212
+### Changed
+- From Calendar Versioning (CalVer) back to Semantic Versioning (SemVer) for better major change indication and future support
+
## [2022.1.4 = 10.1.0.7] 20220205
### Added
- Rule variables %timer1% to %timer16% (#14619)
@@ -125,8 +132,6 @@ All notable changes to this project will be documented in this file.
- ESP32 LedPwmMode exception (#14073)
- ESP32 Compile error when I2S_Audio is enabled (#14095)
-## [Released]
-
## [10.1.0] 20211208
- Release Noelle
diff --git a/RELEASENOTES.md b/RELEASENOTES.md
index 0f455fe00..54fc8a90f 100644
--- a/RELEASENOTES.md
+++ b/RELEASENOTES.md
@@ -103,74 +103,13 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo
[Complete list](BUILDS.md) of available feature and sensors.
-## Changelog v10.1.0.8
+## Changelog v11.0.0.1
### Added
-- Command ``Json {}`` to enable input of any command as JSON tokens [#14568](https://github.com/arendst/Tasmota/issues/14568)
-- Command ``SetOption44 1..100`` to set base tolerance percentage for matching incoming IR messages (default 25, max 100) [#14555](https://github.com/arendst/Tasmota/issues/14555)
-- Command ``SetOption134 1`` to disable PWM auto-phasing for lights by default (new behavior) [#14590](https://github.com/arendst/Tasmota/issues/14590)
-- Command ``SSerialConfig `` to change Serial Bridge configuration
-- Command ``SspmDisplay 1`` to display Sonoff SPM energy data in GUI for relays powered on only
-- Command ``SspmEnergyTotal`` to (p)reset Sonoff SPM total energy without today's energy
-- Command ``SspmEnergyYesterday`` to (p)reset Sonoff SPM energy yesterday
-- Command ``SspmHistory`` to retrieve Sonoff SPM daily energy up to last six month (as defined by ARM firmware)
-- Command ``SspmIAmHere`` to (faintly) blink Sonoff SPM-4Relay module error light of requested relay
-- Command ``SspmLog [x]`` to retrieve Sonoff SPM relay power state change and cause logging
-- Command ``SspmMap 2,1,..`` to map Sonoff SPM scanned module to physical module [#14281](https://github.com/arendst/Tasmota/issues/14281)
-- Command ``SspmOverload `` to set Sonoff SPM overload criteria for any relay
-- Command ``SspmScan`` to rescan Sonoff SPM modbus
-- Command ``WebTime ,`` to show part of date and/or time in web gui based on "2017-03-07T11:08:02-07:00"
-- Commands for ESP32 ethernet configuration ``EthIpAddress``, ``EthGateway``, ``EthSubnetmask``, ``EthDnsServer1`` and ``EthDnsServer2`` [#14385](https://github.com/arendst/Tasmota/issues/14385)
-- Support for Eastron SDM230 modBus energy meter [#13443](https://github.com/arendst/Tasmota/issues/13443)
-- PWM Dimmer two button support [#13993](https://github.com/arendst/Tasmota/issues/13993)
-- Support for Linkind dimmer as GPIO ``Option A6`` [#14004](https://github.com/arendst/Tasmota/issues/14004)
-- DDP schemes for light and WS2812 [#14017](https://github.com/arendst/Tasmota/issues/14017)
-- Device Group Send full status item [#14045](https://github.com/arendst/Tasmota/issues/14045)
-- Support for MAX7219 Dot Matrix displays [#14091](https://github.com/arendst/Tasmota/issues/14091)
-- Experimental ADE7953 (Shelly EM) reset on restart [#14261](https://github.com/arendst/Tasmota/issues/14261)
-- Solax X1 negative temperature support [#14278](https://github.com/arendst/Tasmota/issues/14278)
-- Solax X1 modbus RTS support and offline status [#14305](https://github.com/arendst/Tasmota/issues/14305)
-- Tasmota favicon to webbrowser tab [#14322](https://github.com/arendst/Tasmota/issues/14322)
-- Support for BME688 with latest Bosch-Sensor-API library [#14513](https://github.com/arendst/Tasmota/issues/14513)
-- Rule variable %color% [#14572](https://github.com/arendst/Tasmota/issues/14572)
-- Rule variables %timer1% to %timer16% [#14619](https://github.com/arendst/Tasmota/issues/14619)
-- Support for MQ analog sensor for air quality by Francesco Adriani [#14581](https://github.com/arendst/Tasmota/issues/14581)
-- ESP32 single binary firmware [#14239](https://github.com/arendst/Tasmota/issues/14239)
-- ESP32 disable serial console when 3 (ESP32) or 2 (Other models) serial interfaces are requested [#14487](https://github.com/arendst/Tasmota/issues/14487)
-- ESP32 support for TuyaMcu
-- ESP32 Berry features
-- ESP32 support for USE_PWM_DIMMER as GPIO ``Option E1``
-- ESP32 increase PWM channels to 16
-- ESP32 auto-configuration
-- ESP32 initial support for ESP32S3 with support for 38 configurable GPIOs
### Breaking Changed
### Changed
-- ESP32 core library from v2.0.2 to v2.0.2.1
-- PubSubClient library from v2.8.12 to v2.8.13
-- TasmotaSerial library from v3.3.0 to v3.4.0
-- TasmotaModbus library from v1.2.0 to v3.4.0
-- ESP8266Audio library from v1.9.2 to v1.9.5
-- ESP8266SAM library from v1.0 to v1.0.1
-- BME68x-Sensor-API library from v3.5.9 to v4.4.7
-- SR04 driver to support US-100
-- Mitsubishi HVAC temperature resolution [#13936](https://github.com/arendst/Tasmota/issues/13936)
-- Remove restriction of topic must differ from mqttclient [#14019](https://github.com/arendst/Tasmota/issues/14019)
-- ESP32 Set stack size with ``#define SET_ESP32_STACK_SIZE``, added ``StackLowMark`` metrics
-- ESP32 Berry stores compiled bytecode into IRAM, freeing space in heap [#14307](https://github.com/arendst/Tasmota/issues/14307)
### Fixed
-- Intermittent exceptions and heap corruption due to PubSubClient library buffer overflow [#13700](https://github.com/arendst/Tasmota/issues/13700)
-- EZOO2 sensor message format [#14000](https://github.com/arendst/Tasmota/issues/14000)
-- DHT support negative temperatures on different hardware [#14173](https://github.com/arendst/Tasmota/issues/14173)
-- Hardware serial parity and stop bits support [#14212](https://github.com/arendst/Tasmota/issues/14212)
-- Edit file for SD card [#14229](https://github.com/arendst/Tasmota/issues/14229)
-- Scripter memory corruption [#14268](https://github.com/arendst/Tasmota/issues/14268)
-- ESP32 Webcam exception during flashwrites
-- ESP32 LedPwmMode exception [#14073](https://github.com/arendst/Tasmota/issues/14073)
-- ESP32 Compile error when I2S_Audio is enabled [#14095](https://github.com/arendst/Tasmota/issues/14095)
-- ESP32 Provide proper OTA_URL for tasmota32solo1 [#14202](https://github.com/arendst/Tasmota/issues/14202)
-- ESP32 OneWire-Stickbreaker (DS18x20) library support for ESP32C3 and ESP32S2 [#14338](https://github.com/arendst/Tasmota/issues/14338)
### Removed
-- ESP32 consolidate odroidgo and core2 binaries into tasmota32-lvgl using Berry features
diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h
index 6a6388472..d2471660f 100644
--- a/tasmota/tasmota_version.h
+++ b/tasmota/tasmota_version.h
@@ -20,6 +20,6 @@
#ifndef _TASMOTA_VERSION_H_
#define _TASMOTA_VERSION_H_
-const uint32_t VERSION = 0x0A010008; // 10.1.0.8
+const uint32_t VERSION = 0x0B000001; // 11.0.0.1
#endif // _TASMOTA_VERSION_H_
From 2c499623ff28da9dc35dd6b9e28807d85ab4c8a0 Mon Sep 17 00:00:00 2001
From: Jason2866 <24528715+Jason2866@users.noreply.github.com>
Date: Sat, 12 Feb 2022 16:05:11 +0100
Subject: [PATCH 010/355] rm odroid
---
.github/workflows/Tasmota_build_master.yml | 1 -
1 file changed, 1 deletion(-)
diff --git a/.github/workflows/Tasmota_build_master.yml b/.github/workflows/Tasmota_build_master.yml
index 144bd9db0..6d29cb7c9 100644
--- a/.github/workflows/Tasmota_build_master.yml
+++ b/.github/workflows/Tasmota_build_master.yml
@@ -35,7 +35,6 @@ jobs:
- tasmota32-display
- tasmota32-ir
- tasmota32-lvgl
- - tasmota32-odroidgo
- tasmota32c3
- tasmota32solo1
steps:
From cc57881c68d525b5deefac039b4d1b1088526495 Mon Sep 17 00:00:00 2001
From: Jason2866 <24528715+Jason2866@users.noreply.github.com>
Date: Sat, 12 Feb 2022 16:05:56 +0100
Subject: [PATCH 011/355] rm odroid
---
.github/workflows/Tasmota_build_devel.yml | 1 -
1 file changed, 1 deletion(-)
diff --git a/.github/workflows/Tasmota_build_devel.yml b/.github/workflows/Tasmota_build_devel.yml
index 549aa5d7a..511e322b7 100644
--- a/.github/workflows/Tasmota_build_devel.yml
+++ b/.github/workflows/Tasmota_build_devel.yml
@@ -36,7 +36,6 @@ jobs:
- tasmota32-display
- tasmota32-ir
- tasmota32-lvgl
- - tasmota32-odroidgo
- tasmota32c3
- tasmota32solo1
steps:
From 5e15cd23967c00d7ae170be70e024f9a5a90966f Mon Sep 17 00:00:00 2001
From: Jason2866 <24528715+Jason2866@users.noreply.github.com>
Date: Sat, 12 Feb 2022 16:11:24 +0100
Subject: [PATCH 012/355] add s2 to CI
---
.github/workflows/build_all_the_things.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/build_all_the_things.yml b/.github/workflows/build_all_the_things.yml
index 359f9f114..f11f44eb2 100644
--- a/.github/workflows/build_all_the_things.yml
+++ b/.github/workflows/build_all_the_things.yml
@@ -39,7 +39,7 @@ jobs:
- tasmota32-display
- tasmota32-ir
- tasmota32-lvgl
- - tasmota32-odroidgo
+ - tasmota32s2
- tasmota32c3
- tasmota32solo1
steps:
From 3d2c9945a86992a500d265f35f04b5b9bb07b083 Mon Sep 17 00:00:00 2001
From: Theo Arends <11044339+arendst@users.noreply.github.com>
Date: Sat, 12 Feb 2022 16:37:48 +0100
Subject: [PATCH 013/355] Fix SSPM energy yesterday when zero
---
CHANGELOG.md | 1 +
tasmota/xdrv_86_esp32_sonoff_spm.ino | 13 ++++++++++---
2 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 88c4aa9e9..8fc7960e4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file.
### Changed
### Fixed
+- SSPM energy yesterday when zero
## [Released]
diff --git a/tasmota/xdrv_86_esp32_sonoff_spm.ino b/tasmota/xdrv_86_esp32_sonoff_spm.ino
index 6a5d2d086..27773eed1 100644
--- a/tasmota/xdrv_86_esp32_sonoff_spm.ino
+++ b/tasmota/xdrv_86_esp32_sonoff_spm.ino
@@ -252,6 +252,7 @@ typedef struct {
uint16_t expected_bytes;
uint8_t module[SSPM_MAX_MODULES][SSPM_MODULE_NAME_SIZE];
+ uint8_t history_day[SSPM_MAX_MODULES][4];
uint8_t allow_updates;
uint8_t get_energy_relay;
uint8_t get_totals;
@@ -1136,16 +1137,22 @@ void SSPMHandleReceivedData(void) {
energy_total += energy;
}
}
+
+ uint8_t history_day = SspmBuffer[36]; // Date of last entry
+ if (0 == Sspm->history_day[module][channel]) { // Initial setting
+ Sspm->history_day[module][channel] = history_day;
+ }
if ((0 == Sspm->Settings.energy_total[module][channel]) && energy_total) {
- Sspm->Settings.energy_yesterday[module][channel] = energy_yesterday; // Inital setting
+ Sspm->Settings.energy_yesterday[module][channel] = energy_yesterday; // Initial setting
Sspm->Settings.energy_total[module][channel] = energy_total; // Initial setting
if (Settings->save_data) {
TasmotaGlobal.save_data_counter = Settings->save_data +2; // Postpone flash write until all relays are updated
}
}
- // If received daily energy is below last daily energy then update total energy
+ // If received daily energy date is changed then update total energy
// This happens around midnight in normal situations
- else if (Sspm->energy_today[module][channel] < last_energy_today) {
+ else if (Sspm->history_day[module][channel] != history_day) {
+ Sspm->history_day[module][channel] = history_day;
Sspm->Settings.energy_yesterday[module][channel] = last_energy_today; // Daily save
Sspm->Settings.energy_total[module][channel] += last_energy_today; // Daily incremental save
if (Settings->save_data) {
From a9dfd284bb001cbbd3ef878a00087999bf39b1d9 Mon Sep 17 00:00:00 2001
From: Stephan Hadinger
Date: Sat, 12 Feb 2022 18:14:22 +0100
Subject: [PATCH 014/355] Berry update internal type system
---
lib/libesp32/berry/src/be_api.c | 8 ++---
lib/libesp32/berry/src/be_baselib.c | 4 +--
lib/libesp32/berry/src/be_bytecode.c | 10 +++---
lib/libesp32/berry/src/be_class.c | 38 ++++++++++----------
lib/libesp32/berry/src/be_class.h | 12 +++----
lib/libesp32/berry/src/be_constobj.h | 10 +++---
lib/libesp32/berry/src/be_exec.c | 2 +-
lib/libesp32/berry/src/be_gc.c | 10 +++---
lib/libesp32/berry/src/be_gc.h | 3 +-
lib/libesp32/berry/src/be_module.c | 5 ++-
lib/libesp32/berry/src/be_object.c | 2 +-
lib/libesp32/berry/src/be_object.h | 28 ++++++++-------
lib/libesp32/berry/src/be_parser.c | 11 +++---
lib/libesp32/berry/src/be_solidifylib.c | 6 ++--
lib/libesp32/berry/src/be_vm.c | 47 ++++++++++++++-----------
15 files changed, 101 insertions(+), 95 deletions(-)
diff --git a/lib/libesp32/berry/src/be_api.c b/lib/libesp32/berry/src/be_api.c
index 79d5c48ff..c3fd59e23 100644
--- a/lib/libesp32/berry/src/be_api.c
+++ b/lib/libesp32/berry/src/be_api.c
@@ -34,19 +34,19 @@ static void class_init(bvm *vm, bclass *c, const bnfuncinfo *lib)
while (lib->name) {
bstring *s = be_newstr(vm, lib->name);
if (lib->function) { /* method */
- be_prim_method_bind(vm, c, s, lib->function);
+ be_class_native_method_bind(vm, c, s, lib->function);
} else {
- be_member_bind(vm, c, s, btrue); /* member */
+ be_class_member_bind(vm, c, s, btrue); /* member */
}
++lib;
}
- if (lib->function == (bntvfunc) BE_CLOSURE) {
+ if (lib->function == (bntvfunc)BE_CLOSURE) {
/* next section is closures */
struct solidfuncinfo *slib = (struct solidfuncinfo*)++lib;
while (slib->name) {
if (slib->function) { /* method */
bstring *s = be_newstr(vm, slib->name);
- be_closure_method_bind(vm, c, s, slib->function);
+ be_class_closure_method_bind(vm, c, s, slib->function);
}
++slib;
}
diff --git a/lib/libesp32/berry/src/be_baselib.c b/lib/libesp32/berry/src/be_baselib.c
index f09c5f812..2b9c25095 100644
--- a/lib/libesp32/berry/src/be_baselib.c
+++ b/lib/libesp32/berry/src/be_baselib.c
@@ -85,7 +85,7 @@ static bclass *find_class_closure(bclass *cl, bclosure *needle)
if (members) { /* only iterate if there are members */
bmapiter iter = be_map_iter();
while ((node = be_map_next(members, &iter)) != NULL) {
- if (var_type(&node->value) == BE_CLOSURE) { /* only native functions are considered */
+ if (var_primetype(&node->value) == BE_CLOSURE) { /* only native functions are considered */
bclosure *clos_iter = var_toobj(&node->value); /* retrieve the method's closure */
if (clos_iter == needle) {
/* we found the closure, we now know its class */
@@ -140,7 +140,7 @@ static int l_super(bvm *vm)
if (size >= 2) { /* need at least 2 stackframes: current (for super() native) and caller (the one we are interested in) */
bcallframe *caller = be_vector_at(&vm->callstack, size - 2); /* get the callframe of caller */
bvalue *func = caller->func; /* function object of caller */
- if (var_type(func) == BE_CLOSURE) { /* only useful if the caller is a Berry closure (i.e. not native) */
+ if (var_primetype(func) == BE_CLOSURE) { /* only useful if the caller is a Berry closure (i.e. not native) */
bclosure *clos_ctx = var_toobj(func); /* this is the closure we look for in the class chain */
base_class = find_class_closure(o->_class, clos_ctx); /* iterate on current and super classes to find where the closure belongs */
}
diff --git a/lib/libesp32/berry/src/be_bytecode.c b/lib/libesp32/berry/src/be_bytecode.c
index 9f9283fbe..e7ba8aaca 100644
--- a/lib/libesp32/berry/src/be_bytecode.c
+++ b/lib/libesp32/berry/src/be_bytecode.c
@@ -176,8 +176,8 @@ static void save_class(bvm *vm, void *fp, bclass *c)
static void save_value(bvm *vm, void *fp, bvalue *v)
{
- save_byte(fp, (uint8_t)var_type(v)); /* type */
- switch (var_type(v)) {
+ save_byte(fp, (uint8_t)var_primetype(v)); /* type */
+ switch (var_primetype(v)) {
case BE_INT: save_int(fp, var_toint(v)); break;
case BE_REAL: save_real(fp, var_toreal(v)); break;
case BE_STRING: save_string(fp, var_tostr(v)); break;
@@ -425,16 +425,16 @@ static void load_class(bvm *vm, void *fp, bvalue *v, int version)
be_incrtop(vm);
if (load_proto(vm, fp, (bproto**)&var_toobj(value), -3, version)) {
/* actual method */
- be_method_bind(vm, c, name, var_toobj(value), bfalse);
+ be_class_method_bind(vm, c, name, var_toobj(value), bfalse);
} else {
/* no proto, static member set to nil */
- be_member_bind(vm, c, name, bfalse);
+ be_class_member_bind(vm, c, name, bfalse);
}
be_stackpop(vm, 2); /* pop the cached string and proto */
}
for (count = 0; count < nvar; ++count) { /* load member-variable table */
bstring *name = cache_string(vm, fp);
- be_member_bind(vm, c, name, btrue);
+ be_class_member_bind(vm, c, name, btrue);
be_stackpop(vm, 1); /* pop the cached string */
}
}
diff --git a/lib/libesp32/berry/src/be_class.c b/lib/libesp32/berry/src/be_class.c
index 0f4efb3d5..0ad035150 100644
--- a/lib/libesp32/berry/src/be_class.c
+++ b/lib/libesp32/berry/src/be_class.c
@@ -7,13 +7,11 @@
********************************************************************/
#include "be_class.h"
#include "be_string.h"
-#include "be_vector.h"
#include "be_map.h"
#include "be_exec.h"
#include "be_gc.h"
#include "be_vm.h"
#include "be_func.h"
-#include "be_var.h"
#include
#define check_members(vm, c) \
@@ -44,6 +42,7 @@ void be_class_compress(bvm *vm, bclass *c)
}
}
+/* Return the type of the class attribute, only used to check if the attribute already exists */
int be_class_attribute(bvm *vm, bclass *c, bstring *attr)
{
for (; c; c = c->super) {
@@ -57,7 +56,7 @@ int be_class_attribute(bvm *vm, bclass *c, bstring *attr)
return BE_NONE;
}
-void be_member_bind(bvm *vm, bclass *c, bstring *name, bbool var)
+void be_class_member_bind(bvm *vm, bclass *c, bstring *name, bbool var)
{
bvalue *attr;
set_fixed(name);
@@ -75,7 +74,7 @@ void be_member_bind(bvm *vm, bclass *c, bstring *name, bbool var)
}
}
-void be_method_bind(bvm *vm, bclass *c, bstring *name, bproto *p, bbool is_static)
+void be_class_method_bind(bvm *vm, bclass *c, bstring *name, bproto *p, bbool is_static)
{
bclosure *cl;
bvalue *attr;
@@ -88,11 +87,11 @@ void be_method_bind(bvm *vm, bclass *c, bstring *name, bproto *p, bbool is_stati
cl->proto = p;
var_setclosure(attr, cl);
if (is_static) {
- func_setstatic(attr);
+ var_markstatic(attr);
}
}
-void be_prim_method_bind(bvm *vm, bclass *c, bstring *name, bntvfunc f)
+void be_class_native_method_bind(bvm *vm, bclass *c, bstring *name, bntvfunc f)
{
bvalue *attr;
set_fixed(name);
@@ -103,7 +102,7 @@ void be_prim_method_bind(bvm *vm, bclass *c, bstring *name, bntvfunc f)
attr->type = MT_PRIMMETHOD;
}
-void be_closure_method_bind(bvm *vm, bclass *c, bstring *name, bclosure *cl)
+void be_class_closure_method_bind(bvm *vm, bclass *c, bstring *name, bclosure *cl)
{
bvalue *attr;
check_members(vm, c);
@@ -242,7 +241,8 @@ bbool be_class_newobj(bvm *vm, bclass *c, int pos, int argc, int mode)
}
/* Default empty constructor */
-static int default_init_native_method(bvm *vm) {
+static int default_init_native_method(bvm *vm)
+{
be_return_nil(vm);
}
@@ -253,10 +253,11 @@ int be_instance_member_simple(bvm *vm, binstance *instance, bstring *name, bvalu
int type;
be_assert(name != NULL);
binstance * obj = instance_member(vm, instance, name, dst);
- type = var_type(dst);
- if (obj && type == MT_VARIABLE) {
+ if (obj && var_type(dst) == MT_VARIABLE) {
*dst = obj->members[dst->v.i];
}
+ type = var_type(dst);
+ var_clearstatic(dst);
return type;
}
@@ -268,18 +269,19 @@ int be_instance_member(bvm *vm, binstance *instance, bstring *name, bvalue *dst)
{
int type;
be_assert(name != NULL);
- binstance * obj = instance_member(vm, instance, name, dst);
- type = var_type(dst);
- if (obj && type == MT_VARIABLE) {
+ binstance *obj = instance_member(vm, instance, name, dst);
+ if (obj && var_type(dst) == MT_VARIABLE) {
*dst = obj->members[dst->v.i];
}
+ type = var_type(dst);
if (obj) {
+ var_clearstatic(dst);
return type;
} else { /* if no method found, try virtual */
/* if 'init' does not exist, create a virtual empty constructor */
if (strcmp(str(name), "init") == 0) {
var_setntvfunc(dst, default_init_native_method);
- return var_type(dst);
+ return var_primetype(dst);
} else {
/* get method 'member' */
obj = instance_member(vm, instance, str_literal(vm, "member"), vm->top);
@@ -296,6 +298,7 @@ int be_instance_member(bvm *vm, binstance *instance, bstring *name, bvalue *dst)
}
type = var_type(dst);
if (type != BE_NIL) {
+ var_clearstatic(dst);
return type;
}
}
@@ -310,11 +313,8 @@ int be_class_member(bvm *vm, bclass *obj, bstring *name, bvalue *dst)
be_assert(name != NULL);
obj = class_member(vm, obj, name, dst);
type = var_type(dst);
- if (obj) {
- return type;
- } else {
- return BE_NONE;
- }
+ var_clearstatic(dst);
+ return obj ? type : BE_NONE;
}
bbool be_instance_setmember(bvm *vm, binstance *o, bstring *name, bvalue *src)
diff --git a/lib/libesp32/berry/src/be_class.h b/lib/libesp32/berry/src/be_class.h
index 405ea6d38..f80ca8799 100644
--- a/lib/libesp32/berry/src/be_class.h
+++ b/lib/libesp32/berry/src/be_class.h
@@ -52,17 +52,17 @@ struct binstance {
bclass* be_newclass(bvm *vm, bstring *name, bclass *super);
void be_class_compress(bvm *vm, bclass *c);
int be_class_attribute(bvm *vm, bclass *c, bstring *attr);
-void be_member_bind(bvm *vm, bclass *c, bstring *name, bbool var);
-void be_method_bind(bvm *vm, bclass *c, bstring *name, bproto *p, bbool is_static);
-void be_prim_method_bind(bvm *vm, bclass *c, bstring *name, bntvfunc f);
-void be_closure_method_bind(bvm *vm, bclass *c, bstring *name, bclosure *cl);
+void be_class_member_bind(bvm *vm, bclass *c, bstring *name, bbool var);
+void be_class_method_bind(bvm *vm, bclass *c, bstring *name, bproto *p, bbool is_static);
+void be_class_native_method_bind(bvm *vm, bclass *c, bstring *name, bntvfunc f);
+void be_class_closure_method_bind(bvm *vm, bclass *c, bstring *name, bclosure *cl);
+int be_class_member(bvm *vm, bclass *obj, bstring *name, bvalue *dst);
+bbool be_class_setmember(bvm *vm, bclass *obj, bstring *name, bvalue *src);
int be_class_closure_count(bclass *c);
void be_class_upvalue_init(bvm *vm, bclass *c);
bbool be_class_newobj(bvm *vm, bclass *c, int pos, int argc, int mode);
int be_instance_member_simple(bvm *vm, binstance *obj, bstring *name, bvalue *dst);
int be_instance_member(bvm *vm, binstance *obj, bstring *name, bvalue *dst);
-int be_class_member(bvm *vm, bclass *obj, bstring *name, bvalue *dst);
bbool be_instance_setmember(bvm *vm, binstance *obj, bstring *name, bvalue *src);
-bbool be_class_setmember(bvm *vm, bclass *obj, bstring *name, bvalue *src);
#endif
diff --git a/lib/libesp32/berry/src/be_constobj.h b/lib/libesp32/berry/src/be_constobj.h
index 301b06af8..708cce03d 100644
--- a/lib/libesp32/berry/src/be_constobj.h
+++ b/lib/libesp32/berry/src/be_constobj.h
@@ -40,7 +40,7 @@ extern "C" {
#define be_const_static_func(_func) { \
.v.nf = (_func), \
- .type = BE_NTVFUNC | BE_FUNC_STATIC \
+ .type = BE_NTVFUNC | BE_STATIC \
}
#define be_const_nil() { \
@@ -79,7 +79,7 @@ extern "C" {
}
#define be_const_comptr(_val) { \
- .v.c = (const void*)(_val), \
+ .v.c = (const void*)(_val), \
.type = BE_COMPTR \
}
@@ -95,7 +95,7 @@ extern "C" {
#define be_const_static_closure(_closure) { \
.v.c = &(_closure), \
- .type = BE_CLOSURE | BE_FUNC_STATIC \
+ .type = BE_CLOSURE | BE_STATIC \
}
#define be_const_module(_module) { \
@@ -256,7 +256,7 @@ const bntvmodule be_native_module(_module) = { \
#define be_const_static_func(_func) { \
bvaldata(_func), \
- BE_NTVFUNC | BE_FUNC_STATIC \
+ BE_NTVFUNC | BE_STATIC \
}
#define be_const_nil() { \
@@ -311,7 +311,7 @@ const bntvmodule be_native_module(_module) = { \
#define be_const_static_closure(_closure) { \
bvaldata(&(_closure)), \
- BE_CLOSURE | BE_FUNC_STATIC \
+ BE_CLOSURE | BE_STATIC \
}
#define be_const_module(_module) { \
diff --git a/lib/libesp32/berry/src/be_exec.c b/lib/libesp32/berry/src/be_exec.c
index 14dbe903c..c2b2e1f6a 100644
--- a/lib/libesp32/berry/src/be_exec.c
+++ b/lib/libesp32/berry/src/be_exec.c
@@ -335,7 +335,7 @@ void be_stackpush(bvm *vm)
}
/* check that the stack is able to store `count` items, and increase stack if needed */
-void be_stack_require(bvm *vm, int count)
+BERRY_API void be_stack_require(bvm *vm, int count)
{
if (vm->top + count >= vm->stacktop) {
be_stack_expansion(vm, count);
diff --git a/lib/libesp32/berry/src/be_gc.c b/lib/libesp32/berry/src/be_gc.c
index 19e88cb12..9e1ca0b74 100644
--- a/lib/libesp32/berry/src/be_gc.c
+++ b/lib/libesp32/berry/src/be_gc.c
@@ -138,7 +138,8 @@ static void mark_gray(bvm *vm, bgcobject *obj)
{
if (obj && gc_iswhite(obj) && !gc_isconst(obj)) {
gc_setgray(obj);
- switch (var_type(obj)) {
+ be_assert(!var_isstatic(obj));
+ switch (var_primetype(obj)) {
case BE_STRING: gc_setdark(obj); break; /* just set dark */
case BE_CLASS: link_gray(vm, cast_class(obj)); break;
case BE_PROTO: link_gray(vm, cast_proto(obj)); break;
@@ -171,7 +172,7 @@ static void mark_map(bvm *vm, bgcobject *obj)
while ((node = be_map_next(map, &iter)) != NULL) {
bmapkey *key = &node->key;
bvalue *val = &node->value;
- if (be_isgctype((signed char)key->type)) {
+ if (be_isgcobj(key)) {
mark_gray(vm, var_togc(key));
}
mark_gray_var(vm, val);
@@ -348,7 +349,7 @@ static void free_instance(bvm *vm, bgcobject *obj)
static void free_object(bvm *vm, bgcobject *obj)
{
- switch (var_type(obj)) {
+ switch (var_primetype(obj)) {
case BE_STRING: free_lstring(vm, obj); break; /* long string */
case BE_CLASS: be_free(vm, obj, sizeof(bclass)); break;
case BE_INSTANCE: free_instance(vm, obj); break;
@@ -432,7 +433,8 @@ static void mark_unscanned(bvm *vm)
bgcobject *obj = vm->gc.gray;
if (obj && !gc_isdark(obj) && !gc_isconst(obj)) {
gc_setdark(obj);
- switch (var_type(obj)) {
+ be_assert(!var_isstatic(obj));
+ switch (var_primetype(obj)) {
case BE_CLASS: mark_class(vm, obj); break;
case BE_PROTO: mark_proto(vm, obj); break;
case BE_INSTANCE: mark_instance(vm, obj); break;
diff --git a/lib/libesp32/berry/src/be_gc.h b/lib/libesp32/berry/src/be_gc.h
index 0e0ce9e82..49e311291 100644
--- a/lib/libesp32/berry/src/be_gc.h
+++ b/lib/libesp32/berry/src/be_gc.h
@@ -47,8 +47,7 @@ if (!gc_isconst(o)) { \
#define gc_exmark(o) (((o)->marked >> 4) & 0x0F)
#define gc_setexmark(o, k) ((o)->marked |= (k) << 4)
-#define be_isgctype(t) ((t) >= BE_GCOBJECT)
-#define be_isgcobj(o) be_isgctype(var_type(o))
+#define be_isgcobj(o) (var_primetype(o) >= BE_GCOBJECT)
#define be_gcnew(v, t, s) be_newgcobj((v), (t), sizeof(s))
#define set_fixed(s) bbool _was_fixed = be_gc_fix_set(vm, cast(bgcobject*, (s)), 1)
diff --git a/lib/libesp32/berry/src/be_module.c b/lib/libesp32/berry/src/be_module.c
index 0256809af..ab4504ee5 100644
--- a/lib/libesp32/berry/src/be_module.c
+++ b/lib/libesp32/berry/src/be_module.c
@@ -329,10 +329,9 @@ int be_module_attr(bvm *vm, bmodule *module, bstring *attr, bvalue *dst)
}
}
return BE_NONE;
- } else {
- *dst = *member;
- return var_type(dst);
}
+ *dst = *member;
+ return var_type(dst);
}
bbool be_module_setmember(bvm *vm, bmodule *module, bstring *attr, bvalue *src)
diff --git a/lib/libesp32/berry/src/be_object.c b/lib/libesp32/berry/src/be_object.c
index ed338f790..138fcc1f1 100644
--- a/lib/libesp32/berry/src/be_object.c
+++ b/lib/libesp32/berry/src/be_object.c
@@ -15,7 +15,7 @@
const char* be_vtype2str(bvalue *v)
{
- switch(var_type(v)) {
+ switch(var_primetype(v)) {
case BE_NIL: return "nil";
case BE_INT: return "int";
case BE_REAL: return "real";
diff --git a/lib/libesp32/berry/src/be_object.h b/lib/libesp32/berry/src/be_object.h
index df7c7a9af..67e79bcdf 100644
--- a/lib/libesp32/berry/src/be_object.h
+++ b/lib/libesp32/berry/src/be_object.h
@@ -11,14 +11,14 @@
#include "berry.h"
/* basic types, do not change value */
+#define BE_NONE -256 /* unknown type */
#define BE_NIL 0
#define BE_INT 1
#define BE_REAL 2
#define BE_BOOL 3
-#define BE_NONE 4 /* unknown type */
-#define BE_COMPTR 5 /* common pointer */
-#define BE_INDEX 6 /* index for instance variable, previously BE_INT */
-#define BE_FUNCTION 7
+#define BE_COMPTR 4 /* common pointer */
+#define BE_INDEX 5 /* index for instance variable, previously BE_INT */
+#define BE_FUNCTION 6
#define BE_GCOBJECT 16 /* from this type can be gced */
@@ -35,11 +35,11 @@
#define BE_CLOSURE ((1 << 5) | BE_FUNCTION)
#define BE_NTVCLOS ((2 << 5) | BE_FUNCTION)
#define BE_CTYPE_FUNC ((3 << 5) | BE_FUNCTION)
-#define BE_FUNC_STATIC (1 << 7)
+#define BE_STATIC (1 << 7)
-#define func_isstatic(o) (((o)->type & BE_FUNC_STATIC) != 0)
-#define func_setstatic(o) ((o)->type |= BE_FUNC_STATIC)
-#define func_clearstatic(o) ((o)->type &= ~BE_FUNC_STATIC)
+#define func_isstatic(o) (((o)->type & BE_STATIC) != 0)
+#define func_setstatic(o) ((o)->type |= BE_STATIC)
+#define func_clearstatic(o) ((o)->type &= ~BE_STATIC)
/* values for bproto.varg */
#define BE_VA_VARARG (1 << 0) /* function has variable number of arguments */
@@ -201,10 +201,14 @@ typedef const char* (*breader)(void*, size_t*);
#define cast_bool(_v) cast(bbool, _v)
#define basetype(_t) ((_t) & 0x1F)
-#define var_type(_v) ((_v)->type & 0x7F)
+#define var_type(_v) ((_v)->type)
#define var_basetype(_v) basetype((_v)->type)
-#define var_istype(_v, _t) (var_type(_v) == _t)
+#define var_primetype(_v) (var_type(_v) & ~BE_STATIC)
+#define var_isstatic(_v) ((var_type(_v) & BE_STATIC) == BE_STATIC)
+#define var_istype(_v, _t) (var_primetype(_v) == _t)
#define var_settype(_v, _t) ((_v)->type = _t)
+#define var_markstatic(_v) var_settype(_v, var_type(_v) | BE_STATIC)
+#define var_clearstatic(_v) var_settype(_v, var_type(_v) & ~BE_STATIC)
#define var_setobj(_v, _t, _o) { (_v)->v.p = _o; var_settype(_v, _t); }
#define var_isnil(_v) var_istype(_v, BE_NIL)
@@ -215,7 +219,6 @@ typedef const char* (*breader)(void*, size_t*);
#define var_isclosure(_v) var_istype(_v, BE_CLOSURE)
#define var_isntvclos(_v) var_istype(_v, BE_NTVCLOS)
#define var_isntvfunc(_v) var_istype(_v, BE_NTVFUNC)
-#define var_isctypefunc(_v) var_istype(_v, BE_CTYPEFUNC)
#define var_isfunction(_v) (var_basetype(_v) == BE_FUNCTION)
#define var_isproto(_v) var_istype(_v, BE_PROTO)
#define var_isclass(_v) var_istype(_v, BE_CLASS)
@@ -238,11 +241,10 @@ typedef const char* (*breader)(void*, size_t*);
#define var_setclosure(_v, _o) var_setobj(_v, BE_CLOSURE, _o)
#define var_setntvclos(_v, _o) var_setobj(_v, BE_NTVCLOS, _o)
#define var_setntvfunc(_v, _o) { (_v)->v.nf = (_o); var_settype(_v, BE_NTVFUNC); }
-#define var_setctypefunc(_v, _o) { (_v)->v.nf = (_o); var_settype(_v, BE_CTYPEFUNC); }
#define var_setlist(_v, _o) var_setobj(_v, BE_LIST, _o)
#define var_setmap(_v, _o) var_setobj(_v, BE_MAP, _o)
#define var_setmodule(_v, _o) var_setobj(_v, BE_MODULE, _o)
-#define var_setindex(_v, _i) { var_settype(_v, BE_INDEX); (_v)->v.i = (_i); }
+#define var_setindex(_v, _i) { var_settype(_v, BE_INDEX); (_v)->v.i = (_i); }
#define var_setproto(_v, _o) var_setobj(_v, BE_PROTO, _o)
#define var_tobool(_v) ((_v)->v.b)
diff --git a/lib/libesp32/berry/src/be_parser.c b/lib/libesp32/berry/src/be_parser.c
index af59f5749..ba5b408d8 100644
--- a/lib/libesp32/berry/src/be_parser.c
+++ b/lib/libesp32/berry/src/be_parser.c
@@ -18,7 +18,6 @@
#include "be_func.h"
#include "be_class.h"
#include "be_decoder.h"
-#include "be_debug.h"
#include "be_exec.h"
#include
@@ -1392,11 +1391,11 @@ static void classvar_stmt(bparser *parser, bclass *c)
scan_next_token(parser); /* skip 'var' */
if (match_id(parser, name) != NULL) {
check_class_attr(parser, c, name);
- be_member_bind(parser->vm, c, name, btrue);
+ be_class_member_bind(parser->vm, c, name, btrue);
while (match_skip(parser, OptComma)) { /* ',' */
if (match_id(parser, name) != NULL) {
check_class_attr(parser, c, name);
- be_member_bind(parser->vm, c, name, btrue);
+ be_class_member_bind(parser->vm, c, name, btrue);
} else {
parser_error(parser, "class var error");
}
@@ -1433,7 +1432,7 @@ static void classdef_stmt(bparser *parser, bclass *c, bbool is_static)
name = func_name(parser, &e, 1);
check_class_attr(parser, c, name);
proto = funcbody(parser, name, is_static ? 0 : FUNC_METHOD);
- be_method_bind(parser->vm, c, proto->name, proto, is_static);
+ be_class_method_bind(parser->vm, c, proto->name, proto, is_static);
be_stackpop(parser->vm, 1);
}
@@ -1446,13 +1445,13 @@ static void classstatic_stmt(bparser *parser, bclass *c, bexpdesc *e)
classdef_stmt(parser, c, btrue);
} else if (match_id(parser, name) != NULL) {
check_class_attr(parser, c, name);
- be_member_bind(parser->vm, c, name, bfalse);
+ be_class_member_bind(parser->vm, c, name, bfalse);
class_static_assignment_expr(parser, e, name);
while (match_skip(parser, OptComma)) { /* ',' */
if (match_id(parser, name) != NULL) {
check_class_attr(parser, c, name);
- be_member_bind(parser->vm, c, name, bfalse);
+ be_class_member_bind(parser->vm, c, name, bfalse);
class_static_assignment_expr(parser, e, name);
} else {
parser_error(parser, "class static error");
diff --git a/lib/libesp32/berry/src/be_solidifylib.c b/lib/libesp32/berry/src/be_solidifylib.c
index 4d4e3bcb6..1767fb16b 100644
--- a/lib/libesp32/berry/src/be_solidifylib.c
+++ b/lib/libesp32/berry/src/be_solidifylib.c
@@ -148,7 +148,7 @@ static void m_solidify_list(bvm *vm, blist * list, const char *class_name)
// pass key name in case of class, or NULL if none
static void m_solidify_bvalue(bvm *vm, bvalue * value, const char *classname, const char *key)
{
- int type = var_type(value);
+ int type = var_primetype(value);
switch (type) {
case BE_NIL:
logfmt("be_const_nil()");
@@ -197,7 +197,7 @@ static void m_solidify_bvalue(bvm *vm, bvalue * value, const char *classname, co
char func_name_id[id_len];
toidentifier(func_name_id, func_name);
logfmt("be_const_%sclosure(%s%s%s_closure)",
- func_isstatic(value) ? "static_" : "",
+ var_isstatic(value) ? "static_" : "",
classname ? classname : "", classname ? "_" : "",
func_name_id);
}
@@ -210,7 +210,7 @@ static void m_solidify_bvalue(bvm *vm, bvalue * value, const char *classname, co
break;
case BE_NTVFUNC:
logfmt("be_const_%sfunc(be_ntv_%s_%s)",
- func_isstatic(value) ? "static_" : "",
+ var_isstatic(value) ? "static_" : "",
classname ? classname : "unknown", key ? key : "unknown");
break;
case BE_INSTANCE:
diff --git a/lib/libesp32/berry/src/be_vm.c b/lib/libesp32/berry/src/be_vm.c
index 3032fa8ae..622930526 100644
--- a/lib/libesp32/berry/src/be_vm.c
+++ b/lib/libesp32/berry/src/be_vm.c
@@ -83,13 +83,15 @@
#define equal_rule(op, iseq) \
bbool res; \
+ be_assert(!var_isstatic(a)); \
+ be_assert(!var_isstatic(b)); \
if (var_isint(a) && var_isint(b)) { \
res = ibinop(op, a, b); \
} else if (var_isnumber(a) && var_isnumber(b)) { \
res = var2real(a) op var2real(b); \
} else if (var_isinstance(a) && !var_isnil(b)) { \
res = object_eqop(vm, #op, iseq, a, b); \
- } else if (var_type(a) == var_type(b)) { /* same types */ \
+ } else if (var_primetype(a) == var_primetype(b)) { /* same types */ \
if (var_isnil(a)) { /* nil op nil */ \
res = 1 op 1; \
} else if (var_isbool(a)) { /* bool op bool */ \
@@ -256,6 +258,7 @@ static bbool obj2bool(bvm *vm, bvalue *var)
binstance *obj = var_toobj(var);
bstring *tobool = str_literal(vm, "tobool");
/* get operator method */
+ // TODO what if `tobool` is static
int type = be_instance_member(vm, obj, tobool, vm->top);
if (type != BE_NONE && type != BE_NIL) {
vm->top[1] = *var; /* move self to argv[0] */
@@ -342,6 +345,7 @@ static bbool object_eqop(bvm *vm,
bbool isself = var_isinstance(b) && o == var_toobj(b);
/* first, try to call the overloaded operator of the object */
int type = be_instance_member(vm, o, be_newstr(vm, op), vm->top);
+ // TODO check that method is not static
if (basetype(type) == BE_FUNCTION) { /* call method */
bvalue *top = vm->top;
top[1] = self; /* move self to argv[0] */
@@ -826,41 +830,41 @@ newframe: /* a new call frame */
#if BE_USE_PERF_COUNTERS
vm->counter_get++;
#endif
- bvalue a_temp; /* copy result to a temp variable because the stack may be relocated in virtual member calls */
+ bvalue result; /* copy result to a temp variable because the stack may be relocated in virtual member calls */
bvalue *b = RKB(), *c = RKC();
if (var_isinstance(b) && var_isstr(c)) {
- obj_attribute(vm, b, var_tostr(c), &a_temp);
+ obj_attribute(vm, b, var_tostr(c), &result);
reg = vm->reg;
} else if (var_isclass(b) && var_isstr(c)) {
- class_attribute(vm, b, c, &a_temp);
+ class_attribute(vm, b, c, &result);
reg = vm->reg;
} else if (var_ismodule(b) && var_isstr(c)) {
- module_attribute(vm, b, c, &a_temp);
+ module_attribute(vm, b, c, &result);
reg = vm->reg;
} else {
attribute_error(vm, "attribute", b, c);
- a_temp = *RA(); /* avoid gcc warning for uninitialized variable a_temp, this code is never reached */
+ result = *RA(); /* avoid gcc warning for uninitialized variable result, this code is never reached */
}
bvalue *a = RA();
- *a = a_temp; /* assign the resul to the specified register on the updated stack */
+ *a = result; /* assign the resul to the specified register on the updated stack */
dispatch();
}
opcase(GETMET): {
#if BE_USE_PERF_COUNTERS
vm->counter_get++;
#endif
- bvalue a_temp; /* copy result to a temp variable because the stack may be relocated in virtual member calls */
+ bvalue result; /* copy result to a temp variable because the stack may be relocated in virtual member calls */
bvalue *b = RKB(), *c = RKC();
if (var_isinstance(b) && var_isstr(c)) {
binstance *obj = var_toobj(b);
- int type = obj_attribute(vm, b, var_tostr(c), &a_temp);
+ int type = obj_attribute(vm, b, var_tostr(c), &result);
reg = vm->reg;
bvalue *a = RA();
- *a = a_temp;
+ *a = result;
if (var_basetype(a) == BE_FUNCTION) {
- if (func_isstatic(a) || (type == BE_INDEX)) { /* if instance variable then we consider it's non-method */
- /* static method, don't bother with the instance */
- a[1] = a_temp;
+ if ((type & BE_STATIC) || (type == BE_INDEX)) { /* if instance variable then we consider it's non-method */
+ /* static method, don't bother with the instance */
+ a[1] = result;
var_settype(a, NOT_METHOD);
} else {
/* this is a real method (i.e. non-static) */
@@ -876,16 +880,16 @@ newframe: /* a new call frame */
str(be_instance_name(obj)), str(var_tostr(c)));
}
} else if (var_isclass(b) && var_isstr(c)) {
- class_attribute(vm, b, c, &a_temp);
+ class_attribute(vm, b, c, &result);
reg = vm->reg;
bvalue *a = RA();
- a[1] = a_temp;
+ a[1] = result;
var_settype(a, NOT_METHOD);
} else if (var_ismodule(b) && var_isstr(c)) {
- module_attribute(vm, b, c, &a_temp);
+ module_attribute(vm, b, c, &result);
reg = vm->reg;
bvalue *a = RA();
- a[1] = a_temp;
+ a[1] = result;
var_settype(a, NOT_METHOD);
} else {
attribute_error(vm, "method", b, c);
@@ -913,11 +917,11 @@ newframe: /* a new call frame */
/* if value is a function, we mark it as a static to distinguish from methods */
bclass *obj = var_toobj(a);
bstring *attr = var_tostr(b);
- bvalue c_static = *c;
- if (var_isfunction(&c_static)) {
- c_static.type = func_setstatic(&c_static);
+ bvalue result = *c;
+ if (var_isfunction(&result)) {
+ var_markstatic(&result);
}
- if (!be_class_setmember(vm, obj, attr, &c_static)) {
+ if (!be_class_setmember(vm, obj, attr, &result)) {
reg = vm->reg;
vm_error(vm, "attribute_error",
"class '%s' cannot assign to static attribute '%s'",
@@ -1253,6 +1257,7 @@ void be_dofunc(bvm *vm, bvalue *v, int argc)
be_assert(vm->reg <= v && v < vm->stacktop);
be_assert(vm->stack <= vm->reg && vm->reg < vm->stacktop);
int pos = v - vm->reg;
+ be_assert(!var_isstatic(v));
switch (var_type(v)) {
case BE_CLASS: do_class(vm, pos, argc); break;
case BE_CLOSURE: do_closure(vm, pos, argc); break;
From 35571322b46f43d4a951d3414d85ad30f7740981 Mon Sep 17 00:00:00 2001
From: Theo Arends <11044339+arendst@users.noreply.github.com>
Date: Sat, 12 Feb 2022 18:27:01 +0100
Subject: [PATCH 015/355] Update migration links
---
README.md | 10 +++++-----
RELEASENOTES.md | 10 +++++-----
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/README.md b/README.md
index b2f01d470..97339b00c 100644
--- a/README.md
+++ b/README.md
@@ -73,17 +73,17 @@ Pay attention to the following version breaks due to dynamic settings updates:
1. Migrate to **Sonoff-Tasmota 3.9.x**
2. Migrate to **Sonoff-Tasmota 4.x**
3. Migrate to **Sonoff-Tasmota 5.14**
-4. Migrate to **Sonoff-Tasmota 6.7.1** (http://ota.tasmota.com/tasmota/release-6.7.1/)
-5. Migrate to **Tasmota 7.2.0** (http://ota.tasmota.com/tasmota/release-7.2.0/)
+4. Migrate to **Sonoff-Tasmota 6.7.1** (http://ota.tasmota.com/tasmota/release_6.7.1/sonoff.bin) - NOTICE underscore as a dash is not supported in older versions
+5. Migrate to **Tasmota 7.2.0** (http://ota.tasmota.com/tasmota/release-7.2.0/tasmota.bin)
--- Major change in parameter storage layout ---
-6. Migrate to **Tasmota 8.5.1** (http://ota.tasmota.com/tasmota/release-8.5.1/)
+6. Migrate to **Tasmota 8.5.1** (http://ota.tasmota.com/tasmota/release-8.5.1/tasmota.bin)
--- Major change in internal GPIO function representation ---
-7. Migrate to **Tasmota 9.1** (http://ota.tasmota.com/tasmota/release-9.1.0/)
-8. Upgrade to **latest release** (http://ota.tasmota.com/tasmota/release/)
+7. Migrate to **Tasmota 9.1** (http://ota.tasmota.com/tasmota/release-9.1.0/tasmota.bin.gz)
+8. Upgrade to **latest release** (http://ota.tasmota.com/tasmota/release/tasmota.bin.gz)
While fallback or downgrading is common practice it was never supported due to Settings additions or changes in newer releases. Starting with release **v9.1.0 Imogen** the internal GPIO function representation has changed in such a way that fallback is only possible to the latest GPIO configuration before installing **v9.1.0**.
diff --git a/RELEASENOTES.md b/RELEASENOTES.md
index 54fc8a90f..e708ba31e 100644
--- a/RELEASENOTES.md
+++ b/RELEASENOTES.md
@@ -15,17 +15,17 @@ Pay attention to the following version breaks due to dynamic settings updates:
1. Migrate to **Sonoff-Tasmota 3.9.x**
2. Migrate to **Sonoff-Tasmota 4.x**
3. Migrate to **Sonoff-Tasmota 5.14**
-4. Migrate to **Sonoff-Tasmota 6.7.1** (http://ota.tasmota.com/tasmota/release-6.7.1/)
-5. Migrate to **Tasmota 7.2.0** (http://ota.tasmota.com/tasmota/release-7.2.0/)
+4. Migrate to **Sonoff-Tasmota 6.7.1** (http://ota.tasmota.com/tasmota/release_6.7.1/sonoff.bin) - NOTICE underscore as a dash is not supported in older versions
+5. Migrate to **Tasmota 7.2.0** (http://ota.tasmota.com/tasmota/release-7.2.0/tasmota.bin)
--- Major change in parameter storage layout ---
-6. Migrate to **Tasmota 8.5.1** (http://ota.tasmota.com/tasmota/release-8.5.1/)
+6. Migrate to **Tasmota 8.5.1** (http://ota.tasmota.com/tasmota/release-8.5.1/tasmota.bin)
--- Major change in internal GPIO function representation ---
-7. Migrate to **Tasmota 9.1** (http://ota.tasmota.com/tasmota/release-9.1.0/)
-8. Upgrade to **latest release** (http://ota.tasmota.com/tasmota/release/)
+7. Migrate to **Tasmota 9.1** (http://ota.tasmota.com/tasmota/release-9.1.0/tasmota.bin.gz)
+8. Upgrade to **latest release** (http://ota.tasmota.com/tasmota/release/tasmota.bin.gz)
While fallback or downgrading is common practice it was never supported due to Settings additions or changes in newer releases. Starting with release **v9.1.0 Imogen** the internal GPIO function representation has changed in such a way that fallback is only possible to the latest GPIO configuration before installing **v9.1.0**.
From 246efd95393f997c646104af62d94eec702e1331 Mon Sep 17 00:00:00 2001
From: Theo Arends <11044339+arendst@users.noreply.github.com>
Date: Sat, 12 Feb 2022 18:32:38 +0100
Subject: [PATCH 016/355] Update changelogs
---
CHANGELOG.md | 1 +
RELEASENOTES.md | 2 ++
2 files changed, 3 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8fc7960e4..5b4ee441b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file.
### Added
### Changed
+- ESP32 update the internal Berry type system to sync with Skiars Berry reopsitory. No expected impact on code, but .bec files need to be generated again. (#14811)
### Fixed
- SSPM energy yesterday when zero
diff --git a/RELEASENOTES.md b/RELEASENOTES.md
index e708ba31e..ae0046010 100644
--- a/RELEASENOTES.md
+++ b/RELEASENOTES.md
@@ -109,7 +109,9 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo
### Breaking Changed
### Changed
+- ESP32 update the internal Berry type system to sync with Skiars Berry reopsitory. No expected impact on code, but .bec files need to be generated again. [#14811](https://github.com/arendst/Tasmota/issues/14811)
### Fixed
+- SSPM energy yesterday when zero
### Removed
From 33a779f105beb4a42678ec0ff5ca0c95817d7b56 Mon Sep 17 00:00:00 2001
From: s-hadinger <49731213+s-hadinger@users.noreply.github.com>
Date: Sat, 12 Feb 2022 18:54:39 +0100
Subject: [PATCH 017/355] LVGL library from 8.1.0 to 8.2.0 (#14815)
---
lib/libesp32/berry/default/be_modtab.c | 2 +
lib/libesp32/berry/generate/be_const_strtab.h | 9 +
.../berry/generate/be_const_strtab_def.h | 2031 +++++++++--------
.../be_fixed_be_class_tasmota_log_reader.h | 19 +
.../berry/generate/be_fixed_lv_tasmota.h | 19 +-
.../berry_mapping/src/be_class_wrapper.c | 4 +-
.../berry_tasmota/src/be_lv_tasmota_lib.c | 73 +-
.../src/be_lvgl_signal_arcs_lib.c | 323 ++-
.../src/be_lvgl_signal_bars_lib.c | 171 +-
.../src/be_tasmota_log_reader_class.cpp | 25 +
.../src/embedded/lv_signal_arcs.be | 29 +-
.../src/embedded/lv_signal_bars.be | 4 +-
.../berry_tasmota/src/embedded/lv_tasmota.be | 1 +
.../LVGL_assets/src/lv_theme_openhasp.c | 2 +-
lib/libesp32_lvgl/freetype/library.json | 1 +
.../lv_berry/generate/be_lv_c_mapping.h | 9 +
.../lv_berry/generate/be_lvgl_module.c | 44 +-
.../lv_berry/generate/be_lvgl_widgets_lib.c | 153 +-
lib/libesp32_lvgl/lv_berry/mapping/lv_enum.h | 22 +-
lib/libesp32_lvgl/lv_berry/mapping/lv_funcs.h | 192 +-
.../lv_berry/src/be_lvgl_ctypes_definitions.c | 235 +-
.../lv_berry/src/embedded/lvgl_ctypes.be | 165 +-
lib/libesp32_lvgl/lv_berry/tools/convert.py | 4 +
.../lv_berry/tools/preprocessor.py | 6 +-
lib/libesp32_lvgl/lvgl/Kconfig | 541 ++++-
lib/libesp32_lvgl/lvgl/README.md | 12 +-
lib/libesp32_lvgl/lvgl/library.json | 2 +-
lib/libesp32_lvgl/lvgl/library.properties | 2 +-
lib/libesp32_lvgl/lvgl/lv_conf_template.h | 329 ++-
lib/libesp32_lvgl/lvgl/lvgl.h | 2 +-
lib/libesp32_lvgl/lvgl/lvgl.mk | 3 +-
lib/libesp32_lvgl/lvgl/src/core/lv_event.c | 73 +-
lib/libesp32_lvgl/lvgl/src/core/lv_event.h | 43 +-
lib/libesp32_lvgl/lvgl/src/core/lv_group.c | 13 +-
lib/libesp32_lvgl/lvgl/src/core/lv_indev.c | 56 +-
lib/libesp32_lvgl/lvgl/src/core/lv_indev.h | 2 +-
.../lvgl/src/core/lv_indev_scroll.c | 48 +-
lib/libesp32_lvgl/lvgl/src/core/lv_obj.c | 95 +-
lib/libesp32_lvgl/lvgl/src/core/lv_obj.h | 40 +-
.../lvgl/src/core/lv_obj_class.c | 2 +-
lib/libesp32_lvgl/lvgl/src/core/lv_obj_draw.c | 23 +-
lib/libesp32_lvgl/lvgl/src/core/lv_obj_draw.h | 6 +-
lib/libesp32_lvgl/lvgl/src/core/lv_obj_pos.c | 105 +-
lib/libesp32_lvgl/lvgl/src/core/lv_obj_pos.h | 42 +-
.../lvgl/src/core/lv_obj_scroll.c | 192 +-
.../lvgl/src/core/lv_obj_scroll.h | 18 +-
.../lvgl/src/core/lv_obj_style.c | 16 +-
.../lvgl/src/core/lv_obj_style.h | 21 +-
.../lvgl/src/core/lv_obj_style_gen.c | 386 ++--
.../lvgl/src/core/lv_obj_style_gen.h | 339 +--
lib/libesp32_lvgl/lvgl/src/core/lv_obj_tree.c | 6 +
lib/libesp32_lvgl/lvgl/src/core/lv_obj_tree.h | 4 +-
lib/libesp32_lvgl/lvgl/src/core/lv_refr.c | 571 ++---
lib/libesp32_lvgl/lvgl/src/core/lv_refr.h | 14 +-
lib/libesp32_lvgl/lvgl/src/core/lv_theme.h | 7 +-
.../src/{gpu/lv_gpu_sdl.c => draw/lv_draw.c} | 34 +-
lib/libesp32_lvgl/lvgl/src/draw/lv_draw.h | 63 +-
lib/libesp32_lvgl/lvgl/src/draw/lv_draw.mk | 4 +-
lib/libesp32_lvgl/lvgl/src/draw/lv_draw_arc.c | 431 +---
lib/libesp32_lvgl/lvgl/src/draw/lv_draw_arc.h | 17 +-
.../lvgl/src/draw/lv_draw_blend.c | 1063 ---------
.../lvgl/src/draw/lv_draw_blend.h | 50 -
lib/libesp32_lvgl/lvgl/src/draw/lv_draw_img.c | 401 +---
lib/libesp32_lvgl/lvgl/src/draw/lv_draw_img.h | 11 +-
.../lvgl/src/draw/lv_draw_label.c | 539 +----
.../lvgl/src/draw/lv_draw_label.h | 22 +-
.../lvgl/src/draw/lv_draw_line.c | 445 +---
.../lvgl/src/draw/lv_draw_line.h | 17 +-
.../lvgl/src/draw/lv_draw_mask.c | 135 +-
.../lvgl/src/draw/lv_draw_mask.h | 20 +-
.../lvgl/src/draw/lv_draw_rect.c | 1284 +----------
.../lvgl/src/draw/lv_draw_rect.h | 36 +-
.../lvgl/src/draw/lv_draw_triangle.c | 176 +-
.../lvgl/src/draw/lv_draw_triangle.h | 20 +-
lib/libesp32_lvgl/lvgl/src/draw/lv_img_buf.c | 4 +-
.../{gpu => draw/nxp_pxp}/lv_gpu_nxp_pxp.c | 4 +-
.../{gpu => draw/nxp_pxp}/lv_gpu_nxp_pxp.h | 6 +
.../nxp_pxp}/lv_gpu_nxp_pxp_osa.c | 4 +-
.../nxp_pxp}/lv_gpu_nxp_pxp_osa.h | 2 +-
.../nxp_vglite}/lv_gpu_nxp_vglite.c | 3 +-
.../nxp_vglite}/lv_gpu_nxp_vglite.h | 6 +-
.../lvgl/src/{gpu => draw}/sdl/README.md | 4 +-
.../lvgl/src/draw/sdl/lv_draw_sdl.c | 98 +
.../lvgl/src/draw/sdl/lv_draw_sdl.h | 96 +
.../lvgl/src/draw/sdl/lv_draw_sdl.mk | 18 +
.../lvgl/src/draw/sdl/lv_draw_sdl_arc.c | 238 ++
.../lvgl/src/draw/sdl/lv_draw_sdl_bg.c | 106 +
.../lvgl/src/draw/sdl/lv_draw_sdl_composite.c | 256 +++
.../lvgl/src/draw/sdl/lv_draw_sdl_composite.h | 72 +
.../lvgl/src/draw/sdl/lv_draw_sdl_img.c | 459 ++++
.../lvgl/src/draw/sdl/lv_draw_sdl_img.h | 72 +
.../lvgl/src/draw/sdl/lv_draw_sdl_label.c | 158 ++
.../lvgl/src/draw/sdl/lv_draw_sdl_line.c | 154 ++
.../sdl/lv_draw_sdl_mask.c} | 54 +-
.../lvgl/src/draw/sdl/lv_draw_sdl_mask.h | 51 +
.../lvgl/src/draw/sdl/lv_draw_sdl_polygon.c | 133 ++
.../sdl/lv_draw_sdl_priv.h} | 31 +-
.../lvgl/src/draw/sdl/lv_draw_sdl_rect.c | 708 ++++++
.../lvgl/src/draw/sdl/lv_draw_sdl_rect.h | 75 +
.../sdl/lv_draw_sdl_stack_blur.c} | 6 +-
.../sdl/lv_draw_sdl_stack_blur.h} | 12 +-
.../sdl/lv_draw_sdl_texture_cache.c} | 121 +-
.../src/draw/sdl/lv_draw_sdl_texture_cache.h | 102 +
.../sdl/lv_draw_sdl_utils.c} | 98 +-
.../sdl/lv_draw_sdl_utils.h} | 22 +-
.../src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.c | 256 +++
.../src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.h | 66 +
.../lvgl/src/draw/sw/lv_draw_sw.c | 74 +
.../lvgl/src/draw/sw/lv_draw_sw.h | 78 +
.../lvgl/src/draw/sw/lv_draw_sw.mk | 15 +
.../lvgl/src/draw/sw/lv_draw_sw_arc.c | 531 +++++
.../lvgl/src/draw/sw/lv_draw_sw_blend.c | 757 ++++++
.../lvgl/src/draw/sw/lv_draw_sw_blend.h | 69 +
.../lvgl/src/draw/sw/lv_draw_sw_dither.c | 213 ++
.../lvgl/src/draw/sw/lv_draw_sw_dither.h | 70 +
.../lvgl/src/draw/sw/lv_draw_sw_gradient.c | 353 +++
.../lvgl/src/draw/sw/lv_draw_sw_gradient.h | 97 +
.../lvgl/src/draw/sw/lv_draw_sw_img.c | 321 +++
.../lvgl/src/draw/sw/lv_draw_sw_letter.c | 536 +++++
.../lvgl/src/draw/sw/lv_draw_sw_line.c | 443 ++++
.../lvgl/src/draw/sw/lv_draw_sw_polygon.c | 207 ++
.../lvgl/src/draw/sw/lv_draw_sw_rect.c | 1419 ++++++++++++
lib/libesp32_lvgl/lvgl/src/extra/README.md | 3 +-
.../lvgl/src/extra/layouts/flex/lv_flex.c | 6 +-
.../lvgl/src/extra/layouts/grid/lv_grid.c | 2 +-
.../src/extra/libs/freetype/lv_freetype.c | 343 ++-
.../src/extra/libs/freetype/lv_freetype.h | 2 +
.../lvgl/src/extra/libs/fsdrv/lv_fs_fatfs.c | 50 +-
.../lvgl/src/extra/libs/fsdrv/lv_fs_posix.c | 67 +-
.../lvgl/src/extra/libs/fsdrv/lv_fs_stdio.c | 64 +-
.../lvgl/src/extra/libs/fsdrv/lv_fs_win32.c | 95 +-
.../lvgl/src/extra/libs/fsdrv/lv_fsdrv.h | 8 +-
.../lvgl/src/extra/libs/lv_libs.h | 6 +-
.../lvgl/src/extra/libs/png/lv_png.c | 104 +-
.../lvgl/src/extra/libs/png/lv_png.h | 2 +-
.../lvgl/src/extra/libs/qrcode/lv_qrcode.c | 215 ++
.../lvgl/src/extra/libs/qrcode/lv_qrcode.h | 69 +
.../lvgl/src/extra/libs/qrcode/qrcodegen.c | 1035 +++++++++
.../lvgl/src/extra/libs/qrcode/qrcodegen.h | 319 +++
lib/libesp32_lvgl/lvgl/src/extra/lv_extra.c | 13 +-
.../src/extra/others/gridnav/lv_gridnav.c | 354 +++
.../src/extra/others/gridnav/lv_gridnav.h | 115 +
.../lvgl/src/extra/others/lv_others.h | 2 +
.../lvgl/src/extra/others/monkey/lv_monkey.c | 187 ++
.../lvgl/src/extra/others/monkey/lv_monkey.h | 118 +
.../src/extra/others/snapshot/lv_snapshot.c | 77 +-
.../src/extra/others/snapshot/lv_snapshot.h | 2 +-
.../src/extra/widgets/animimg/lv_animimg.h | 12 +-
.../src/extra/widgets/calendar/lv_calendar.c | 3 +-
.../src/extra/widgets/calendar/lv_calendar.h | 4 +-
.../calendar/lv_calendar_header_arrow.h | 2 +-
.../calendar/lv_calendar_header_dropdown.h | 2 +-
.../lvgl/src/extra/widgets/chart/lv_chart.c | 184 +-
.../lvgl/src/extra/widgets/chart/lv_chart.h | 4 +-
.../extra/widgets/colorwheel/lv_colorwheel.c | 10 +-
.../extra/widgets/colorwheel/lv_colorwheel.h | 2 +-
.../lvgl/src/extra/widgets/imgbtn/lv_imgbtn.c | 60 +-
.../lvgl/src/extra/widgets/imgbtn/lv_imgbtn.h | 4 +-
.../src/extra/widgets/keyboard/lv_keyboard.c | 11 +-
.../src/extra/widgets/keyboard/lv_keyboard.h | 26 +-
.../lvgl/src/extra/widgets/led/lv_led.c | 22 +-
.../lvgl/src/extra/widgets/led/lv_led.h | 6 +-
.../lvgl/src/extra/widgets/list/lv_list.c | 2 +
.../lvgl/src/extra/widgets/lv_widgets.h | 1 +
.../lvgl/src/extra/widgets/menu/lv_menu.c | 752 ++++++
.../lvgl/src/extra/widgets/menu/lv_menu.h | 233 ++
.../lvgl/src/extra/widgets/meter/lv_meter.c | 38 +-
.../lvgl/src/extra/widgets/meter/lv_meter.h | 2 +-
.../lvgl/src/extra/widgets/msgbox/lv_msgbox.c | 28 +-
.../lvgl/src/extra/widgets/span/lv_span.c | 230 +-
.../lvgl/src/extra/widgets/span/lv_span.h | 11 +-
.../src/extra/widgets/spinbox/lv_spinbox.c | 24 +-
.../src/extra/widgets/spinbox/lv_spinbox.h | 36 +-
.../src/extra/widgets/spinner/lv_spinner.c | 2 +-
.../src/extra/widgets/tileview/lv_tileview.c | 2 +
.../src/extra/widgets/tileview/lv_tileview.h | 6 +-
lib/libesp32_lvgl/lvgl/src/font/lv_font.c | 15 +-
lib/libesp32_lvgl/lvgl/src/font/lv_font.h | 39 +-
.../font/lv_font_dejavu_16_persian_hebrew.c | 11 +-
.../lvgl/src/font/lv_font_fmt_txt.c | 1 +
.../lvgl/src/font/lv_font_montserrat_10.c | 2 +-
.../lvgl/src/font/lv_font_montserrat_12.c | 23 +-
.../src/font/lv_font_montserrat_12_subpx.c | 23 +-
.../lvgl/src/font/lv_font_montserrat_14.c | 23 +-
.../lvgl/src/font/lv_font_montserrat_16.c | 23 +-
.../lvgl/src/font/lv_font_montserrat_18.c | 23 +-
.../lvgl/src/font/lv_font_montserrat_20.c | 23 +-
.../lvgl/src/font/lv_font_montserrat_22.c | 23 +-
.../lvgl/src/font/lv_font_montserrat_24.c | 23 +-
.../lvgl/src/font/lv_font_montserrat_26.c | 23 +-
.../lvgl/src/font/lv_font_montserrat_28.c | 23 +-
.../font/lv_font_montserrat_28_compressed.c | 23 +-
.../lvgl/src/font/lv_font_montserrat_30.c | 23 +-
.../lvgl/src/font/lv_font_montserrat_32.c | 23 +-
.../lvgl/src/font/lv_font_montserrat_34.c | 23 +-
.../lvgl/src/font/lv_font_montserrat_36.c | 23 +-
.../lvgl/src/font/lv_font_montserrat_38.c | 23 +-
.../lvgl/src/font/lv_font_montserrat_40.c | 23 +-
.../lvgl/src/font/lv_font_montserrat_42.c | 23 +-
.../lvgl/src/font/lv_font_montserrat_44.c | 23 +-
.../lvgl/src/font/lv_font_montserrat_46.c | 23 +-
.../lvgl/src/font/lv_font_montserrat_48.c | 23 +-
.../lvgl/src/font/lv_font_montserrat_8.c | 2 +-
.../lvgl/src/font/lv_font_simsun_16_cjk.c | 11 +-
.../lvgl/src/font/lv_font_unscii_16.c | 2 +-
.../lvgl/src/font/lv_font_unscii_8.c | 2 +-
.../lvgl/src/font/lv_symbol_def.h | 335 ++-
lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu.mk | 2 -
.../lvgl/src/gpu/lv_gpu_stm32_dma2d.c | 262 ---
.../lvgl/src/gpu/lv_gpu_stm32_dma2d.h | 109 -
.../lvgl/src/gpu/sdl/lv_gpu_sdl.mk | 16 -
.../lvgl/src/gpu/sdl/lv_gpu_sdl_draw_arc.c | 163 --
.../lvgl/src/gpu/sdl/lv_gpu_sdl_draw_blend.c | 102 -
.../lvgl/src/gpu/sdl/lv_gpu_sdl_draw_img.c | 171 --
.../lvgl/src/gpu/sdl/lv_gpu_sdl_draw_label.c | 332 ---
.../lvgl/src/gpu/sdl/lv_gpu_sdl_draw_line.c | 158 --
.../lvgl/src/gpu/sdl/lv_gpu_sdl_draw_rect.c | 733 ------
.../lvgl/src/gpu/sdl/lv_gpu_sdl_lru.h | 90 -
.../lvgl/src/gpu/sdl/lv_gpu_sdl_mask.h | 57 -
.../src/gpu/sdl/lv_gpu_sdl_texture_cache.h | 90 -
lib/libesp32_lvgl/lvgl/src/hal/lv_hal_disp.c | 50 +-
lib/libesp32_lvgl/lvgl/src/hal/lv_hal_disp.h | 28 +-
lib/libesp32_lvgl/lvgl/src/hal/lv_hal_indev.c | 35 +
lib/libesp32_lvgl/lvgl/src/hal/lv_hal_indev.h | 6 +
lib/libesp32_lvgl/lvgl/src/hal/lv_hal_tick.c | 4 +-
lib/libesp32_lvgl/lvgl/src/misc/lv_anim.h | 2 +-
.../lvgl/src/misc/lv_anim_timeline.c | 2 +-
.../lvgl/src/misc/lv_anim_timeline.h | 2 +-
lib/libesp32_lvgl/lvgl/src/misc/lv_area.c | 5 +
lib/libesp32_lvgl/lvgl/src/misc/lv_area.h | 13 +-
lib/libesp32_lvgl/lvgl/src/misc/lv_bidi.c | 24 +-
lib/libesp32_lvgl/lvgl/src/misc/lv_color.h | 29 +
lib/libesp32_lvgl/lvgl/src/misc/lv_fs.c | 200 +-
lib/libesp32_lvgl/lvgl/src/misc/lv_fs.h | 9 +
lib/libesp32_lvgl/lvgl/src/misc/lv_gc.h | 4 +-
lib/libesp32_lvgl/lvgl/src/misc/lv_log.c | 5 +-
.../sdl/lv_gpu_sdl_lru.c => misc/lv_lru.c} | 180 +-
lib/libesp32_lvgl/lvgl/src/misc/lv_lru.h | 81 +
lib/libesp32_lvgl/lvgl/src/misc/lv_mem.h | 2 +-
lib/libesp32_lvgl/lvgl/src/misc/lv_misc.mk | 1 +
lib/libesp32_lvgl/lvgl/src/misc/lv_printf.c | 2 +-
lib/libesp32_lvgl/lvgl/src/misc/lv_printf.h | 28 +-
lib/libesp32_lvgl/lvgl/src/misc/lv_style.c | 3 +-
lib/libesp32_lvgl/lvgl/src/misc/lv_style.h | 81 +-
.../lvgl/src/misc/lv_style_gen.c | 385 ++--
.../lvgl/src/misc/lv_style_gen.h | 687 ++----
lib/libesp32_lvgl/lvgl/src/misc/lv_tlsf.c | 2 +-
lib/libesp32_lvgl/lvgl/src/misc/lv_tlsf.h | 2 +-
lib/libesp32_lvgl/lvgl/src/misc/lv_txt.c | 25 +-
lib/libesp32_lvgl/lvgl/src/misc/lv_txt.h | 10 +-
lib/libesp32_lvgl/lvgl/src/misc/lv_types.h | 2 +-
lib/libesp32_lvgl/lvgl/src/misc/lv_utils.c | 4 +-
lib/libesp32_lvgl/lvgl/src/misc/lv_utils.h | 2 +-
lib/libesp32_lvgl/lvgl/src/widgets/lv_arc.c | 109 +-
lib/libesp32_lvgl/lvgl/src/widgets/lv_arc.h | 2 +-
lib/libesp32_lvgl/lvgl/src/widgets/lv_bar.c | 44 +-
lib/libesp32_lvgl/lvgl/src/widgets/lv_bar.h | 2 +-
.../lvgl/src/widgets/lv_btnmatrix.c | 42 +-
.../lvgl/src/widgets/lv_btnmatrix.h | 6 +-
.../lvgl/src/widgets/lv_canvas.c | 285 +--
.../lvgl/src/widgets/lv_checkbox.c | 20 +-
.../lvgl/src/widgets/lv_dropdown.c | 124 +-
.../lvgl/src/widgets/lv_dropdown.h | 16 +-
lib/libesp32_lvgl/lvgl/src/widgets/lv_img.c | 16 +-
lib/libesp32_lvgl/lvgl/src/widgets/lv_img.h | 6 +-
lib/libesp32_lvgl/lvgl/src/widgets/lv_label.c | 43 +-
lib/libesp32_lvgl/lvgl/src/widgets/lv_label.h | 28 +-
lib/libesp32_lvgl/lvgl/src/widgets/lv_line.c | 4 +-
lib/libesp32_lvgl/lvgl/src/widgets/lv_line.h | 4 +-
.../lvgl/src/widgets/lv_objx_templ.h | 2 +-
.../lvgl/src/widgets/lv_roller.c | 59 +-
.../lvgl/src/widgets/lv_roller.h | 2 +-
.../lvgl/src/widgets/lv_slider.c | 22 +-
.../lvgl/src/widgets/lv_slider.h | 2 +-
.../lvgl/src/widgets/lv_switch.c | 31 +-
.../lvgl/src/widgets/lv_switch.h | 7 +-
lib/libesp32_lvgl/lvgl/src/widgets/lv_table.c | 24 +-
.../lvgl/src/widgets/lv_textarea.c | 12 +-
.../lvgl/src/widgets/lv_textarea.h | 4 +-
tasmota/berry/lvgl_examples/lv.be | 116 +
.../berry/lvgl_examples/lv_tasmota_info.be | 66 +
tasmota/berry/lvgl_examples/lv_tasmota_log.be | 64 +
.../lvgl_examples/lv_tasmota_log_roboto.be | 68 +
tasmota/berry/lvgl_examples/lv_wifi_graph.be | 70 +
tasmota/lvgl_berry/tasmota_lv_conf.h | 534 +++--
tasmota/xdrv_52_3_berry_lvgl.ino | 19 +
tasmota/xdrv_52_3_berry_tasmota.ino | 46 +-
287 files changed, 19767 insertions(+), 12214 deletions(-)
create mode 100644 lib/libesp32/berry/generate/be_fixed_be_class_tasmota_log_reader.h
create mode 100644 lib/libesp32/berry_tasmota/src/be_tasmota_log_reader_class.cpp
rename lib/libesp32_lvgl/lvgl/src/{gpu/lv_gpu_sdl.c => draw/lv_draw.c} (58%)
delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/lv_draw_blend.c
delete mode 100644 lib/libesp32_lvgl/lvgl/src/draw/lv_draw_blend.h
rename lib/libesp32_lvgl/lvgl/src/{gpu => draw/nxp_pxp}/lv_gpu_nxp_pxp.c (99%)
rename lib/libesp32_lvgl/lvgl/src/{gpu => draw/nxp_pxp}/lv_gpu_nxp_pxp.h (98%)
rename lib/libesp32_lvgl/lvgl/src/{gpu => draw/nxp_pxp}/lv_gpu_nxp_pxp_osa.c (99%)
rename lib/libesp32_lvgl/lvgl/src/{gpu => draw/nxp_pxp}/lv_gpu_nxp_pxp_osa.h (97%)
rename lib/libesp32_lvgl/lvgl/src/{gpu => draw/nxp_vglite}/lv_gpu_nxp_vglite.c (99%)
rename lib/libesp32_lvgl/lvgl/src/{gpu => draw/nxp_vglite}/lv_gpu_nxp_vglite.h (98%)
rename lib/libesp32_lvgl/lvgl/src/{gpu => draw}/sdl/README.md (93%)
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl.c
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl.h
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl.mk
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_arc.c
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_bg.c
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_composite.c
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_composite.h
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_img.c
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_img.h
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_label.c
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_line.c
rename lib/libesp32_lvgl/lvgl/src/{gpu/sdl/lv_gpu_sdl_mask.c => draw/sdl/lv_draw_sdl_mask.c} (50%)
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_mask.h
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_polygon.c
rename lib/libesp32_lvgl/lvgl/src/{gpu/lv_gpu_sdl.h => draw/sdl/lv_draw_sdl_priv.h} (68%)
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_rect.c
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_rect.h
rename lib/libesp32_lvgl/lvgl/src/{gpu/sdl/lv_gpu_sdl_stack_blur.c => draw/sdl/lv_draw_sdl_stack_blur.c} (98%)
rename lib/libesp32_lvgl/lvgl/src/{gpu/sdl/lv_gpu_sdl_stack_blur.h => draw/sdl/lv_draw_sdl_stack_blur.h} (76%)
rename lib/libesp32_lvgl/lvgl/src/{gpu/sdl/lv_gpu_sdl_texture_cache.c => draw/sdl/lv_draw_sdl_texture_cache.c} (51%)
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sdl/lv_draw_sdl_texture_cache.h
rename lib/libesp32_lvgl/lvgl/src/{gpu/sdl/lv_gpu_sdl_utils.c => draw/sdl/lv_draw_sdl_utils.c} (61%)
rename lib/libesp32_lvgl/lvgl/src/{gpu/sdl/lv_gpu_sdl_utils.h => draw/sdl/lv_draw_sdl_utils.h} (64%)
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.c
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/stm32_dma2d/lv_gpu_stm32_dma2d.h
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw.c
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw.h
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw.mk
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_arc.c
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_blend.c
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_blend.h
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_dither.c
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_dither.h
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_gradient.c
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_gradient.h
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_img.c
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_letter.c
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_line.c
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_polygon.c
create mode 100644 lib/libesp32_lvgl/lvgl/src/draw/sw/lv_draw_sw_rect.c
create mode 100644 lib/libesp32_lvgl/lvgl/src/extra/libs/qrcode/lv_qrcode.c
create mode 100644 lib/libesp32_lvgl/lvgl/src/extra/libs/qrcode/lv_qrcode.h
create mode 100644 lib/libesp32_lvgl/lvgl/src/extra/libs/qrcode/qrcodegen.c
create mode 100644 lib/libesp32_lvgl/lvgl/src/extra/libs/qrcode/qrcodegen.h
create mode 100644 lib/libesp32_lvgl/lvgl/src/extra/others/gridnav/lv_gridnav.c
create mode 100644 lib/libesp32_lvgl/lvgl/src/extra/others/gridnav/lv_gridnav.h
create mode 100755 lib/libesp32_lvgl/lvgl/src/extra/others/monkey/lv_monkey.c
create mode 100755 lib/libesp32_lvgl/lvgl/src/extra/others/monkey/lv_monkey.h
create mode 100644 lib/libesp32_lvgl/lvgl/src/extra/widgets/menu/lv_menu.c
create mode 100644 lib/libesp32_lvgl/lvgl/src/extra/widgets/menu/lv_menu.h
delete mode 100644 lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu_stm32_dma2d.c
delete mode 100644 lib/libesp32_lvgl/lvgl/src/gpu/lv_gpu_stm32_dma2d.h
delete mode 100644 lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl.mk
delete mode 100644 lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_draw_arc.c
delete mode 100644 lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_draw_blend.c
delete mode 100644 lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_draw_img.c
delete mode 100644 lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_draw_label.c
delete mode 100644 lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_draw_line.c
delete mode 100644 lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_draw_rect.c
delete mode 100644 lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_lru.h
delete mode 100644 lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_mask.h
delete mode 100644 lib/libesp32_lvgl/lvgl/src/gpu/sdl/lv_gpu_sdl_texture_cache.h
rename lib/libesp32_lvgl/lvgl/src/{gpu/sdl/lv_gpu_sdl_lru.c => misc/lv_lru.c} (62%)
create mode 100644 lib/libesp32_lvgl/lvgl/src/misc/lv_lru.h
create mode 100644 tasmota/berry/lvgl_examples/lv.be
create mode 100644 tasmota/berry/lvgl_examples/lv_tasmota_info.be
create mode 100644 tasmota/berry/lvgl_examples/lv_tasmota_log.be
create mode 100644 tasmota/berry/lvgl_examples/lv_tasmota_log_roboto.be
create mode 100644 tasmota/berry/lvgl_examples/lv_wifi_graph.be
diff --git a/lib/libesp32/berry/default/be_modtab.c b/lib/libesp32/berry/default/be_modtab.c
index 3a7cfc11c..fd98159ec 100644
--- a/lib/libesp32/berry/default/be_modtab.c
+++ b/lib/libesp32/berry/default/be_modtab.c
@@ -145,6 +145,7 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = {
#ifdef ESP32
extern void be_load_tasmota_ntvlib(bvm *vm);
+extern void be_load_tasmota_log_reader_class(bvm *vm);
extern void be_load_light_state_class(bvm *vm);
extern void be_load_wirelib(bvm *vm);
extern void be_load_onewirelib(bvm *vm);
@@ -193,6 +194,7 @@ BERRY_API void be_load_custom_libs(bvm *vm)
#endif
be_load_Timer_class(vm);
be_load_tasmota_ntvlib(vm);
+ be_load_tasmota_log_reader_class(vm);
be_load_Driver_class(vm);
be_load_md5_lib(vm);
be_load_serial_lib(vm);
diff --git a/lib/libesp32/berry/generate/be_const_strtab.h b/lib/libesp32/berry/generate/be_const_strtab.h
index 42529fa92..3f78caf90 100644
--- a/lib/libesp32/berry/generate/be_const_strtab.h
+++ b/lib/libesp32/berry/generate/be_const_strtab.h
@@ -232,6 +232,7 @@ extern const bcstring be_const_str_allocated;
extern const bcstring be_const_str_alternate;
extern const bcstring be_const_str_animate;
extern const bcstring be_const_str_animators;
+extern const bcstring be_const_str_arc_dsc;
extern const bcstring be_const_str_arch;
extern const bcstring be_const_str_area;
extern const bcstring be_const_str_arg;
@@ -350,6 +351,9 @@ extern const bcstring be_const_str_display;
extern const bcstring be_const_str_display_X2Eini;
extern const bcstring be_const_str_do;
extern const bcstring be_const_str_draw_arc;
+extern const bcstring be_const_str_draw_arc_dsc;
+extern const bcstring be_const_str_draw_arc_dsc_init;
+extern const bcstring be_const_str_draw_ctx;
extern const bcstring be_const_str_draw_line;
extern const bcstring be_const_str_draw_line_dsc;
extern const bcstring be_const_str_draw_line_dsc_init;
@@ -393,6 +397,7 @@ extern const bcstring be_const_str_find_op;
extern const bcstring be_const_str_finish;
extern const bcstring be_const_str_floor;
extern const bcstring be_const_str_flush;
+extern const bcstring be_const_str_font_embedded;
extern const bcstring be_const_str_font_montserrat;
extern const bcstring be_const_str_font_seg7;
extern const bcstring be_const_str_for;
@@ -424,6 +429,7 @@ extern const bcstring be_const_str_get_free_heap;
extern const bcstring be_const_str_get_height;
extern const bcstring be_const_str_get_input_power_status;
extern const bcstring be_const_str_get_light;
+extern const bcstring be_const_str_get_log;
extern const bcstring be_const_str_get_object_from_ptr;
extern const bcstring be_const_str_get_option;
extern const bcstring be_const_str_get_percentage;
@@ -462,6 +468,7 @@ extern const bcstring be_const_str_imax;
extern const bcstring be_const_str_imin;
extern const bcstring be_const_str_import;
extern const bcstring be_const_str_init;
+extern const bcstring be_const_str_init_draw_arc_dsc;
extern const bcstring be_const_str_init_draw_line_dsc;
extern const bcstring be_const_str_input;
extern const bcstring be_const_str_ins_goto;
@@ -638,6 +645,7 @@ extern const bcstring be_const_str_reverse_gamma10;
extern const bcstring be_const_str_rotate;
extern const bcstring be_const_str_round_end;
extern const bcstring be_const_str_round_start;
+extern const bcstring be_const_str_rounded;
extern const bcstring be_const_str_rtc;
extern const bcstring be_const_str_rule;
extern const bcstring be_const_str_run;
@@ -734,6 +742,7 @@ extern const bcstring be_const_str_target_search;
extern const bcstring be_const_str_tasmota;
extern const bcstring be_const_str_tasmota_X2Eget_light_X28_X29_X20is_X20deprecated_X2C_X20use_X20light_X2Eget_X28_X29;
extern const bcstring be_const_str_tasmota_X2Eset_light_X28_X29_X20is_X20deprecated_X2C_X20use_X20light_X2Eset_X28_X29;
+extern const bcstring be_const_str_tasmota_log_reader;
extern const bcstring be_const_str_tcpclient;
extern const bcstring be_const_str_tele;
extern const bcstring be_const_str_the_X20second_X20argument_X20is_X20not_X20a_X20function;
diff --git a/lib/libesp32/berry/generate/be_const_strtab_def.h b/lib/libesp32/berry/generate/be_const_strtab_def.h
index f0712889a..b26de1f17 100644
--- a/lib/libesp32/berry/generate/be_const_strtab_def.h
+++ b/lib/libesp32/berry/generate/be_const_strtab_def.h
@@ -1,742 +1,751 @@
-be_define_const_str(, "", 2166136261u, 0, 0, &be_const_str_ins_goto);
-be_define_const_str(_X0A, "\n", 252472541u, 0, 1, &be_const_str_int);
-be_define_const_str(_X20, " ", 621580159u, 0, 1, &be_const_str__X2Ebec);
-be_define_const_str(_X21_X3D, "!=", 2428715011u, 0, 2, NULL);
-be_define_const_str(_X21_X3D_X3D, "!==", 559817114u, 0, 3, &be_const_str_round_start);
-be_define_const_str(_X23, "#", 638357778u, 0, 1, &be_const_str_display_X2Eini);
-be_define_const_str(_X23autoexec_X2Ebat, "#autoexec.bat", 3382890497u, 0, 13, &be_const_str__X2E);
-be_define_const_str(_X23autoexec_X2Ebe, "#autoexec.be", 1181757091u, 0, 12, &be_const_str_ceil);
-be_define_const_str(_X23display_X2Eini, "#display.ini", 182218220u, 0, 12, &be_const_str_do);
-be_define_const_str(_X23init_X2Ebat, "#init.bat", 3297595077u, 0, 9, &be_const_str_AES_GCM);
-be_define_const_str(_X23preinit_X2Ebe, "#preinit.be", 687035716u, 0, 11, &be_const_str_arg_X20must_X20be_X20a_X20subclass_X20of_X20lv_obj);
-be_define_const_str(_X2502d_X25s_X2502d, "%02d%s%02d", 1587999717u, 0, 10, &be_const_str_geti);
-be_define_const_str(_X2504d_X2D_X2502d_X2D_X2502dT_X2502d_X3A_X2502d_X3A_X2502d, "%04d-%02d-%02dT%02d:%02d:%02d", 3425528601u, 0, 29, &be_const_str__ptr);
-be_define_const_str(_X2508x_X2D_X2504x_X2D_X2504x_X2D_X2504x_X2D_X2504x_X2508x, "%08x-%04x-%04x-%04x-%04x%08x", 1670063141u, 0, 28, &be_const_str_day);
-be_define_const_str(_X25s_X2Eautoconf, "%s.autoconf", 3560383524u, 0, 11, NULL);
-be_define_const_str(_X26lt_X3BError_X3A_X20apply_X20new_X20or_X20remove_X26gt_X3B, "<Error: apply new or remove>", 2855507949u, 0, 34, &be_const_str__X2F);
-be_define_const_str(_X26lt_X3BNone_X26gt_X3B, "<None>", 2602165498u, 0, 12, &be_const_str__X3C_X3D);
-be_define_const_str(_X28_X29, "()", 685372826u, 0, 2, &be_const_str_super);
-be_define_const_str(_X2B, "+", 772578730u, 0, 1, &be_const_str_get_bri);
-be_define_const_str(_X2C, ",", 688690635u, 0, 1, &be_const_str_create_custom_widget);
-be_define_const_str(_X2C_X22AXP192_X22_X3A_X7B_X22VBusVoltage_X22_X3A_X25_X2E3f_X2C_X22VBusCurrent_X22_X3A_X25_X2E1f_X2C_X22BattVoltage_X22_X3A_X25_X2E3f_X2C_X22BattCurrent_X22_X3A_X25_X2E1f_X2C_X22Temperature_X22_X3A_X25_X2E1f_X7D, ",\"AXP192\":{\"VBusVoltage\":%.3f,\"VBusCurrent\":%.1f,\"BattVoltage\":%.3f,\"BattCurrent\":%.1f,\"Temperature\":%.1f}", 2598755376u, 0, 106, &be_const_str_get_warning_level);
+be_define_const_str(, "", 2166136261u, 0, 0, &be_const_str_rtc);
+be_define_const_str(_X0A, "\n", 252472541u, 0, 1, &be_const_str__X3Cp_X3ECurrent_X20configuration_X3A_X20_X3C_X2Fp_X3E_X3Cp_X3E_X3Cb_X3E_X25s_X3C_X2Fb_X3E_X3C_X2Fp_X3E);
+be_define_const_str(_X20, " ", 621580159u, 0, 1, &be_const_str__X2Ep);
+be_define_const_str(_X21_X3D, "!=", 2428715011u, 0, 2, &be_const_str_CT);
+be_define_const_str(_X21_X3D_X3D, "!==", 559817114u, 0, 3, &be_const_str_publish);
+be_define_const_str(_X23, "#", 638357778u, 0, 1, &be_const_str_asstring);
+be_define_const_str(_X23autoexec_X2Ebat, "#autoexec.bat", 3382890497u, 0, 13, &be_const_str_lvgl_event_dispatch);
+be_define_const_str(_X23autoexec_X2Ebe, "#autoexec.be", 1181757091u, 0, 12, &be_const_str__X5B);
+be_define_const_str(_X23display_X2Eini, "#display.ini", 182218220u, 0, 12, &be_const_str_begin_multicast);
+be_define_const_str(_X23init_X2Ebat, "#init.bat", 3297595077u, 0, 9, &be_const_str_CFG_X3A_X20_X27init_X2Ebat_X27_X20done_X2C_X20restarting);
+be_define_const_str(_X23preinit_X2Ebe, "#preinit.be", 687035716u, 0, 11, &be_const_str__error);
+be_define_const_str(_X2502d_X25s_X2502d, "%02d%s%02d", 1587999717u, 0, 10, &be_const_str__X3D_X3C_X3E_X21);
+be_define_const_str(_X2504d_X2D_X2502d_X2D_X2502dT_X2502d_X3A_X2502d_X3A_X2502d, "%04d-%02d-%02dT%02d:%02d:%02d", 3425528601u, 0, 29, &be_const_str_BUTTON_CONFIGURATION);
+be_define_const_str(_X2508x_X2D_X2504x_X2D_X2504x_X2D_X2504x_X2D_X2504x_X2508x, "%08x-%04x-%04x-%04x-%04x%08x", 1670063141u, 0, 28, &be_const_str_lv_coord_arr);
+be_define_const_str(_X25s_X2Eautoconf, "%s.autoconf", 3560383524u, 0, 11, &be_const_str_RES_OK);
+be_define_const_str(_X26lt_X3BError_X3A_X20apply_X20new_X20or_X20remove_X26gt_X3B, "<Error: apply new or remove>", 2855507949u, 0, 34, &be_const_str_gamma);
+be_define_const_str(_X26lt_X3BNone_X26gt_X3B, "<None>", 2602165498u, 0, 12, &be_const_str__X2Fac);
+be_define_const_str(_X28_X29, "()", 685372826u, 0, 2, &be_const_str_read24);
+be_define_const_str(_X2B, "+", 772578730u, 0, 1, &be_const_str_make_cb);
+be_define_const_str(_X2C, ",", 688690635u, 0, 1, &be_const_str_https_X3A_X2F_X2Fraw_X2Egithubusercontent_X2Ecom_X2Ftasmota_X2Fautoconf_X2Fmain_X2F_X25s_manifest_X2Ejson);
+be_define_const_str(_X2C_X22AXP192_X22_X3A_X7B_X22VBusVoltage_X22_X3A_X25_X2E3f_X2C_X22VBusCurrent_X22_X3A_X25_X2E1f_X2C_X22BattVoltage_X22_X3A_X25_X2E3f_X2C_X22BattCurrent_X22_X3A_X25_X2E1f_X2C_X22Temperature_X22_X3A_X25_X2E1f_X7D, ",\"AXP192\":{\"VBusVoltage\":%.3f,\"VBusCurrent\":%.1f,\"BattVoltage\":%.3f,\"BattCurrent\":%.1f,\"Temperature\":%.1f}", 2598755376u, 0, 106, &be_const_str_bus);
be_define_const_str(_X2D_X2D_X3A_X2D_X2D, "--:--", 1370615441u, 0, 5, NULL);
-be_define_const_str(_X2E, ".", 722245873u, 0, 1, &be_const_str_bool);
-be_define_const_str(_X2E_X2E, "..", 2748622605u, 0, 2, &be_const_str_lv_solidified);
-be_define_const_str(_X2Eautoconf, ".autoconf", 2524679088u, 0, 9, &be_const_str_BRY_X3A_X20could_X20not_X20save_X20compiled_X20file_X20_X25s_X20_X28_X25s_X29);
-be_define_const_str(_X2Ebe, ".be", 1325797348u, 0, 3, &be_const_str_LVG_X3A_X20call_X20to_X20unsupported_X20callback);
-be_define_const_str(_X2Ebec, ".bec", 3985273221u, 0, 4, &be_const_str__X3Clambda_X3E);
-be_define_const_str(_X2Elen, ".len", 850842136u, 0, 4, &be_const_str_lv_signal_bars);
-be_define_const_str(_X2Ep, ".p", 1171526419u, 0, 2, &be_const_str_pow);
-be_define_const_str(_X2Ep1, ".p1", 249175686u, 0, 3, NULL);
-be_define_const_str(_X2Ep2, ".p2", 232398067u, 0, 3, &be_const_str_introspect);
-be_define_const_str(_X2Esize, ".size", 1965188224u, 0, 5, &be_const_str_read32);
-be_define_const_str(_X2Etapp, ".tapp", 1363391594u, 0, 5, &be_const_str_set_height);
-be_define_const_str(_X2Ew, ".w", 1255414514u, 0, 2, &be_const_str__X3Cp_X3E_X3Cform_X20id_X3Dreapply_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20action_X3D_X27_X2Fac_X27_X20method_X3D_X27post_X27_X20);
-be_define_const_str(_X2F, "/", 705468254u, 0, 1, &be_const_str__X3Cp_X20style_X3D_X27width_X3A340px_X3B_X27_X3E_X3Cb_X3EException_X3A_X3C_X2Fb_X3E_X3Cbr_X3E_X27_X25s_X27_X3Cbr_X3E_X25s_X3C_X2Fp_X3E);
-be_define_const_str(_X2F_X2Eautoconf, "/.autoconf", 2212074393u, 0, 10, &be_const_str_codedump);
-be_define_const_str(_X2F_X3Frst_X3D, "/?rst=", 580074707u, 0, 6, NULL);
-be_define_const_str(_X2Fac, "/ac", 3904651978u, 0, 3, &be_const_str_compile);
-be_define_const_str(_X3A, ":", 1057798253u, 0, 1, &be_const_str_strptime);
-be_define_const_str(_X3C, "<", 957132539u, 0, 1, &be_const_str__anonymous_);
-be_define_const_str(_X3C_X2Fform_X3E_X3C_X2Fp_X3E, "
", 3546571739u, 0, 11, NULL);
-be_define_const_str(_X3C_X2Fselect_X3E_X3Cp_X3E_X3C_X2Fp_X3E, "", 1863865923u, 0, 16, &be_const_str_AudioOutput);
-be_define_const_str(_X3C_X3D, "<=", 2499223986u, 0, 2, &be_const_str__X3Cp_X3E_X3Cform_X20id_X3Dac_X20action_X3D_X27ac_X27_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20method_X3D_X27get_X27_X3E_X3Cbutton_X3EAuto_X2Dconfiguration_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E);
-be_define_const_str(_X3Cbutton_X20name_X3D_X27reapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3ERe_X2Dapply_X20current_X20configuration_X3C_X2Fbutton_X3E, "", 3147934216u, 0, 82, &be_const_str_b);
-be_define_const_str(_X3Cbutton_X20name_X3D_X27zipapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3EApply_X20configuration_X3C_X2Fbutton_X3E, "", 1205771629u, 0, 72, &be_const_str_gpio);
-be_define_const_str(_X3Cfieldset_X3E_X3Cstyle_X3E_X2Ebdis_X7Bbackground_X3A_X23888_X3B_X7D_X2Ebdis_X3Ahover_X7Bbackground_X3A_X23888_X3B_X7D_X3C_X2Fstyle_X3E, "", 2052843416u, 0, 25, NULL);
-be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dac_X20action_X3D_X27ac_X27_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20method_X3D_X27get_X27_X3E_X3Cbutton_X3EAuto_X2Dconfiguration_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E, "", 2058443583u, 0, 110, &be_const_str_HTTP_GET);
-be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dreapply_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20action_X3D_X27_X2Fac_X27_X20method_X3D_X27post_X27_X20, "", 3546571739u, 0, 11, &be_const_str_set_style_bg_color);
+be_define_const_str(_X3C_X2Fselect_X3E_X3Cp_X3E_X3C_X2Fp_X3E, "", 1863865923u, 0, 16, NULL);
+be_define_const_str(_X3C_X3D, "<=", 2499223986u, 0, 2, NULL);
+be_define_const_str(_X3Cbutton_X20name_X3D_X27reapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3ERe_X2Dapply_X20current_X20configuration_X3C_X2Fbutton_X3E, "", 3147934216u, 0, 82, &be_const_str_assert);
+be_define_const_str(_X3Cbutton_X20name_X3D_X27zipapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3EApply_X20configuration_X3C_X2Fbutton_X3E, "", 1205771629u, 0, 72, &be_const_str_set_useragent);
+be_define_const_str(_X3Cfieldset_X3E_X3Cstyle_X3E_X2Ebdis_X7Bbackground_X3A_X23888_X3B_X7D_X2Ebdis_X3Ahover_X7Bbackground_X3A_X23888_X3B_X7D_X3C_X2Fstyle_X3E, "", 2052843416u, 0, 25, &be_const_str_EC_C25519);
+be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dac_X20action_X3D_X27ac_X27_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20method_X3D_X27get_X27_X3E_X3Cbutton_X3EAuto_X2Dconfiguration_X3C_X2Fbutton_X3E_X3C_X2Fform_X3E_X3C_X2Fp_X3E, "", 2058443583u, 0, 110, NULL);
+be_define_const_str(_X3Cp_X3E_X3Cform_X20id_X3Dreapply_X20style_X3D_X27display_X3A_X20block_X3B_X27_X20action_X3D_X27_X2Fac_X27_X20method_X3D_X27post_X27_X20, "