如何将 'convert' 的 Hz 量转换为适当的 byte/bit 格式?
How to 'convert' amount of Hz to appropriate byte/bit format?
我正在为红外摄像机编程。但是用于存储刷新率的内部寄存器(总共 16 个中的第 9、8 和 7 位)当然只接受 1 和 0。例如,值 0b110 表示 32Hz,0b111 表示 64Hz。查看刷新率控制图片时,如何最好地将 0.5Hz 和 64Hz 之间的给定整数 (refresh_rate
) 值转换为 0b000 - 0b111?
老实说,我还没有尝试过任何东西,因为我认为这需要一个奇怪的技巧。然而,我一直在考虑查找表,我认为这是可能的,但需要更多的内存,而且它必须是内存高效的,因为它是在 Arduino Due 上编程的。
注意:您可以看到 refresh_rate 是一个 uint16_t
,它不接受浮点值,例如 0.5Hz,但是,我可能不会使用 0.5Hz 设置。
// the end-user currently has to pass a value between 7 and 0
void mlx90650::set_refresh_rate(uint16_t refresh_rate) {
// So the refresh rate may not be higher than 7 (0b111) since this register only
accepts 3 bits. The memory map is:
/*
| decimal | bits |
(decimal 0) 0 0 0 IR refresh rate = 0.5Hz
(decimal 1) 0 0 1 IR refresh rate = 1Hz
(decimal 2) 0 1 0 IR refresh rate = 2Hz (default)
(decimal 3) 0 1 1 IR refresh rate = 4Hz
(decimal 4) 1 0 0 IR refresh rate = 8Hz
(decimal 5) 1 0 1 IR refresh rate = 16Hz
(decimal 6) 1 1 0 IR refresh rate = 32Hz
(decimal 7) 1 1 1 IR refresh rate = 64H
*/
}
我希望此函数将例如 64Hz 转换为 0b111。
先将寄存器中的Hz值转换成数字:
register_value >>= 7; // Shift right 7 bits.
register_value &= 7; // Keep remaining 3 bits.
接下来,通过左移计算赫兹。
herz = (1 << register_value) / 2.;
要设置赫兹值,请执行相反(反向)步骤。
无论您将实际的 Hz 映射到位模式,您都可以像这样设置它们:
void set_hz(uint16_t& control_reg, uint8_t hz) // here hz is 0 for .5 Hz, 1 for 1Hz,.. 7 for 64Hz
{
constexpr int hz_shift = 7;
constexpr uint16_t hz_mask = static_cast<uint16_t>(0x07) << hz_shift;
control_reg &= ~hz_mask;
control_reg |= static_cast<uint16_t>(hz) << hz_shift;
}
How can I best convert a given integer (refresh_rate) value between 0.5Hz and 64Hz to 0b000 - 0b111
一种方法是看到输入每增加一倍目标值就增加一个,意思是log2(Hz) + 1.
所以,你可以这样写
uint16_t hz_bits(float hz) {
return static_cast<uint16_t>(round(1.0f + log2(hz)));
}
诚然需要 floating-point 而不是 highly-optimized。反之,
float hz_from_bits(uint16_t hzB) {
return 0.5f * (1 << hzB);
}
这两个都将您关心的三位作为 uint16_t
的最低有效位。
如果你想使用整数赫兹数,而忽略 0.5
的情况,那么 log2 就是最高设置位的编号:例如,64 = 0b1000000,最高设置位为 6(您仍然需要加 1 以获得 7 = 0b111)。
然后你可以将它们与
之类的东西结合起来
static const uint16_t HZ_START = 7;
static const uint16_t HZ_LEN = 3;
static const uint16_t HZ_MASK = ((1 << HZ_LEN)-1) << HZ_START;
uint16_t set_hz_bits(uint16_t control, uint16_t hzB) {
return (control & ~HZ_MASK) | (hzB << HZ_START);
}
uint16_t get_hz_bits(uint16_t control) {
return (control & HZ_MASK) >> HZ_START;
}
进入
uint16_t set_hz(uint16_t control, float hz) {
return set_hz_bits(control, hz_bits(hz));
}
float get_hz(uint16_t control) {
return hz_from_bits(get_hz_bits(control));
}
请注意,实际的位屏蔽和移位是非常机械的 - 您可以很容易地为您的各个领域自动化这些东西,使用类似下面的东西,并传递 HzField
个对象,而不必记住哪个uint16_t
包含 zero-based 编码的 Hz 值,并且正确包含 layed-out 控制寄存器。
template <size_t Bstart, size_t Blen, typename T = uint16_t>
struct BitField
{
T value; // zero-based, not shifted
static constexpr T mask() { return ((1 << Blen)-1) << Bstart; }
static T clear(T r) { return r & ~mask(); }
void decode(T r) { value = (r & mask()) >> Bstart; }
T encode(T r) { return clear(r) | ((value << Bstart) & mask()); }
// etc.
};
using HzField = BitField<7, 3>;
我正在为红外摄像机编程。但是用于存储刷新率的内部寄存器(总共 16 个中的第 9、8 和 7 位)当然只接受 1 和 0。例如,值 0b110 表示 32Hz,0b111 表示 64Hz。查看刷新率控制图片时,如何最好地将 0.5Hz 和 64Hz 之间的给定整数 (refresh_rate
) 值转换为 0b000 - 0b111?
老实说,我还没有尝试过任何东西,因为我认为这需要一个奇怪的技巧。然而,我一直在考虑查找表,我认为这是可能的,但需要更多的内存,而且它必须是内存高效的,因为它是在 Arduino Due 上编程的。
注意:您可以看到 refresh_rate 是一个 uint16_t
,它不接受浮点值,例如 0.5Hz,但是,我可能不会使用 0.5Hz 设置。
// the end-user currently has to pass a value between 7 and 0
void mlx90650::set_refresh_rate(uint16_t refresh_rate) {
// So the refresh rate may not be higher than 7 (0b111) since this register only
accepts 3 bits. The memory map is:
/*
| decimal | bits |
(decimal 0) 0 0 0 IR refresh rate = 0.5Hz
(decimal 1) 0 0 1 IR refresh rate = 1Hz
(decimal 2) 0 1 0 IR refresh rate = 2Hz (default)
(decimal 3) 0 1 1 IR refresh rate = 4Hz
(decimal 4) 1 0 0 IR refresh rate = 8Hz
(decimal 5) 1 0 1 IR refresh rate = 16Hz
(decimal 6) 1 1 0 IR refresh rate = 32Hz
(decimal 7) 1 1 1 IR refresh rate = 64H
*/
}
我希望此函数将例如 64Hz 转换为 0b111。
先将寄存器中的Hz值转换成数字:
register_value >>= 7; // Shift right 7 bits.
register_value &= 7; // Keep remaining 3 bits.
接下来,通过左移计算赫兹。
herz = (1 << register_value) / 2.;
要设置赫兹值,请执行相反(反向)步骤。
无论您将实际的 Hz 映射到位模式,您都可以像这样设置它们:
void set_hz(uint16_t& control_reg, uint8_t hz) // here hz is 0 for .5 Hz, 1 for 1Hz,.. 7 for 64Hz
{
constexpr int hz_shift = 7;
constexpr uint16_t hz_mask = static_cast<uint16_t>(0x07) << hz_shift;
control_reg &= ~hz_mask;
control_reg |= static_cast<uint16_t>(hz) << hz_shift;
}
How can I best convert a given integer (refresh_rate) value between 0.5Hz and 64Hz to 0b000 - 0b111
一种方法是看到输入每增加一倍目标值就增加一个,意思是log2(Hz) + 1.
所以,你可以这样写
uint16_t hz_bits(float hz) {
return static_cast<uint16_t>(round(1.0f + log2(hz)));
}
诚然需要 floating-point 而不是 highly-optimized。反之,
float hz_from_bits(uint16_t hzB) {
return 0.5f * (1 << hzB);
}
这两个都将您关心的三位作为 uint16_t
的最低有效位。
如果你想使用整数赫兹数,而忽略 0.5
的情况,那么 log2 就是最高设置位的编号:例如,64 = 0b1000000,最高设置位为 6(您仍然需要加 1 以获得 7 = 0b111)。
然后你可以将它们与
之类的东西结合起来static const uint16_t HZ_START = 7;
static const uint16_t HZ_LEN = 3;
static const uint16_t HZ_MASK = ((1 << HZ_LEN)-1) << HZ_START;
uint16_t set_hz_bits(uint16_t control, uint16_t hzB) {
return (control & ~HZ_MASK) | (hzB << HZ_START);
}
uint16_t get_hz_bits(uint16_t control) {
return (control & HZ_MASK) >> HZ_START;
}
进入
uint16_t set_hz(uint16_t control, float hz) {
return set_hz_bits(control, hz_bits(hz));
}
float get_hz(uint16_t control) {
return hz_from_bits(get_hz_bits(control));
}
请注意,实际的位屏蔽和移位是非常机械的 - 您可以很容易地为您的各个领域自动化这些东西,使用类似下面的东西,并传递 HzField
个对象,而不必记住哪个uint16_t
包含 zero-based 编码的 Hz 值,并且正确包含 layed-out 控制寄存器。
template <size_t Bstart, size_t Blen, typename T = uint16_t>
struct BitField
{
T value; // zero-based, not shifted
static constexpr T mask() { return ((1 << Blen)-1) << Bstart; }
static T clear(T r) { return r & ~mask(); }
void decode(T r) { value = (r & mask()) >> Bstart; }
T encode(T r) { return clear(r) | ((value << Bstart) & mask()); }
// etc.
};
using HzField = BitField<7, 3>;