How to shift a byte through multiple byte array

时间:2019-04-16 22:43:59

标签: c byte bit-shift

I am working on LED Tower that contains 15 layers, where each of them contains 4 bytes (32 LEDs). I would like to be able to shift a byte from right to left. However there is an issue with multiple bytes, can't figure out how to continously transition the shifting.

Additional information:

void Invert_Display(void){
for (int y = 0; y < LAYERS; y++){
    for (int x = 0; x < BYTES; x++){
        LED_Buffer[y][x] ^= (0b11111111);
    }
}
Update_Display();

Where UpdateDisplay function is as follows:

void Update_Display(void){

    while(!TRMT);           // Wait until transmission register is empty

    for (int y = 0; y < LAYERS; y++){
        for (int x = 0; x < BYTES; x++){
        TXREG = LED_Buffer[y][x];
        while (!TRMT);
        }
    }

    LE = 1;                 // Data is loaded to the Output latch
    NOP();              
    LE = 0;                 // Data is latched into the Output latch

The expected outcome is attached below.enter image description here

2 个答案:

答案 0 :(得分:1)

The following code will shift an array of bytes to the left. The number of bits to shift must be between 1 and 7. Shifting by more than 7 would require additional code.

void shiftArrayLeft(unsigned char array[], int length, int shift) // 1 <= shift <= 7
{
    unsigned char carry = 0;                        // no carry into the first byte
    for (int i = length-1; i >= 0; i--)
    {
        unsigned char temp = array[i];              // save the value
        array[i] = (array[i] << shift) | carry;     // update the array element
        carry = temp >> (8 - shift);                // compute the new carry
    }
}

It works by storing the old value from the array. Then update the current array element by shifting it and logical-OR a carry from the previous byte. Then compute the new carry (the upper bits of the original value).

The function can be called with code like this

unsigned char array[] = { 0x00, 0x00, 0x00, 0xAA };
int length = sizeof(array) / sizeof(array[0]);
shiftArrayLeft(array, length, 1);

which will change the array to { 0x00, 0x00, 0x01, 0x54 }

答案 1 :(得分:0)

这会将每一行打印到屏幕上,将各行移动一位。
iteratewrap允许图像移动几个循环。
pattern一次添加到第[7]行,下一个循环将模式扩展到相邻行,因此它们包含相同的模式,但右移一位。
模式也会左右移动。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>

void show ( unsigned char *bank, size_t size) {
    for ( size_t byte = 0; byte < size; ++byte) {
        unsigned char mask = 0x80;
        for ( int bit = 0; bit < CHAR_BIT; ++bit) {
            mask & bank[byte] ? printf ( "*") : printf ( " ");
            mask >>= 1;
        }
    }
    printf ( "\r");
}

void shiftright ( unsigned char *bank, size_t size) {
    unsigned char carry = 0;
    for ( size_t byte = 0; byte < size; ++byte) {
        unsigned char mask = bank[byte] & 1;
        bank[byte] >>= 1;
        bank[byte] |= carry << ( CHAR_BIT - 1);
        carry = mask;
    }
}

void shiftleft ( unsigned char *bank, size_t size) {
    unsigned char carry = 0;
    for ( size_t byte = size; byte > 0; ) {
        byte--;
        unsigned char mask = bank[byte] & 0x80;
        bank[byte] <<= 1;
        bank[byte] |= carry >> ( CHAR_BIT - 1);
        carry = mask;
    }
}

void shiftdown ( size_t rows, size_t cols, unsigned char (*bank)[cols]) {
    for ( size_t height = rows; height > 1; ) {
        height--;
        memmove ( bank[height], bank[height - 1], cols);
    }
}

int main( void) {
    unsigned char bank[15][4] = { { 0}};

    printf ( "\n\n\n\n\n\n\n");

    unsigned char pattern = 0xaa;
    for ( int iterate = 3; iterate >= 0; --iterate) {
        for ( int slide = 0; slide < ( sizeof bank[0] * CHAR_BIT); ++slide) {
            for ( int row = 0; row < sizeof bank / sizeof bank[0]; ++row) {
                int wrap = bank[row][0] & 0x80;
                show ( bank[row], sizeof bank[row]);
                shiftleft ( bank[row], sizeof bank[row]);
                if ( wrap) {
                    bank[row][3] |= 1;
                }
                printf ( "\n");
            }
            //add pattern
            unsigned char bit;
            if ( pattern) {//add the pattern to row 7, bit by bit
                bit = 0x80 & pattern;
                if ( bit) {
                    bank[7][3] |= 1;
                }
                pattern <<= 1;
            }
            if ( slide < CHAR_BIT * 2) {//extend pattern to adjacent rows. one bit behind
                unsigned char mask = 0x01;
                for ( int length = 0; length < 7; ++length) {
                    bit = mask & bank[7][3];
                    for ( int height = 0; height < length; ++height) {//add bit to widening lines from center
                        bank[7 - height][3] |= bit;
                        bank[7 + height][3] |= bit;
                        bit >>= 1;
                    }
                    mask <<= 1;
                }
            }
            usleep ( 150000);
            printf ( "\n\n\n\n\n\n\n");
        }
    }
    for ( int iterate = 3; iterate >= 0; --iterate) {
        for ( int slide = 0; slide < sizeof bank / sizeof bank[0]; ++slide) {
            unsigned char wraprow[4];
            memmove ( wraprow, bank[14], sizeof wraprow);
            shiftdown ( sizeof bank / sizeof bank[0], sizeof bank[0], bank);
            memmove ( bank[0], wraprow, sizeof wraprow);
            for ( int row = 0; row < sizeof bank / sizeof bank[0]; ++row) {
                show ( bank[row], sizeof bank[row]);
                printf ( "\n");
            }
            usleep ( 150000);
            printf ( "\n\n\n\n\n\n\n");
        }
    }
    for ( int iterate = 3; iterate >= 0; --iterate) {
        for ( int slide = 0; slide < ( sizeof bank[0] * CHAR_BIT); ++slide) {
            for ( int row = 0; row < sizeof bank / sizeof bank[0]; ++row) {
                int wrap = bank[row][3] & 1;
                show ( bank[row], sizeof bank[row]);
                shiftright ( bank[row], sizeof bank[row]);
                if ( iterate && wrap) {
                    bank[row][0] |= 0x08;
                }
                printf ( "\n");
            }
            usleep ( 150000);
            printf ( "\n\n\n\n\n\n\n");
        }
    }
    printf ( "\n");
    return 0;
}