From bf724ce6926b90974d61ea60bd2ce085460c6e81 Mon Sep 17 00:00:00 2001 From: Jakub <106778416+MarekZegare4@users.noreply.github.com> Date: Sun, 24 May 2026 19:59:21 +0200 Subject: [PATCH] perf(bot): lower body once and strstr instead of O(n*m) per-offset tolower For a 140-byte channel msg with a 64-byte trigger, the old loop did ~8960 tolower() calls per inbound message; now it's 140 tolower calls plus one strstr. perf(buzzer): skip nRF52 STOPPED wait when PWM was not running TASKS_STOP on a disabled PWM never fires EVENTS_STOPPED, so the wait always timed out at 2 ms. Gating on _pwm_on removes the wait on the first note of a melody and after pauses, where there's nothing to wait for. Co-Authored-By: Claude Sonnet 4.6 --- examples/companion_radio/MyMeshBot.h | 31 ++++++++++++---------------- src/helpers/ui/buzzer.cpp | 13 +++++++----- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/examples/companion_radio/MyMeshBot.h b/examples/companion_radio/MyMeshBot.h index 2c38cb0e..1058b10c 100644 --- a/examples/companion_radio/MyMeshBot.h +++ b/examples/companion_radio/MyMeshBot.h @@ -8,15 +8,13 @@ void MyMesh::tryBotReplyDM(const ContactInfo& from, const char* text) { millis() - _bot_last_dm_reply_ms > 10000UL)) return; - const char* tr = _prefs.bot_trigger; // already lowercase (normalised at save/load time) - int tlen = strlen(tr); - bool matched = false; - for (const char* t = text; *t && !matched; t++) { - int i = 0; - while (i < tlen && tolower((uint8_t)t[i]) == (uint8_t)tr[i]) i++; - if (i == tlen) matched = true; - } - if (!matched) return; + // Lower-case the body once, then a single strstr — avoids O(n*m) tolower per offset. + char low[200]; + size_t n = strlen(text); + if (n >= sizeof(low)) n = sizeof(low) - 1; + for (size_t i = 0; i < n; i++) low[i] = (char)tolower((uint8_t)text[i]); + low[n] = '\0'; + if (!strstr(low, _prefs.bot_trigger)) return; uint32_t ts = getRTCClock()->getCurrentTime(); char expanded[200]; @@ -45,15 +43,12 @@ void MyMesh::tryBotReplyChannel(uint8_t channel_idx, const char* text) { const char* sep = strstr(text, ": "); if (sep) msg = sep + 2; - const char* tr = _prefs.bot_trigger; // already lowercase (normalised at save/load time) - int tlen = strlen(tr); - bool matched = false; - for (const char* t = msg; *t && !matched; t++) { - int i = 0; - while (i < tlen && tolower((uint8_t)t[i]) == (uint8_t)tr[i]) i++; - if (i == tlen) matched = true; - } - if (!matched) return; + char low[200]; + size_t n = strlen(msg); + if (n >= sizeof(low)) n = sizeof(low) - 1; + for (size_t i = 0; i < n; i++) low[i] = (char)tolower((uint8_t)msg[i]); + low[n] = '\0'; + if (!strstr(low, _prefs.bot_trigger)) return; ChannelDetails ch; if (!getChannel(channel_idx, ch)) return; diff --git a/src/helpers/ui/buzzer.cpp b/src/helpers/ui/buzzer.cpp index 12cb515a..88d9d163 100644 --- a/src/helpers/ui/buzzer.cpp +++ b/src/helpers/ui/buzzer.cpp @@ -104,11 +104,14 @@ void genericBuzzer::_nrfStartPwm(uint16_t freq) { _duty_buf = 0x8000U | cmp; __DMB(); - NRF_PWM2->TASKS_STOP = 1; - // Wait for STOPPED (short busy-wait, typically < 1 PWM period) - uint32_t t = millis(); - while (!(NRF_PWM2->EVENTS_STOPPED) && (millis() - t) < 2) {} - NRF_PWM2->EVENTS_STOPPED = 0; + // Only wait for STOPPED if PWM was actually running — TASKS_STOP on a disabled + // PWM never fires EVENTS_STOPPED, so the wait would always time out at 2 ms. + if (_pwm_on) { + NRF_PWM2->TASKS_STOP = 1; + uint32_t t = millis(); + while (!(NRF_PWM2->EVENTS_STOPPED) && (millis() - t) < 2) {} + NRF_PWM2->EVENTS_STOPPED = 0; + } NRF_PWM2->PSEL.OUT[0] = nrf_pin; NRF_PWM2->PSEL.OUT[1] = 0xFFFFFFFFUL;