如何通过环绕将 4 字节数组移位所有 32 位?
How to shift 4 byte array by all 32 bits with a wraparound?
我正在尝试实现动画移动功能,这将允许我将所有 (LAYERS*BYTES) LED 移动 32 位并重叠。我只能通过字节移位来完成,但这不是我需要的。
为了更好地理解这个想法,下面提供了图片:
我把它画出来了,其中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 ;
}
}
}
如果图层始终为 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 )
}
另一种方法是使用联合。例如,
typedef union{
uint8_t buff8[4];
uint32_t buff32;
}led_buffer_t;
然后用它来声明LED_Buffer
(例如led_buffer_t LED_Buffer[LAYERS] = {0};
)
然后在这里使用循环移位答案:Circular shift in c
我在这里试过了:https://onlinegdb.com/ByfcMY1sE
我正在尝试实现动画移动功能,这将允许我将所有 (LAYERS*BYTES) LED 移动 32 位并重叠。我只能通过字节移位来完成,但这不是我需要的。
为了更好地理解这个想法,下面提供了图片:
我把它画出来了,其中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 ;
}
}
}
如果图层始终为 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 )
}
另一种方法是使用联合。例如,
typedef union{
uint8_t buff8[4];
uint32_t buff32;
}led_buffer_t;
然后用它来声明LED_Buffer
(例如led_buffer_t LED_Buffer[LAYERS] = {0};
)
然后在这里使用循环移位答案:Circular shift in c
我在这里试过了:https://onlinegdb.com/ByfcMY1sE