Skip to content

Do not let a switched off beeper source block the output - #11907

Open
Raffi1202 wants to merge 1 commit into
iNavFlight:maintenance-10.xfrom
Raffi1202:fix/beeper-masked-source
Open

Raffi1202 wants to merge 1 commit into
iNavFlight:maintenance-10.xfrom
Raffi1202:fix/beeper-masked-source

Conversation

@Raffi1202

@Raffi1202 Raffi1202 commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Problem

With beeper -HW_FAILURE set and the beeper mode assigned to an RC channel, the external beeper responds to the switch only while all hardware is healthy. As soon as the GPS receiver is disconnected the beeper stops; the same happens with beeper -BAT_LOW once the battery is low. The only workaround is beeper all. Reported in #9580 (Speedybee F405 V3, INAV 7.0.0).

Fixes #9580

Cause

beeper() does not consult the off mask when it selects a source; the mask is applied only where the output is driven (src/main/io/beeper.c:359 on maintenance-10.x). A masked source therefore still becomes currentBeeperEntry and wins the priority comparison at src/main/io/beeper.c:238. beeperUpdate() requests BEEPER_RX_SET (priority 10) for the switch and then BEEPER_HARDWARE_FAILURE (priority 1) on every loop while a sensor is unhealthy (src/main/io/beeper.c:318-333). The failure sequence runs silently, ends in beeperSilence(), and is re-selected on the next loop, so the enabled source never reaches the output.

Change

beeper() now returns early when the requested mode is set in the off mask, so a switched-off source never becomes currentBeeperEntry. The existing mask checks at the output stay in place, so a mask changed while a sequence is already running still takes effect. Because a masked source no longer becomes the current entry, it also no longer blinks the warning LED (warningLedEnable() at src/main/io/beeper.c:362 ran regardless of the mask).

Test

Not run on hardware or SITL. Cause verified by reading src/main/io/beeper.c:219-253 and :318-362 on maintenance-10.x against the steps in #9580; pwm_mapping_beeper_unittest.cc covers timer pad mapping only, not beeper(). Compiled for all targets and the four SITL builds on the fork, green: https://github.com/Raffi1202/inav/actions/runs/34770677230

Flash / RAM

Builds clean on all targets. No size comparison yet: the fork build has no baseline for this branch, and the upstream size report runs once CI is released for this PR.

Docs

No documentation change needed: docs/Buzzer.md:70 already states that a minus in front of a name disables that source, which is the behaviour this change restores; nothing documents the previous blocking or the warning LED.

A source that is switched off with the beeper off mask was still selected
as the current beeper entry, the mask was only evaluated when the output
was actually driven. A high priority source that is retriggered on every
update, such as HW_FAILURE while a sensor is unhealthy, therefore replaced
every enabled lower priority source again and again, so nothing could be
heard at all any more - not even the beeper mode on an RC channel.

Reject a switched off source in beeper() so it never becomes the current
entry and the output stays available for the sources that are enabled.

Fixes iNavFlight#9580
@Raffi1202
Raffi1202 marked this pull request as ready for review September 11, 2026 15:51
@qodo-code-review

Copy link
Copy Markdown
Contributor

ⓘ Qodo reviews are paused because the subscription is no longer active. Ask your workspace admin to reactivate the subscription to resume reviews. Manage billing

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Prevent masked beeper sources from blocking enabled alerts

🐞 Bug fix 🕐 Less than 10 minutes

Grey Divider

AI Description

• Rejects masked beeper sources before priority arbitration, preserving enabled alerts.
• Prevents newly masked sources from activating beeper output or the warning LED.
Diagram

graph TD
    A["Beeper Request"] --> B{"Source Masked?"}
    B -- "Yes" --> C["Reject Request"]
    B -- "No" --> D["Priority Arbitration"] --> E["Current Sequence"] --> F{"Still Enabled?"}
    F -- "Yes" --> G["Beeper Output"]
    F -- "No" --> H["Silent Output"]
Loading
High-Level Assessment

The early mask guard is the narrowest and most appropriate fix because it prevents disabled sources from participating in priority arbitration while retaining output-time checks for mask changes during playback. Filtering only at the output would preserve the blocking defect, while embedding the condition in table selection would add unnecessary complexity. A focused beeper arbitration regression test would still be valuable.

Files changed (1) +7 / -0

Bug fix (1) +7 / -0
beeper.cReject masked sources before beeper priority arbitration +7/-0

Reject masked sources before beeper priority arbitration

• Adds an early off-mask check so a disabled mode cannot become 'currentBeeperEntry' and repeatedly preempt enabled, lower-priority alerts. Newly requested masked modes also no longer activate the warning LED, while existing output-time mask checks remain in place for active sequences.

src/main/io/beeper.c

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Grey Divider

Tip of the day
💡 Did you know, you can switch off images and animations for a plain-text comment

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The beeper ouput pin is blocked by deactivated sources, other sources that are not deactivated cannot activate the beeper

2 participants