Commit Graph

22833 Commits

Author SHA1 Message Date
J. Nick Koston
607fcb4254 Merge branch 'base64_decode_dedup' into integration
# Conflicts:
#	esphome/core/helpers.cpp
2026-02-20 00:15:32 -06:00
J. Nick Koston
fbc2d6c066 [core] Also deduplicate base64_encode 3-to-4 byte conversion
Same pattern as the decode side - the bit manipulation was
duplicated in the main loop and tail path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 00:12:10 -06:00
J. Nick Koston
f291773d5c [core] Remove unnecessary input contract comment
base64_find_char() safely handles any input including 0,
returning 0 via strchr fallback - no special contract needed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 00:10:14 -06:00
J. Nick Koston
cdc40101d4 [core] Document base64_decode_quad_ input requirements
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 00:08:58 -06:00
J. Nick Koston
af4d4b35ae [core] Also deduplicate base64 output copy loop
Fold the output copy loop into base64_decode_quad_ since both
call sites use the same truncation-checked copy logic, differing
only in count (3 vs i-1).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 00:08:09 -06:00
J. Nick Koston
4b53f6ef2b [core] Extract base64_decode_quad_ to deduplicate base64 decode logic
The base64 character-to-byte conversion and output copy loop were
duplicated in both the main decode loop and the tail/padding path.
Extract into a shared static helper to reduce flash usage (-64 bytes
on ESP32) and eliminate duplicated logic.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 00:07:20 -06:00
J. Nick Koston
9a028f37ba [core] Extract base64_decode_quad_ to deduplicate base64 decode logic
The base64 character-to-byte conversion was duplicated in both the
main decode loop and the tail/padding path. Extract into a shared
static helper to reduce flash usage (-64 bytes on ESP32).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 00:02:27 -06:00
J. Nick Koston
7a14f30710 Merge branch 'scheduler_relaxed_atomics_under_lock' into integration 2026-02-19 23:44:05 -06:00
J. Nick Koston
7568b64a4a Fix remaining direct atomic reads under lock
Replace two more direct item->remove accesses (implicit seq_cst) with
is_item_removed_locked_() in call() and cleanup_(), both under lock.
2026-02-19 23:31:43 -06:00
J. Nick Koston
25b979bbed [scheduler] Use relaxed memory ordering for atomic reads under lock
When the scheduler lock is already held, atomic loads of the remove
flag don't need acquire ordering — the mutex provides all necessary
synchronization guarantees. Add is_item_removed_locked_() helper that
uses memory_order_relaxed and use it in all _locked_ call sites.

