0

Having a given byte array which represents a capital "A", which is laying on the right site. (source)

The expected result is to rotate the byte array counter clockwise for a standing "A".

My attempt to convert the given array into a rotated version is working but not nice. Something in my code is not correct in "loop()" at the bit shifting and calculation part. For this reason I had to handle x==5 and x==6 separately.

How can I rotate a byte array counter clockwise in a more generic way in c?

Finally the array is displayed at a 8x8 LED Matrix on Arduino. See code and output below.

Code:

#include "LedControl.h"
LedControl lc=LedControl(12,11,10,4);

void setup(){
  for (int addr=0; addr<lc.getDeviceCount(); addr++){
    lc.shutdown(addr,false);
    lc.setIntensity(addr,0);
    lc.clearDisplay(addr);
  }
}

void loop(){
  // given
  byte a[5]={B01111110,B00010001,B00010001,B01111110,B00000000};

  // expected
  byte a2[8]={B01100000,B10010000,B10010000,B10010000,B11110000,B10010000,B10010000,B00000000};

  // rotated
  byte a3[8];
  byte row;
  for (int x = 0; x < 8; x++){
    row = B00000000;
    for (int y = 0; y < 5; y++){
      if (x==0 || x==1 || x==2 || x==3 || x==4) {
        row |= (a[y] & B00000001 << x) << 7-x-y;
      }
      if (x==5) {
        row |= (a[0] & B00100000) << 2;
        row |= (a[1] & B00100000) << 1;
        row |= (a[2] & B00100000);
        row |= (a[3] & B00100000) >> 1;
      }
      if (x==6) {
        row |= (a[0] & B01000000) << 1;
        row |= (a[1] & B01000000);
        row |= (a[2] & B01000000) >> 1;
        row |= (a[3] & B01000000) >> 2;
      }
    }
    a3[x] = row;
  }

  // output
  for(int i=0; i<8; i++){
    lc.setRow(0,i,a[i]); // given
    lc.setRow(1,i,a2[i]); // expected
    lc.setRow(2,i,a3[i]); // rotated
    delay(100);
  }
}

Output LEDs:

given a            expected a2
                   rotated a3

_ o o o o o o _    _ o o _ _ _ _ _
_ _ _ o _ _ _ o    o _ _ o _ _ _ _
_ _ _ o _ _ _ o    o _ _ o _ _ _ _
_ o o o o o o _    o _ _ o _ _ _ _
_ _ _ _ _ _ _ _    o o o o _ _ _ _
_ _ _ _ _ _ _ _    o _ _ o _ _ _ _
_ _ _ _ _ _ _ _    o _ _ o _ _ _ _
_ _ _ _ _ _ _ _    _ _ _ _ _ _ _ _

1 Answer 1

1

Your code seems really overdone. You can use a nested loop which iterates any each possible bit of source data and set dest data accordingly (which basically swaps indices), something like:

#include <stdio.h>

typedef unsigned char byte;

void printCharacter(const byte* data, size_t length)
{
  for (size_t i = 0; i < length; ++i)
  {
    for (size_t j = 0; j < 8; ++j)
    {
      const unsigned char mask = 1 << j;
      printf("%c ", data[i] & mask ? 'o' : '-');
    }
    printf("\n");
  }
}

void rotate(const byte* source, byte* dest, size_t length)
{
  /* for each bit position starting from first */
  for (size_t j = 0; j < 8; ++j)
  {
    /* this is the mask of the i-th bit in source data */
    const unsigned char mask = 1 << j;

    /* for each row in source data (which will become column) */
    for (size_t i = 0; i < length; ++i)
    {
      /* if j-th bit of i-th row set */
      if (source[i] & mask)
      /* then set i-th bit of j-th row */
        dest[j] |= 1 << i;
    }
  }
}

int main() {
  byte a[5]= { 0b01111110,0b00010001,0b00010001,0b01111110,0b00000000 };
  byte b[8]= { 0 };
  printCharacter(a, 5);
  rotate(a, b, 5);
  printCharacter(b, 8);
  return 0;
}

Now this outputs

- o o o o o o - 
o - - - o - - - 
o - - - o - - - 
- o o o o o o - 
- - - - - - - - 

- o o - - - - - 
o - - o - - - - 
o - - o - - - - 
o - - o - - - - 
o o o o - - - - 
o - - o - - - - 
o - - o - - - - 
- - - - - - - - 

which is not exactly what you are looking for, but you just need to adjust the mask/index to start from first/last bit according to the rotation you want.

Sign up to request clarification or add additional context in comments.

6 Comments

In your solution the source and destination may not overlap.
@PaulOgilvie: so where's the point? Just use memcpy after the new array is created. The OP isn't requiring to avoid using temporary data so why would you make your life much more complicated without the need of an auxiliary temporary array? There's no reason to do it, as there were no reason to downvote.
Jack, you are right. It is still worth noticing (in part by the const directive). The downvote was undone once I noticed it was not a requirement.
Yes totally worth noticing, I just assumed it wasn't a requirement (also because memcpy afterwards doesn't have any strange side effects unless specified)
@Jack: Thank you, but your code seems to mirror the letter while rotating (which is not noticeable for an A) but for "J" you will see: byte j[5] = {B00110000, B01000000, B01000001, B00111111, B00000000};
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.