mirror of
https://github.com/esphome/esphome.git
synced 2026-09-17 18:18:43 +00:00
[remote_receiver] Treat buffer size as bytes on the pulse ring targets (#19101)
This commit is contained in:
@@ -112,20 +112,21 @@ CONFIG_SCHEMA = remote_base.validate_triggers(
|
||||
cv.Required(CONF_PIN): cv.All(pins.internal_gpio_input_pin_schema),
|
||||
cv.Optional(CONF_DUMP, default=[]): remote_base.validate_dumpers,
|
||||
cv.Optional(CONF_TOLERANCE, default="25%"): validate_tolerance,
|
||||
# pulse ring targets hold one 4 byte entry per pulse; 4000b keeps their 1000 pulses
|
||||
cv.SplitDefault(
|
||||
CONF_BUFFER_SIZE,
|
||||
esp32=cv.UNDEFINED,
|
||||
# the pulse ring needs a size; only RMT targets size themselves in setup()
|
||||
**{
|
||||
f"esp32_{variant.removeprefix('ESP32').lower()}": "1000b"
|
||||
f"esp32_{variant.removeprefix('ESP32').lower()}": "4000b"
|
||||
for variant in esp32_rmt.VARIANTS_NO_RMT
|
||||
},
|
||||
esp8266="1000b",
|
||||
bk72xx="1000b",
|
||||
ln882x="1000b",
|
||||
rtl87xx="1000b",
|
||||
rp2="1000b",
|
||||
): cv.All(cv.validate_bytes, cv.int_range(min=64)),
|
||||
esp8266="4000b",
|
||||
bk72xx="4000b",
|
||||
ln882x="4000b",
|
||||
rtl87xx="4000b",
|
||||
rp2="4000b",
|
||||
): cv.All(cv.validate_bytes, cv.int_range(min=64, max=65535)),
|
||||
cv.Optional(CONF_FILTER, default="50us"): cv.All(
|
||||
cv.positive_time_period_microseconds,
|
||||
cv.Range(max=TimePeriod(microseconds=4294967295)),
|
||||
|
||||
@@ -14,7 +14,7 @@ static void IRAM_ATTR HOT write_value(RemoteReceiverComponentStore *arg, uint32_
|
||||
int32_t multiplier = ((int32_t) level << 1) - 1;
|
||||
uint32_t buffer_write = arg->buffer_write;
|
||||
arg->buffer[buffer_write++] = (int32_t) delta * multiplier;
|
||||
if (buffer_write >= arg->buffer_size) {
|
||||
if (buffer_write >= arg->buffer_entries) {
|
||||
buffer_write = 0;
|
||||
}
|
||||
|
||||
@@ -65,8 +65,9 @@ void RemoteReceiverComponent::setup() {
|
||||
this->store_.idle_us = this->idle_us_;
|
||||
this->store_.filter_us = this->filter_us_;
|
||||
this->store_.pin = this->pin_->to_isr();
|
||||
this->store_.buffer = new int32_t[this->buffer_size_];
|
||||
this->store_.buffer_size = this->buffer_size_;
|
||||
// rounded up so a size that is not a multiple of four never holds less than requested
|
||||
this->store_.buffer_entries = (this->buffer_size_ + sizeof(int32_t) - 1) / sizeof(int32_t);
|
||||
this->store_.buffer = new int32_t[this->store_.buffer_entries];
|
||||
this->store_.prev_micros = micros();
|
||||
this->store_.commit_micros = this->store_.prev_micros;
|
||||
this->store_.prev_level = this->pin_->digital_read();
|
||||
@@ -79,11 +80,11 @@ void RemoteReceiverComponent::dump_config() {
|
||||
ESP_LOGCONFIG(
|
||||
TAG,
|
||||
"Remote Receiver:\n"
|
||||
" Buffer Size: %" PRIu32 "\n"
|
||||
" Buffer Size: %" PRIu32 " bytes (%" PRIu32 " pulses)\n"
|
||||
" Tolerance: %" PRIu32 "%s\n"
|
||||
" Filter out pulses shorter than: %" PRIu32 " us\n"
|
||||
" Signal is done after %" PRIu32 " us of no changes",
|
||||
this->buffer_size_, this->tolerance_,
|
||||
this->buffer_size_, this->store_.buffer_entries, this->tolerance_,
|
||||
(this->tolerance_mode_ == remote_base::TOLERANCE_MODE_TIME) ? LOG_STR_LITERAL(" us") : LOG_STR_LITERAL("%"),
|
||||
this->filter_us_, this->idle_us_);
|
||||
LOG_PIN(" Pin: ", this->pin_);
|
||||
@@ -119,7 +120,7 @@ void RemoteReceiverComponent::loop() {
|
||||
while (temp_read != last_index && (uint32_t) std::abs(s.buffer[temp_read]) < this->idle_us_) {
|
||||
reserve_size++;
|
||||
temp_read++;
|
||||
if (temp_read >= s.buffer_size) {
|
||||
if (temp_read >= s.buffer_entries) {
|
||||
temp_read = 0;
|
||||
}
|
||||
}
|
||||
@@ -129,7 +130,7 @@ void RemoteReceiverComponent::loop() {
|
||||
// read the buffer
|
||||
for (uint32_t i = 0; i < reserve_size + 1; i++) {
|
||||
this->temp_.push_back((int32_t) s.buffer[s.buffer_read++]);
|
||||
if (s.buffer_read >= s.buffer_size) {
|
||||
if (s.buffer_read >= s.buffer_entries) {
|
||||
s.buffer_read = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ struct RemoteReceiverComponentStore {
|
||||
uint32_t buffer_read{0};
|
||||
volatile uint32_t commit_micros{0};
|
||||
volatile uint32_t prev_micros{0};
|
||||
uint32_t buffer_size{1000};
|
||||
uint32_t buffer_entries{0};
|
||||
uint32_t filter_us{10};
|
||||
uint32_t idle_us{10000};
|
||||
ISRInternalGPIOPin pin;
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
esphome:
|
||||
name: test
|
||||
|
||||
bk72xx:
|
||||
board: generic-bk7252
|
||||
|
||||
remote_receiver:
|
||||
- id: rcvr
|
||||
pin: P6
|
||||
@@ -0,0 +1,12 @@
|
||||
esphome:
|
||||
name: test
|
||||
|
||||
esp32:
|
||||
board: esp32-c61-devkitc1
|
||||
variant: esp32c61
|
||||
framework:
|
||||
type: esp-idf
|
||||
|
||||
remote_receiver:
|
||||
- id: rcvr
|
||||
pin: GPIO4
|
||||
@@ -0,0 +1,9 @@
|
||||
esphome:
|
||||
name: test
|
||||
|
||||
ln882x:
|
||||
board: generic-ln882h
|
||||
|
||||
remote_receiver:
|
||||
- id: rcvr
|
||||
pin: PA4
|
||||
@@ -0,0 +1,9 @@
|
||||
esphome:
|
||||
name: test
|
||||
|
||||
rp2:
|
||||
board: rpipicow
|
||||
|
||||
remote_receiver:
|
||||
- id: rcvr
|
||||
pin: GPIO4
|
||||
@@ -0,0 +1,9 @@
|
||||
esphome:
|
||||
name: test
|
||||
|
||||
rtl87xx:
|
||||
board: generic-rtl8710bn-2mb-788k
|
||||
|
||||
remote_receiver:
|
||||
- id: rcvr
|
||||
pin: PA12
|
||||
@@ -1,8 +1,16 @@
|
||||
"""buffer_size reaches the receiver when set, and always on the pulse ring targets."""
|
||||
"""buffer_size is bytes on the pulse ring targets and only reaches RMT targets when set."""
|
||||
|
||||
from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from esphome.components import remote_receiver
|
||||
from esphome.components.esp8266 import gpio as esp8266_gpio # noqa: F401 registers the pin schema
|
||||
from esphome.config_validation import Invalid
|
||||
from esphome.const import PlatformFramework
|
||||
from tests.component_tests.types import SetCoreConfigCallable
|
||||
|
||||
|
||||
def test_explicit_buffer_size_is_passed_through(
|
||||
generate_main: Callable[[str | Path], str],
|
||||
@@ -12,17 +20,29 @@ def test_explicit_buffer_size_is_passed_through(
|
||||
assert "rcvr->set_buffer_size(2000);" in main_cpp
|
||||
|
||||
|
||||
def test_pulse_ring_target_keeps_a_default(
|
||||
@pytest.mark.parametrize(
|
||||
"target", ["esp8266", "rp2", "bk72xx", "rtl87xx", "ln882x", "esp32_c2", "esp32_c61"]
|
||||
)
|
||||
def test_pulse_ring_default_holds_1000_pulses(
|
||||
generate_main: Callable[[str | Path], str],
|
||||
component_config_path: Callable[[str], Path],
|
||||
target: str,
|
||||
) -> None:
|
||||
main_cpp = generate_main(component_config_path("receiver_esp8266.yaml"))
|
||||
assert "rcvr->set_buffer_size(1000);" in main_cpp
|
||||
main_cpp = generate_main(component_config_path(f"receiver_{target}.yaml"))
|
||||
assert "rcvr->set_buffer_size(4000);" in main_cpp
|
||||
|
||||
|
||||
def test_esp32_variant_without_rmt_keeps_a_default(
|
||||
generate_main: Callable[[str | Path], str],
|
||||
component_config_path: Callable[[str], Path],
|
||||
@pytest.mark.parametrize(
|
||||
("value", "expected"),
|
||||
[("32b", None), ("64b", 64), ("65b", 65), ("65535b", 65535), ("65536b", None)],
|
||||
)
|
||||
def test_buffer_size_range(
|
||||
set_core_config: SetCoreConfigCallable, value: str, expected: int | None
|
||||
) -> None:
|
||||
main_cpp = generate_main(component_config_path("receiver_esp32_c2.yaml"))
|
||||
assert "rcvr->set_buffer_size(1000);" in main_cpp
|
||||
set_core_config(PlatformFramework.ESP8266_ARDUINO)
|
||||
config = {"pin": "GPIO4", "buffer_size": value}
|
||||
if expected is None:
|
||||
with pytest.raises(Invalid):
|
||||
remote_receiver.CONFIG_SCHEMA(config)
|
||||
else:
|
||||
assert remote_receiver.CONFIG_SCHEMA(config)["buffer_size"] == expected
|
||||
|
||||
Reference in New Issue
Block a user