可能是今年最糟糕的尴尬......评论do you understand how binary operators work?
是正确的。
A >> 2 #shifts the value of A to right by 2 bits
而且所有这些时间,多年来,我认为2在上面的情况下被A的值移动了!!
对于这个愚蠢的问题感谢大家,感谢你纠正我的愚蠢和你的宽容和善意,非常感谢。
我正在尝试了解DIY键盘固件的一部分如何工作。固件称为qmk:https://github.com/qmk/qmk_firmware
我不确定,但代码是一个名为AVR c的c变种。
C macro在保持时更改键盘图层,就像功能键一样,并在快速点击时将隐藏使用ID发送到pc。
图层的初始值是1到32之间的小数 kc是任何一个隐藏使用ID。
#define QK_LAYER_TAP = 0x4000
#define LT(layer, kc) (kc | QK_LAYER_TAP | ((layer & 0xF) << 8))
#define ACTION_LAYER_TAP_KEY(layer, key) ACTION_LAYER_TAP((layer), (key))
#define ACTION_LAYER_TAP(layer, key) (ACT_LAYER_TAP<<12 | (layer)<<8 | (key))
在循环中的另一个文件中,当用户按下可能LT(2,KC_A)
绑定的键时,会触发下面的内容。
case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
action.code = ACTION_LAYER_TAP_KEY((keycode >> 0x8) & 0xF, keycode & 0xFF);
break;
因此,对于LT(2,KC_A)
,此宏#define LT(layer, kc) (kc | QK_LAYER_TAP | ((layer & 0xF) << 8))
会产生04 | 0x4000 | ((2 & 0xf) << 8)
。
KC_A -> 101
0x8 -> 00001000
0xf -> 00001111
0x4000->100000000000000
2&0xf -> 00000010
((2&0xf)<<8) -> 1000000000
固件检测到0x4000位掩码并调用上面的case QK_LAYER_TAP
,然后出现一些源自LT宏的幻数键码。
LT(2,04)
密码为(keycode >> 0x8) & 0xF
产生2,密码为keycode & 0xff
产生4。
keycode包含来自LT宏调用的第一个和第二个参数的int16中的位序列。
由于评估表达式keycode & 0xff
会产生传递给LT的hid使用id,很明显keycode包含前8位中LT的第二个参数。
到目前为止一切都很清楚。但是......
(keycode >> 0x8) & 0xF
产生TL的第一个参数。
00001000
4 >> 0x8
导致零... some negative value >> 0x8
并且可以做到,但我无法理解如何在不触及低8位的情况下操纵(keycode >> 0x8) & 0xF
的值。 答案 0 :(得分:1)
您正在处理驱动硬件的固件。移动一些位并与其他位置进行“或”将创建硬件寄存器的内容,在这种情况下显然是硬件配置寄存器。
需要输入位标志,移位值等,以匹配寄存器的格式,该寄存器包含大量信息,每个信息位于特定位置的一个或多个位。
要明确了解这是做什么的,您需要了解有关hw / sw接口的详细信息,这可能不会即将发布。
现在,针对您的具体问题。你写道:
将上面的内容向右移动4
4 >> 0x8
会导致零...
这是将键码8位向右移位,而不是通过键码位移位8位。 由于前8位是您已解释过的一个值,因此这将提取编码为高位的内容。
例如:
如果你的两个参数是5(要编码到高部分)和4(要编码成低字):
低位字,二进制 00000100
更高的单词,二进制 00000101
合: 0000010100000100
如此按位&amp;用0xFF会给你4 将值向右移8位将为您提供5。
此外,这些很可能是无符号整数。有符号整数通常不用于此类工作。
答案 1 :(得分:1)
正如其他人所说,你应该把它重写为一个简洁的问题。 ..但是,这听起来像你要问的是:“这段代码在做什么”。我会试着解释一下。
你的case语句正在执行这一行:action.code = ACTION_LAYER_TAP_KEY((keycode >> 0x8) & 0xF, keycode & 0xFF);
ACTION_LAYER_TAP_KEY
有2个参数。让我们分别看看它们。
第一个是(keycode >> 0x8) & 0xF
,它的作用是取keycode
并将它向右移8位(失去的位丢失)。然后使用0xF
(00001111
)对结果进行加法(按位)。除了前4位之外,它具有丢弃所有内容的效果。
第二个是keycode & 0xFF
。这样做会丢弃除键码的前8位以外的所有内容。所以现在参数是键码位8-11和键码位0-7。
好的,现在ACTION_LAYER_TAP_KEY
对这些数据做了什么?
#define ACTION_LAYER_TAP_KEY(layer, key) ACTION_LAYER_TAP((layer), (key))
好的,它使用相同的参数调用ACTION_LAYER_TAP
。现在让我们来看看。
ACTION_LAYER_TAP(layer, key) (ACT_LAYER_TAP<<12 | (layer)<<8 | (key))
首先需要ACT_LAYER_TAP
,这可能是一个常数,并将其向左移位12。然后它对layer
执行相同的操作,除了8,然后它需要这两个和key
和/或它们(按位)。结果将<ACT_LAYER_TAP><layer><key>
打包到整数中。图层的值可以是0-15,密钥的值可以是0-255。
回到上面的内容,我们可以看到<layer>
实际上只是keycode的第8-11位。 key是keycode的0-7位。所以我们最终得到的是<ACT_LAYER_TAP><first 12 bits of keycode>
打包成一个整数。