fix(layer): debounce the bi-directional switch so one flick moves one layer - #19
Merged
Conversation
… layer Flicking the switch sometimes advanced two layers at once. The handler waited for the pin to read inactive exactly once, with no debounce, so it returned mid-bounce on release: loop() comes back around in roughly 1 ms, well inside a mechanical switch's 1-10 ms release chatter, and read the same flick as a second press. The pins are bare INPUT_PULLUP with no hardware debounce, and the switchLayout(int) overload has no guard time (unlike the no-arg switchLayout(), whose trailing delay(300) hid the problem on the FN-key path). Add readSwitchPressed(), which re-samples the press edge to reject glitches, and waitForSwitchRelease(), which blocks until the contact has read inactive continuously for SW_DEBOUNCE_MS. Route all three switch directions through them. Also guard switchLayout(int) against layoutLength == 0, where wrapping stored layoutLength - 1 == -1 as 255 and indexed past the end of keyConfig. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Version 0.0.1 is no longer on the PlatformIO registry (only 0.0.2-0.0.4
remain), and `^0.0.1` resolves to `>=0.0.1 <0.0.2`, so a clean checkout fails
with:
UnknownPackageError: Could not find the package with
'jnthas/Improv WiFi Library @ ^0.0.1' requirements
Local builds kept working only because .pio/libdeps still held a cached 0.0.1
from 2023, so this went unnoticed until CI ran on a fresh runner.
Pin an exact version rather than a caret range: the range is what let the
dependency vanish silently, and NimBLE-Arduino is already pinned this way.
0.0.4 is API-compatible with what the firmware uses (ImprovWiFi,
setDeviceInfo, onImprovError, onImprovConnected, handleSerial); the header
changes are additive only. Flash grows by 292 bytes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Flicking the bi-directional switch to change layer sometimes advanced two layers at once.
The handler waited for the pin to read inactive exactly once, with no debounce, so it returned mid-bounce on release:
loop()comes back around in roughly 1 ms — well inside a mechanical switch's 1–10 ms release chatter — so the still-bouncing contact was read as a brand-new flick. The pins are bareINPUT_PULLUPwith no hardware debounce.It only showed up on the switch because
switchLayout(int)has no guard time, unlike the no-argswitchLayout(), whose trailingdelay(300)masked the problem on the FN-key path.Fix
readSwitchPressed()— re-samples the press edge after a short settling delay, rejecting contact chatter and electrical glitches.waitForSwitchRelease()— blocks until the contact has read inactive continuously forSW_DEBOUNCE_MS(25 ms), restarting the quiet period on any activity.Cost is nil while the switch is idle:
readSwitchPressed()returns on its firstdigitalRead, so the settling delay only runs on an actual press.Also guards
switchLayout(int)againstlayoutLength == 0, where wrapping storedlayoutLength - 1 == -1as255and indexed past the end ofkeyConfig.Testing
pio runbuilds clean; no new warnings fromsrc/.