How do I efficiently write to every 12th bit of an array of three 32-bit integers?

37 Views Asked by At

I'm coding on an Arduino R4 Wifi and experimenting with the onboard 8x12 matrix of LEDs. Per the official documentation, it is possible to store frames either as an array of bytes:

uint8_t frame[8][12] = {
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};

or as an array of three 32 bit integers:

unsigned long frame[] = {
  0,
  0,
  0
};

The latter is obviously more memory efficient, but I am having trouble figuring out how to efficiently manipulate specific bits inside of it. For example, if I wanted to turn the rightmost column on using the byte array I could do:

for(int i = 0; i < 8; i++){
  frame[i][12] = 1;
}

I, however, cannot seem to find an efficient way to map the same for loop to the array of longs. This is the desired mapping:

i =
0 -> frame[0], position 20
1 -> frame[0], position 8
2 -> frame[1], position 28
3 -> frame[1], position 16
4 -> frame[1], position 4
5 -> frame[2], position 24
6 -> frame[2], position 12
7 -> frame[2], position 0

I was able to come up with this loop:

for(int i = 0; i < 8; i++){
  bitWrite(frame[(i+1)/3)], ((7-i) / 3) * 4) + (((7 - i) % 3) * 12), 1);
}

This is obviously ugly to look at and seems to be computationally inefficient. It works, but it's not pretty.

1

There are 1 best solutions below

0
Michaël Roy On

The most efficient way of storing an 12x8 bits array is an array of 12 bytes.

As in:

uint8_t frame[12] = {};

All you need are the simple functions to access individual bits, example:

   // assumes x and y aree within bounds.
   inline void led_on(int x, int y) 
   {
       // assert(0 <= x && x < 12)
       // assert(0 <= y && y < 8)
       frame[x] |= (1 << y);
   }

   inline void led_off(int x, int y) 
   {
       // assert(0 <= x && x < 12)
       // assert(0 <= y && y < 8)
       frame[x] &= ~(1 << y);
   }

   inline bool get_led(int x, int y) 
   {
       // assert(0 <= x && x < 12)
       // assert(0 <= y && y < 8)
       return (frame[x] & (1 << y)) != 0;
   }