gpt4 book ai didi

c - 如何制作 3D 面具

转载 作者:太空宇宙 更新时间:2023-11-04 02:43:56 25 4
gpt4 key购买 nike

目前遇到一个技术问题,想改进之前的实现,情况是:

我有 5 个 GPIO 引脚,我需要使用这些引脚作为硬件标识符,例如:

pin1: LOW
pin2: LOW
pin3: LOW
pin4: LOW
pin5: LOW

这意味着我的硬件变体之一,因此我们可以有多种组合。在之前的设计中,开发者使用if-else来实现,就像:

if(PIN1 == LOW && ... && ......&& PIN5 ==LOW) 
{
HWID = variant1;
}
else if( ... )
{
}
...
else
{
}

但是我觉得这样不好,因为它会有200多个变体,而且代码会变得很长,我想把它改成一个mask。我的想法是将这五个引脚视为一个五位寄存器,因为我可以根据 GPIO 状态预测我需要分配哪个变体(这已经由硬件团队定义,他们提供了一个变体列表,其中包含所有这些 GPIO 引脚配置) ,因此,代码可能如下所示:

enum{
variant 0x0 //GPIO config 1
...
variant 0xF3 //GPIO config 243
}

然后我可以先读取这五个 GPIO 引脚状态,然后与某个掩码进行比较,看它们是否相等。

问题

但是对于GPIO来说,它有三种状态,分别是:LOW、HIGH、OPEN。有什么好的计算方法可以得到一个3D掩模吗?

最佳答案

您有 5 个引脚,每个引脚有 3 个状态。您可以通过几种方式来表示这一点。

首先,想象一下使用这种框架:

#define LOW (0)
#define HIGH (1)
#define OPEN (2)

uint16_t config = PIN_CONFIG(pin1, pin2, pin3, pin4, pin5);

if(config == PIN_CONFIG(LOW, HIGH, OPEN, LOW, LOW))
{
// do something
}

switch(config) {
case PIN_CONFIG(LOW, HIGH, OPEN, LOW, HIGH):
// do something;
break;
}

uint16_t config_max = PIN_CONFIG(OPEN, OPEN, OPEN, OPEN, OPEN);
uint32_t hardware_ids[config_max + 1] = {0};

// init your hardware ids
hardware_ids[PIN_CONFIG(LOW, HIGH, HIGH, LOW, LOW)] = 0xF315;
hardware_ids[PIN_CONFIG(LOW, LOW, HIGH, LOW, LOW)] = 0xF225;

// look up a HWID
uint32_t hwid = hardware_ids[config];

此代码正是您想要对引脚配置进行的那种操作。唯一需要实现的是 PIN_CONFIG


方法一

第一种方法是继续将其用作位域,但不是每个引脚 1 位,而是使用 2 位来表示每个引脚状态。我认为这是最干净的,即使您为每个引脚“浪费”了一半。

#define PIN_CLAMP(x) ((x) & 0x03)
#define PIN_CONFIG(p1, p2, p3, p4, p5) \\
(PIN_CLAMP(p1) & \\
(PIN_CLAMP(p2) << 2) & \\
(PIN_CLAMP(p3) << 4) & \\
(PIN_CLAMP(p4) << 6) & \\
(PIN_CLAMP(p5) << 8))

这有点不错,因为如果您稍后要进行搜索,它会为“无关”或“无效”值留出空间。


方法二

或者,您可以使用算术运算,确保使用所需的最少位数。也就是说,~1.5 位来编码 3 个值。正如预期的那样,这从 0 到 242 总共有 3^5=243 个状态。在不了解您的情况的情况下,我相信这是您的引脚状态的最小完整编码。(实际上,您必须使用 8 位来编码 243 个值,因此每个引脚高 1.5 位)

#define PIN_CLAMP(x) ((x) % 3) /* note this should really assert */
#define PIN_CONFIG(p1, p2, p3, p4, p5) \\
(PIN_CLAMP(p1) & \\
(PIN_CLAMP(p2) * 3) & \\
(PIN_CLAMP(p3) * 9) & \\
(PIN_CLAMP(p4) * 27) & \\
(PIN_CLAMP(p5) * 81))

方法 1.1

如果你不喜欢预处理器的东西,你可以使用像这样的函数:

enum PinLevel (low = 0, high, open);

void set_pin(uint32_t * config, uint8_t pin_number, enum PinLevel value) {
int shift = pin_number * 2; // 2 bits
int mask = 0x03 << shift; // 2 bits set to on, moved to the right spot
*config &= ~pinmask;
*config |= (((int)value) << shift) & pinmask;
}

enum PinLevel get_pin(uint32_t config, uint8_t pin_number) {
int shift = pin_number * 2; // 2 bits
return (enum PinLevel)((config >> shift) & 0x03);
}

这遵循第一种(每个值 2 位)方法。


方法 1.2

使用 C 的酷位域语法的另一种方式:

struct pins {
uint16_t pin1 : 2;
uint16_t pin2 : 2;
uint16_t pin3 : 2;
uint16_t pin4 : 2;
uint16_t pin5 : 2;
};

typedef union pinconfig_ {
struct pins pins;
uint16_t value;
} pinconfig;

pinconfig input;
input.value = 0; // don't forget to init the members unless static

input.pins.pin1 = HIGH;
input.pins.pin2 = LOW;

printf("%d", input.value);

input.value = 0x0003;
printd("%d", input.pins.pin1);

union 让您可以将位域视为数字,反之亦然。

(注意:所有代码都完全未经测试)

关于c - 如何制作 3D 面具,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29246416/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com