mirror of
https://github.com/esphome/esphome.git
synced 2026-09-11 15:27:33 +00:00
Copy rc_switch table entries out of flash with progmem_memcpy
Codegen now calls rc_switch_protocol(index) instead of copying RC_SWITCH_PROTOCOLS[index] by value, so the ESP8266 copy path never byte loads from the PROGMEM table. Document the keyed slot_counter in AGENTS.md.
This commit is contained in:
@@ -629,6 +629,9 @@ file does, and it is the authority when they disagree. The most useful starting
|
||||
_request_listener_slot()
|
||||
cg.add(hub.register_listener(var))
|
||||
```
|
||||
When several instances each own a list declared at the same size (one per hub of a
|
||||
`MULTI_CONF` component), pass the owning object as the key, `_request_listener_slot(str(hub))`;
|
||||
the define is then the largest count any one key requested instead of the total.
|
||||
```cpp
|
||||
#ifdef MY_COMPONENT_LISTENER_COUNT
|
||||
void register_listener(MyComponentListener *listener);
|
||||
|
||||
@@ -1535,7 +1535,7 @@ def validate_rc_switch_raw_code(value):
|
||||
|
||||
def build_rc_switch_protocol(config):
|
||||
if isinstance(config, int):
|
||||
return rc_switch_protocols[config]
|
||||
return rc_switch_protocol(config)
|
||||
pl = config[CONF_PULSE_LENGTH]
|
||||
return RCSwitchBase(
|
||||
config[CONF_SYNC][0] * pl,
|
||||
@@ -1622,7 +1622,7 @@ RC_SWITCH_TRANSMITTER = cv.Schema(
|
||||
}
|
||||
)
|
||||
|
||||
rc_switch_protocols = ns.RC_SWITCH_PROTOCOLS
|
||||
rc_switch_protocol = ns.rc_switch_protocol
|
||||
RCSwitchData = ns.struct("RCSwitchData")
|
||||
RCSwitchBase = ns.class_("RCSwitchBase")
|
||||
RCSwitchTrigger = ns.class_("RCSwitchTrigger", RemoteReceiverTrigger)
|
||||
|
||||
@@ -1,12 +1,19 @@
|
||||
#include "rc_switch_protocol.h"
|
||||
|
||||
#include <iterator>
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome::remote_base {
|
||||
|
||||
static const char *const TAG = "remote.rc_switch";
|
||||
|
||||
RCSwitchBase rc_switch_protocol(uint8_t index) {
|
||||
RCSwitchBase protocol;
|
||||
progmem_memcpy(&protocol, &RC_SWITCH_PROTOCOLS[index], sizeof(protocol));
|
||||
return protocol;
|
||||
}
|
||||
|
||||
void RCSwitchBase::one(RemoteTransmitData *dst) const {
|
||||
if (!this->inverted_) {
|
||||
dst->mark(this->one_high_);
|
||||
|
||||
@@ -68,8 +68,9 @@ class RCSwitchBase {
|
||||
uint32_t inverted_{}; // bool widened so every field is a word: the table is read from flash
|
||||
};
|
||||
|
||||
// Constant-initialized and kept in flash on every platform; ESP8266 reads it in place, which only
|
||||
// works while every field is a whole word
|
||||
// Constant-initialized and kept in flash on every platform. The decoder reads entries in place
|
||||
// through a pointer, which ESP8266 only allows while every field is a whole word; copies out of
|
||||
// the table go through rc_switch_protocol()
|
||||
static_assert(sizeof(RCSwitchBase) == 7 * sizeof(uint32_t), "RCSwitchBase must stay word-only for flash reads");
|
||||
inline constexpr RCSwitchBase RC_SWITCH_PROTOCOLS[] PROGMEM = {
|
||||
{0, 0, 0, 0, 0, 0, false},
|
||||
@@ -83,6 +84,10 @@ inline constexpr RCSwitchBase RC_SWITCH_PROTOCOLS[] PROGMEM = {
|
||||
{250, 2500, 250, 1250, 250, 250, false},
|
||||
};
|
||||
|
||||
/// RAM copy of RC_SWITCH_PROTOCOLS[index] for the transmit actions and the dumper, made with
|
||||
/// progmem_memcpy so no byte load ever touches the flash table on ESP8266
|
||||
RCSwitchBase rc_switch_protocol(uint8_t index);
|
||||
|
||||
uint64_t decode_binary_string(const std::string &data);
|
||||
|
||||
uint64_t decode_binary_string_mask(const std::string &data);
|
||||
|
||||
Reference in New Issue
Block a user