Как сдвинуть 4-байтовый массив на все 32 бита с циклом? - PullRequest
0 голосов
/ 24 апреля 2019

Я пытаюсь реализовать функцию сдвига анимации, которая позволит мне сместить все (LAYERS * BYTES) светодиоды на 32 бита с перекрытием. Я мог бы сделать это только с помощью сдвига байтов, но это не то, что мне нужно.

Чтобы лучше понять идею, изображение приведено ниже:

enter image description here

Я вытянул его, где C - это бит переноса, который перемещается в начало следующего байта, а последний элемент из 4 байтов назначается первому элементу первого байта.

Возможно, есть лучший способ реализовать это. Я благодарен за любую помощь заранее.

Дополнительная информация:

void Shift_Right_Byte(void){
    for (int row = 0; row < LAYERS; row++) {
            for (int col = 0; col < BYTES; col++) {
                LED_Buffer[row][col] = LED_Buffer[row][(col + 1) % BYTES];
            }
        }
        delay(1000);
}

Новая функция:

void layer_rotate_right(void) 
{
    for (int row = 0; row < LAYERS; row++) {
        unsigned char carry = LED_Buffer[row][BYTES - 1] << 7 ;
        for( int i = 0; i < BYTES; i++ )
        {   
            unsigned char next_carry = LED_Buffer[row][i] << 7 ;
            LED_Buffer[row][i] = (LED_Buffer[row][i] >> 1) | carry ;
            carry = next_carry ;
        }
    }
}

Ответы [ 2 ]

2 голосов
/ 24 апреля 2019

Конкретным решением, если слой всегда равен 4 байта, является упаковка байтов в uint32_t и применение поворота к нему.

Дано:

void layer_rotate_right( uint8_t layer[4] ) 
{
    // Pack...
    uint32_t word = layer[0]<<24 | layer[1]<<16 | layer[2]<<8 | layer[3] ;

    // Rotate...
    uint32_t rotated = word << 31 | word >> 1 ;

    // Unpack...
    layer[0] = rotated >> 24 ;
    layer[1] = (rotated >> 16) & 0xff ;
    layer[2] = (rotated >> 8) & 0xff ;
    layer[3] = rotated & 0xff ;
}

Тогда:

for (int row = 0; row < LAYERS; row++) 
{
    layer_rotate_right( LED_Buffer[row] )
}

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

Более общее решение для байтового массива любого размера:

void layer_rotate_right( uint8_t* layer, int len ) 
{
    uint8_t carry = layer[len - 1] << 7 ;
    for( int i = 0; i < len; i++ )
    {   
        uint8_t next_carry = layer[i] << 7 ;
        layer[i] = (layer[i] >> 1) | carry ;
        carry = next_carry ;
    }
}

Тогда:

for (int row = 0; row < LAYERS; row++) 
{
    layer_rotate_right( LED_Buffer[row], BYTES )
}
1 голос
/ 25 апреля 2019

Другой подход - использовать союз.Например,

typedef union{
    uint8_t buff8[4];
    uint32_t buff32;
}led_buffer_t;

Затем используйте это для объявления LED_Buffer (например, led_buffer_t LED_Buffer[LAYERS] = {0};)

И затем используйте ответ с круговым сдвигом здесь: Сдвиг по кругу в с

Я попробовал это здесь: https://onlinegdb.com/ByfcMY1sE

...