This eliminates redundant memw barriers on Xtensa, saving 12 bytes
in matches_item_locked_ (152 → 140 B) and reducing pipeline stalls
in the scheduler hot path.
2026-02-19 23:10:39 -06:00
J. Nick Koston
d4765bb21d Merge remote-tracking branch 'upstream/dev' into integration 2026-02-19 22:34:05 -06:00
Jonathan Swoboda
efe54e3b5e [ld2410/ld2450] Replace header sync with buffer size increase for frame resync (#14138)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 23:25:25 -05:00
J. Nick Koston
f4e412d1d6 Merge remote-tracking branch 'swoboda1337/fix/ld24xx-buffer-size' into integration 2026-02-19 22:02:34 -06:00
Jonathan Swoboda
dbe3dfb265 [ld2410/ld2450] Replace header sync with buffer size increase for frame resync
Reverts the frame header synchronization added in #14135 and #14136
in favor of a simpler fix: increasing MAX_LINE_LENGTH so that the
existing footer-based resynchronization can recover after losing sync.

Both components already check for frame footers at every byte position,
which naturally resyncs the parser. The problem was that the buffers
were sized exactly to fit the largest frame, so a desynced parser's
footer could land at the overflow boundary and get discarded. Increasing
the buffer by 4 bytes (footer size) ensures the footer always lands
inside the buffer.

- ld2450: 41 -> 45 (zone query response = 40 bytes + 1 null + 4 footer)
- ld2410: 46 -> 50 (engineering data frame = 45 bytes + 1 null + 4 footer)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 22:47:58 -05:00
Jonathan Swoboda
5af871acce [ld2420] Increase MAX_LINE_LENGTH to allow footer-based resync (#14137)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 22:36:12 -05:00
Jonathan Swoboda
a2f0607c1e [ld2410] Add frame header synchronization to readline_() (#14136)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 03:04:38 +00:00
J. Nick Koston
852eca32cf Merge remote-tracking branch 'swoboda1337/fix/ld2410-frame-sync' into integration 2026-02-19 20:59:32 -06:00
Jonathan Swoboda
e9aeb42e2b [ld2410] Add frame header synchronization to readline_()
Add frame header validation to prevent the parser from getting stuck
in an overflow loop when it loses sync with the UART byte stream
(e.g. after module restart or UART noise). This is the same latent
bug fixed in ld2450 (PR #14135) and present in ld2420.

The fix validates the first 4 bytes of each frame match a known
header (DATA or CMD) before accumulating data. On header byte
mismatch, the buffer resets and checks if the mismatched byte starts
a new frame. Also adds a return after buffer overflow reset to
prevent immediately re-accumulating the overflowed byte.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 21:56:46 -05:00
Jonathan Swoboda
b67b2cc3ab [ld2450] Add frame header synchronization to fix initialization regression (#14135)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
2026-02-20 02:56:20 +00:00
J. Nick Koston
b6913a9fb3 Merge branch 'fix/ld2450-frame-sync' into integration 2026-02-19 20:44:15 -06:00
Jonathan Swoboda
7a2a149061 [esp32] Bump ESP-IDF to 5.5.3 (#14122)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 21:43:29 -05:00
Jonathan Swoboda
3dcaa552f7 [ld2450] Add frame header synchronization to fix initialization regression
The batch UART read change in #13818 exposed a latent bug where the
UART parser could start accumulating bytes mid-frame after module
restart, causing an infinite cycle of "Max command length exceeded"
warnings that prevented initialization.

Add header validation for the first 4 bytes of each frame, ensuring
the parser only accumulates data starting from a valid DATA_FRAME_HEADER
(AA FF 03 00) or CMD_FRAME_HEADER (FD FC FB FA). Non-matching bytes are
discarded until a valid frame start is found.

Fixes #14131

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 21:37:09 -05:00
J. Nick Koston
afbc45bf32 [e131] Drain all queued packets per loop iteration (#14133) 2026-02-19 20:35:42 -06:00
J. Nick Koston
d51b0e51b1 Merge remote-tracking branch 'origin/api_varint_split_32_64' into integration 2026-02-19 20:25:25 -06:00
J. Nick Koston
21b9a4139a Address review feedback: fix unconditional guard bug, add ifndef guard, clarify comment
- Fix get_varint64_ifdef() to return unconditional guard when any 64-bit
  varint field has no ifdef (None in ifdefs set)
- Wrap USE_API_VARINT64 define with #ifndef to avoid redefinition warnings
  when esphome/core/defines.h also defines it (test/IDE builds)
- Clarify proto.h comment about uint32_t shift behavior at byte 4
- Add namespace to generated api_pb2_defines.h for linter compliance
2026-02-19 20:23:17 -06:00
J. Nick Koston
4e3b2abd5f Fix ODR violation: generate api_pb2_defines.h for consistent ProtoVarInt layout
USE_API_VARINT64 was only defined in api_pb2.h, but proto.cpp (where
decode() and parse_wide() live) includes proto.h directly. This caused:

1. parse_wide() not compiled in proto.cpp (guarded by #ifdef)
2. decode() used 32-bit-only parse(), returning {} for varints > 5 bytes
3. ODR violation: ProtoVarInt was 4 bytes in proto.cpp but 8 bytes in
   api_pb2*.cpp translation units

For bluetooth_proxy, 48-bit BLE addresses encode as 7-byte varints.
The failed parse caused decode() to return early, leaving request_type
at its default value of 0 (BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT),
producing spurious "V1 connections removed" errors.

Fix: Generate api_pb2_defines.h with the USE_API_VARINT64 define and
include it from proto.h, ensuring all translation units see a consistent
ProtoVarInt layout.
2026-02-19 20:08:29 -06:00
J. Nick Koston
63fcec755a Merge remote-tracking branch 'swoboda1337/esp-idf-5.5.3' into integration 2026-02-19 19:37:29 -06:00
J. Nick Koston
d233e1e6ae Merge remote-tracking branch 'origin/integration' into integration 2026-02-19 19:13:22 -06:00
J. Nick Koston
55f1ef2969 Merge branch 'e131-drain-socket-buffer' into integration 2026-02-19 19:13:11 -06:00
J. Nick Koston
9c445648c2 [e131] Move read_() to header for inlining 2026-02-19 19:12:47 -06:00
J. Nick Koston
47dd62d27a Merge remote-tracking branch 'origin/e131-drain-socket-buffer' into integration 2026-02-19 19:12:01 -06:00
J. Nick Koston
6fa6213348 Merge remote-tracking branch 'origin/e131-drain-socket-buffer' into integration 2026-02-19 19:07:56 -06:00
J. Nick Koston
b8859b990e [e131] Drain all queued packets per loop iteration
Previously the BSD socket path read only one UDP packet per loop()
call. With multi-universe setups (e.g. 380 RGBW LEDs across 3
universes), this caused the light to re-render the entire strip
for each universe packet separately, resulting in visible tearing
and ~3x unnecessary RMT writes.

Now both socket backends drain all available packets before returning,
so multi-universe frames are applied atomically and the light only
writes once per frame. The duplicated packet processing logic is
consolidated into a shared loop with a platform-specific read_()
helper.

Tested on ESP32-IDF with 380 SK6812 RGBW LEDs (3 universes):
- Light total CPU dropped from 5820ms to 1108ms per 60s (~5x)
- Combined e131+light dropped from 6944ms to 4811ms per 60s
- Visible tearing eliminated
2026-02-19 19:04:59 -06:00
J. Nick Koston
c1265a9490 [core] Use constexpr for hand-written PROGMEM arrays in C++ (#14129)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 18:54:57 -06:00
J. Nick Koston
94712b3961 [esp8266][web_server] Use constexpr for PROGMEM arrays in codegen (#14128)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 18:54:44 -06:00
J. Nick Koston
d29288547e [core] Use constexpr for PROGMEM arrays (#14127)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 18:54:33 -06:00
Jonathan Swoboda
1b4de55efd [pulse_counter] Fix PCNT glitch filter calculation off by 1000x (#14132)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 00:12:37 +00:00
J. Nick Koston
cceb109303 [uart] Always call pin setup for UART0 default pins on ESP-IDF (#14130) 2026-02-19 23:48:18 +00:00
Jonathan Swoboda
d9920591b9 [esp32] Bump ESP-IDF to 5.5.3
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 18:35:41 -05:00
J. Nick Koston
57727cba8e Merge remote-tracking branch 'upstream/fix-uart0-pin-setup' into integration 2026-02-19 17:22:18 -06:00
J. Nick Koston
dcff159a33 [uart] Make is_default_uart0_pin constexpr
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 17:20:54 -06:00
J. Nick Koston
d7f8ddb15f [uart] Always call pin setup for UART0 default pins on ESP-IDF
Fix UART0 communication failure on ESP-IDF 5.4.2+ that affected LD2410
and other UART sensors on default UART0 pins across all ESP32 variants.

The gpio_reset_pin() workaround from PR #12519 sets GPIO_MODE_DISABLE
which disables the input buffer. Without a subsequent pin->setup() call,
uart_set_pin() on IOMUX-connected UART0 default pins does not re-enable
the input buffer, so the RX pin cannot receive data.

PR #11914 made pin->setup() conditional on pull/open-drain flags, which
meant most users' UART0 RX pins never got their input buffer re-enabled.

The fix: always call pin->setup() for pins matching U0TXD_GPIO_NUM or
U0RXD_GPIO_NUM to restore proper GPIO direction after gpio_reset_pin().
For non-UART0 pins, the conditional behavior is preserved to avoid
breaking external components (issue #11823).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 17:19:47 -06:00
J. Nick Koston
3def55754c Merge branch 'fix-uart0-pin-setup' into integration 2026-02-19 17:16:36 -06:00
J. Nick Koston
e81eff22c3 [uart] Always call pin setup for UART0 default pins on ESP-IDF
Fix UART0 communication failure on ESP-IDF 5.4.2+ that affected LD2410
and other UART sensors on default UART0 pins across all ESP32 variants.

The gpio_reset_pin() workaround from PR #12519 sets GPIO_MODE_DISABLE
which disables the input buffer. Without a subsequent pin->setup() call,
uart_set_pin() on IOMUX-connected UART0 default pins does not re-enable
the input buffer, so the RX pin cannot receive data.

PR #11914 made pin->setup() conditional on pull/open-drain flags, which
meant most users' UART0 RX pins never got their input buffer re-enabled.

The fix: always call pin->setup() for pins matching U0TXD_GPIO_NUM or
U0RXD_GPIO_NUM to restore proper GPIO direction after gpio_reset_pin().
For non-UART0 pins, the conditional behavior is preserved to avoid
breaking external components (issue #11823).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 17:13:32 -06:00
J. Nick Koston
57e20e4192 Merge remote-tracking branch 'upstream/constexpr-progmem-codegen' into integration 2026-02-19 17:04:13 -06:00
J. Nick Koston
051cba20a3 Also use constexpr for size variables
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 17:02:48 -06:00
J. Nick Koston
9523670546 Merge branch 'remove-powf-normalize-accuracy' into integration 2026-02-19 16:50:04 -06:00
J. Nick Koston
9ce63603a6 Fix pow10_int comment accuracy
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 16:48:55 -06:00
J. Nick Koston
5a8fa6a9cd Merge remote-tracking branch 'origin/integration' into integration 2026-02-19 16:40:45 -06:00
J. Nick Koston
0e6d0a0918 Merge branch 'constexpr-progmem' into integration 2026-02-19 16:40:31 -06:00