Как преобразовать количество Гц в соответствующий формат байтов / бит? - PullRequest
1 голос
/ 29 мая 2019

Я программирую инфракрасную камеру.Но внутренний регистр для сохранения частоты обновления (биты 9, 8 и 7 из 16 всего), конечно, принимает только 1 и 0.Например, значение 0b110 означает 32 Гц, а 0b111 - 64 Гц.Как лучше всего преобразовать заданное целочисленное значение (refresh_rate) между 0,5 Гц и 64 Гц в 0b000 - 0b111, если посмотреть на изображение управления частотой обновления?

Если честноЯ еще ничего не пробовал, потому что думаю, что это требует странного взлома.Тем не менее, я думал о поиске в таблице, я думаю, что это возможно, но требует больше памяти, и он должен быть эффективным, так как он запрограммирован на Arduino Due.

Примечание: Вы можете видеть, что refresh_rate - это uint16_t, который не принимает значения с плавающей запятой, такие как 0,5 Гц, однако, я, вероятно, не собираюсь использовать настройку 0,5 Гц.

// 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
*/
}

Я хочу, чтобы эта функция преобразовывала, например, 64 Гц в 0b111.

Ответы [ 3 ]

2 голосов
/ 29 мая 2019

Сначала преобразуйте значение Гц в регистре в число:

register_value >>= 7;  // Shift right 7 bits.
register_value &= 7;  // Keep remaining 3 bits. 

Затем вычислите Гц, сдвигая влево.

herz = (1 << register_value) / 2.;

Чтобы установить значение Герца, выполните противоположные (обратные) шаги.

1 голос
/ 29 мая 2019

Как лучше всего преобразовать заданное целочисленное значение (refresh_rate) между 0,5 Гц и 64 Гц в 0b000 - 0b111

Один из подходов состоит в том, чтобы увидеть, что целевое значение увеличивается на единицу каждый раз, когда ввод удваивается, то есть оно равно log 2 (Гц) + 1 .

Итак, вы можете написать

uint16_t hz_bits(float hz) {
    return static_cast<uint16_t>(round(1.0f + log2(hz)));
}

, который по общему признанию требует плавающей точки и не очень оптимизирован. С другой стороны,

float hz_from_bits(uint16_t hzB) {
    return 0.5f * (1 << hzB);
}

Оба из этих трех битов, о которых вы заботитесь, являются наименее значимыми битами uint16_t.

Если вы хотите использовать целое число Гц и игнорировать регистр 0.5, тогда log 2 - это просто номер старшего установленного бита: например, 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 содержат закодированные с нуля значения Гц и содержащие правильно размеченные управляющие регистры.

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>;
0 голосов
/ 29 мая 2019

Как бы вы ни отображали фактические Гц в битовые комбинации, вы устанавливаете их так:

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;
} 
...