Bitwise Integrative Debounce 运算符混淆

Bitwise Integrative Debounce Operator Confusion

我正在构建一个键盘,一些固件在用 C 编程的无线模块上运行。我正在尝试推出我自己的去抖动算法,需要一些帮助。本质上,代码的布局如下:

#define DEBOUNCE 5 - 这个值可以是从 1(不可取,不是真正的去抖动)到无穷大(同样不可取,原因很明显)之间的任何值。我正在用这个去抖动 32 个按钮,所以接下来我使用以下方法创建一个 32 位整数数组:

static uint32_t key_integration[DEBOUNCE];

在每次扫描输入时(1KHz 轮询率),我将数组的倒数第二项移到最后一项,将倒数第三项移到倒数第二项,依此类推,直到我最终将键的原始扫描输入到第 0 个数组项中。 (附带问题:比从 0 到 DEBOUNCE-2 迭代循环更简单的方法?如果我有一个 (32*DEBOUNCE) 位整数,我将只使用按位移位,但是......无论如何。)

现在是我遇到困难的棘手部分:将数组结果与当前(去抖动)键状态进行比较。本质上,如果 key_integration int 的位 X 是 1 是所有数组,我想将它与当前(去抖动)键状态进行异或以查看它是否已更改。如果 key_integration int 的每一位 X 在所有数组中都是 0,我想做同样的事情。如果位 X 在数组中分散为 1 和 0,则它仍在去抖,不需要进行比较。

我目前对如何将 key_integration 数组与去抖键状态 int 进行比较感到困惑。我非常感谢有关如何 A) 比较它们或 B) 重构代码以更简单的方式实现相同结果的建议。我绝对不能相信我想出的是最好的方法。

您可以相当容易地计算出哪些键始终为零或始终为一的掩码,(伪代码)

alwaysZ = -1
alwaysO = -1
for (int i = 0; i < DEBOUNCE; i++)
    alwaysZ &= ~keys[i]
    alwaysO &= keys[i]

这样就很容易确定哪些键保持不变(但在任一极性):stable = alwaysZ | alwaysO

虽然这需要在每个轮询时刻重新计算,但这是可以避免的。显然位 stable[i] 将被设置当且仅当第 i 个位被设置的次数是 0 或 DEBOUNCE(可能是 DEBOUNCE - 1,这取决于您定义该常量的含义,但关键是它要么是 0 要么是 "everything")。所以这里有一个替代方案:保留一个 counts 数组,它计算每个按钮在整个去抖动过程中被发现处于按下状态的次数 window。每个当前按下的按钮加一,从每个按下的按钮减一 DEBOUNCE 步到过去。

使用计数数组,您可以判断每个按钮在恒定时间内是否稳定,与去抖动量无关。不利的一面是,您必须明确检查每个计数,而使用位掩码,您可以立即确定 any 按钮是否稳定,然后提前退出。

至于附带问题,您可以使用标准 circular buffer 技术来避免移动数据本身,只需通过调整索引来虚拟地移动它。但这也不是免费的,因为 DEBOUNCE=5 我不会那样做。由于开销是恒定的,因此它可以很好地扩展到巨大的去抖动值。您通常可以避免进行实际的模运算,因为您只是递增一个索引(这样您就可以递增并在到达末尾时返回到 0),而不是随机索引到缓冲区的中间。