Byte mirroring

Is there a function that can mirror a byte?

If i have 11111100 i want to obtain 00111111
i will try ~

what i have so far is

uint8_t S65Display::ReverseByteBits(uint8_t value)
        {
            uint8_t ret = 0;
            for (int i = 0; i < 8; i++)
                if ((value & (uint8_t)(1 << i)) != 0) ret += (uint8_t)(1 << (7 - i));
            return ret;
        }

is there a quicker way?

Shifts by more than one bit are slow on Arduino. You should be able to do it with a total of 16.
If you are in a real hurry, use a lookup table in PROGMEM.

reverse(uint8_t in)
{
  uint8_t out;
  char i;

  out = 0;

  for (i = 0; i < 8; i++) {
      out <<= 1;
      if (in & 1)
        out |= 1;
      in >>= 1;
  }

  return out;
}

less compact, but faster

reverse(uint8_t in)
{
  uint8_t out;
  out = 0;
  if (in & 0x01) out |= 0x80;
  if (in & 0x02) out |= 0x40;
  if (in & 0x04) out |= 0x20;
  if (in & 0x08) out |= 0x10;
  if (in & 0x10) out |= 0x08;
  if (in & 0x20) out |= 0x04;
  if (in & 0x40) out |= 0x02;
  if (in & 0x80) out |= 0x01;

  return(out);
}

There is no reason to perform the if test. The statement will write either a 0 or a 1 to the specified bit. It will be faster if you simply write the 0 than to test that the value would be 0 in order to avoid writing the 0.

this is a job for - http://www.amazon.com/Hackers-Delight-Henry-S-Warren/dp/0201914654/ref=sr_1_1?ie=UTF8&s=books&qid=1299262192&sr=1-1

I have the book on my wishlist but there is allways this site for bithacks: - Bit Twiddling Hacks

(tested positive on Arduino)

 b = ((b * 0x0802LU & 0x22110LU) | (b * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16; 

or

b = (b * 0x0202020202ULL & 0x010884422010ULL) % 1023;  // 64 bit

there are more " bit beauties" there.

I recall several decades ago needing to 'flip' a byte in turbo pascal, so I wrote a function. It was ugly but it did work. I would think a nice class library function that would 'flip' any variable passed to it, byte, int, long, would be a neat function to have in one's toolbag? Any of you software gurus up to the challenge?

Lefty

I've worked on architectures (DSPs mostly) that do it in hardware because it is so useful for FFTs

Groove:
I've worked on architectures (DSPs mostly) that do it in hardware because it is so useful for FFTs

Is that the so called barrel shifter function or hardware ?

No, that's a one cycle shifter - these were often simply switchable bus lines

Groove:
No, that's a one cycle shifter - these were often simply switchable bus lines

Wow, that would be pretty fast, but I guess that's the reason/justification for such specialized hardware features frequently used in Dsp applications

@groove :
Hardware: 74HC595 (all lines crossed) 74HC165 shiftOut byte shiftIn reverse is that possible (no IC at hand)

@lefty
According to - Bit Twiddling Hacks

this should be it: (not tested)

unsigned int s = sizeof(v) * CHAR_BIT;   // bit size; must be power of 2 
unsigned int mask = ~0;         
while ((s >>= 1) > 0) 
{
  mask ^= (mask << s);
  v = ((v >> s) & mask) | ((v << s) & ~mask);
}

robtillaart:
this is a job for - http://www.amazon.com/Hackers-Delight-Henry-S-Warren/dp/0201914654/ref=sr_1_1?ie=UTF8&s=books&qid=1299262192&sr=1-1

I have the book on my wishlist but there is allways this site for bithacks: - Bit Twiddling Hacks

(tested positive on Arduino)

 b = ((b * 0x0802LU & 0x22110LU) | (b * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16; 

or

b = (b * 0x0202020202ULL & 0x010884422010ULL) % 1023;  // 64 bit




there are more " bit beauties" there.

Thanks for posting that - I was pretty certain there had to be a way to do it algorithmically without needing a loop construct, and that it had to be something already invented (if not in the AVR libc!); something that always gets me is the vast amount of time we spend constantly re-inventing the wheel, thinking that somehow we'll be able to do it better (or that our technique is first), seemingly forgetting that computing has a fairly long history behind it.

Not to mention the fact that if your CPU uses "fewer bits" than your PC, likely someone in the past 40-odd years (or greater if you want to include the pre-personal computing era) has already run into the issue, and a solution already exists; the only trouble is finding it, which is why knowing that link you posted (which I've run across in the past), as well as that book (which I haven't, but is going on my "to purchase" list - though I have too many books as it is!) - are both items (among many) that people in this field should be aware of...

:slight_smile:

likely someone in the past 40-odd years (or greater if you want to include the pre-personal computing era) has already run into the issue, and a solution already exists;

many interesting algorithms were invented/designed in the 60ies - most memorable Quicksort in 1960(!)

robtillaart:
@groove :
Hardware: 74HC595 (all lines crossed) 74HC165 shiftOut byte shiftIn reverse is that possible (no IC at hand)

@lefty
According to - Bit Twiddling Hacks

this should be it: (not tested)

unsigned int s = sizeof(v) * CHAR_BIT;   // bit size; must be power of 2 

unsigned int mask = ~0;        
while ((s >>= 1) > 0)
{
 mask ^= (mask << s);
 v = ((v >> s) & mask) | ((v << s) & ~mask);
}

I tried it but got a compiler error " CHAR_BIT not declared in scope" ?
Is that just how many bits in a character for the machine it's running on, 8 for AVR?

Thank you all for the replays, i did learn something from them
The link provided by robtillaart i added to favorites $)
This post is about using an array to draw chars on LCD's. i'm using LS020, LH88 and L2F50
the arrays looks like this, each line represents a character 8x8 bits

const prog_uint8_t font[] = 
{
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 0x20
  0x30,0x78,0x78,0x30,0x30,0x00,0x30,0x00, // 0x21
  0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00, // 0x22
  0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00, // 0x23
  0x30,0x7C,0xC0,0x78,0x0C,0xF8,0x30,0x00, // 0x24
  0x00,0xC6,0xCC,0x18,0x30,0x66,0xC6,0x00, // 0x25
  0x38,0x6C,0x38,0x76,0xDC,0xCC,0x76,0x00, // 0x26
  0x60,0x60,0xC0,0x00,0x00,0x00,0x00,0x00, // 0x27
  0x18,0x30,0x60,0x60,0x60,0x30,0x18,0x00, // 0x28
  0x60,0x30,0x18,0x18,0x18,0x30,0x60,0x00, // 0x29
  0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00, // 0x2A
  0x00,0x30,0x30,0xFC,0x30,0x30,0x00,0x00, // 0x2B
.........................

The L2F50 has a different way of reading bits
"T" char for example is rotated with 90deg and mirrored, the last part i resolve it with your help
now i have to rotate so that "|-" (this is an approximation) will become "T"
Any idea how to start?

this is the function to draw the char

uint8_t S65Display::drawChar(uint8_t x, uint8_t y, char c, uint8_t size, uint16_t color, uint16_t bg_color)
{
	uint8_t ret;
	uint8_t data, mask;
	uint8_t i, j, width, height;
	const prog_uint8_t *ptr;
	i  = (uint8_t)c;
	ptr= &font[(i-FONT_START)*(8*FONT_HEIGHT/8)];
	width  = FONT_WIDTH;
	height = FONT_HEIGHT;
	if(size <= 1)
	{
		ret = x+width;
		if(ret > S65_WIDTH) {return S65_WIDTH+1;}
		setArea(x, y, (x+width-1), (y+height-1));
		s65_drawStart();
		#ifdef S65_L2F50
			for(; height!=0; height--)
			{
				data = (pgm_read_byte(ptr) * 0x0202020202ULL & 0x010884422010ULL) % 1023;ptr+=1;//mirror bits
				for(mask=(1<<(width-1)); mask!=0; mask>>=1)
				{
					if(data & mask)
						s65_draw(color);
					else
						s65_draw(bg_color);
				}
			}
		#else
			for(; height!=0; height--)
			{
				data = pgm_read_byte(ptr); ptr+=1;
				for(mask=(1<<(width-1)); mask!=0; mask>>=1)
				{
					if(data & mask)
						s65_draw(color);
					else
						s65_draw(bg_color);
				}
			}
		#endif
		s65_drawStop();
	}
	else
	{
		ret = x+(width*size);
		if(ret > S65_WIDTH) {return S65_WIDTH+1;}
		s65_setArea(x, y, (x+(width*size)-1), (y+(height*size)-1));
		s65_drawStart();
		for(; height!=0; height--)
		{
			data = pgm_read_byte(ptr); ptr+=1;
			for(i=size; i!=0; i--)
			{
				for(mask=(1<<(width-1)); mask!=0; mask>>=1)
				{
					if(data & mask)
					{
						for(j=size; j!=0; j--)
						{
							s65_draw(color);
						}
					}
					else
					{
						for(j=size; j!=0; j--)
						{
							s65_draw(bg_color);
						}
					}
				}
			}
		}
		s65_drawStop();
	}
	return ret;
}

robtillaart:

likely someone in the past 40-odd years (or greater if you want to include the pre-personal computing era) has already run into the issue, and a solution already exists;

many interesting algorithms were invented/designed in the 60ies - most memorable Quicksort in 1960(!)

Definitely - some of the best stuff in computing, both hardware and software, was developed during that decade; many of the things we think of as "advanced" in a PC were actually available on mainframes of the era. The advance is in the miniaturization, and comoditization of these developments (which certainly shouldn't be discounted).

:slight_smile:

@lefty
CHAR-bit is #bits in a char so it must be 8. eg #define CHAR_BIT 8

(tested for the first 100 values not tested for other datatypes

void setup()
{
  Serial.begin(115200);
  Serial.println("I am Arduino");
}

void loop()
{
  for (unsigned int i=0; i < 65535; i++)
  {
    unsigned int v = i;
    Serial.print(v, BIN);
    Serial.print(' ');
    unsigned int s = sizeof(v) * 8;   // bits/byte; must be power of 2 
    unsigned int mask = ~0;         
    while ((s >>= 1) > 0) 
    {
      mask ^= (mask << s);
      v = ((v >> s) & mask) | ((v << s) & ~mask);
    }
    Serial.println(v, BIN);
  }
}

@Cr0sh

Where's the beer?

:slight_smile:

A very lovely village, but a long way from Sandwich