boolean programming code help?

Go To Last Post
40 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry if title is vague.

lets say I have a binary value 0b111000111

What I am looking for is a way to extract each bit individually lets say.

a boolean variable x = 1 then 1 then 1 then 0 then 0 ..

hence x takes values 1,1,1,0,0,0,1,1,1 one at a time.

it doesn't have to be a binary value it could also be hex.

How would you achieve this?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So you want to unpack an 8 bit binary byte into 8 boolean variables. (your example had 9 bits, but thats ok)

unsigned char packedbools;
unsigned char unpackedbools[8];
void unpack(void){
unsigned char n;
unsigned char msk;

  msk=0x01;
  for(n=0; n<8; n++){
    unpackedbools[n]=(packedbools & msk)==msk;
    msk <<= 1;
  }
}

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In assembler, you might put the value into a register, shift the register left one bit and test the overflow bit.
Rinse and repeat eight times.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

yep that works however the unpacked bools come out from least to most sig, I need them to come out from most significant to least.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
unpackedbools[n]=(packedbools & msk)==msk;
    msk <<= 1; 

From this code I understand that you AND binary value and mask which is initially 00000001 that stores the least significant bit in the array space 0.

I need the most significant to be stored in space 0.

Actually I could just unpack in reverse order :)

However is there a way to do it?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
unsigned char packedbools; 
unsigned char unpackedbools[8]; 
void unpack(void){ 
unsigned char n; 
unsigned char msk; 

  msk=0x80; 
  for(n=0; n<8; n++){ 
    unpackedbools[n]=(packedbools & msk)==msk; 
    msk >>= 1; 
  } 
} 

Order reversed.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
it doesn't have to be a binary value it could also be hex.
Irrelevant: binary, hex and decimal notations are for humans to read. To the CPU it is always binary.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Koshchi wrote:
Quote:
it doesn't have to be a binary value it could also be hex.
Irrelevant: binary, hex and decimal notations are for humans to read. To the CPU it is always binary.

yep just thought I'd make myself clear.

Guess most people know that already here 8)

Last Edited: Thu. Mar 7, 2013 - 09:41 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

How would you achieve this?

Is this homework? Is this a contest? What is the prize? Does smallest win? Fastest? Is a particular language required? Can the input value register contents be destroyed, or must a working copy be made? Is the destination registers or SRAM locations?

Oh, yeah--what is the purpose of this unpacking? Why can't the set of flags be used in-place?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
Quote:

How would you achieve this?

Is this homework? Is this a contest? What is the prize? Does smallest win? Fastest? Is a particular language required? Can the input value register contents be destroyed, or must a working copy be made? Is the destination registers or SRAM locations?

Oh, yeah--what is the purpose of this unpacking? Why can't the set of flags be used in-place?


Nope just needed it for my project, fast and efficient code is important.

The code previously suggested works.
Not sure if you have a better way to write it.

Language, normal C/C++ language.

Not sure about registers, no need for a copy.

binary_value = 0b10110101

bit_value = 1
then 0
then 1
then 1
then 0
then 1
then 0
then 1

as you can see the bit_value takes on value of each bit of the binary value one at a time from most significant to least significant bit.

If have a better way of writing the code than bobgardner please show us how you would do it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
If have a better way
Define "better".

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Define "better".

And also answer
Quote:

what is the purpose of this unpacking? Why can't the set of flags be used in-place?

How can I unpack thee? Let me count the ways...

-- One can loop as shown in the "benchmark" code
-- The loop can be unrolled
-- One can see how the compiler does it, and determine if that is "best".
(bitfield structure)
-- Put the 8 bits to a port, wire each bit to 8 other ports, read the port value (requires a 100-pin AVR model)

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think we are incredulous that such unpacking would be useful. Each bit can be individually tested in the source variable and a nonzero result can be used for a conditional branch. Why create an additional bit_value variable that contains only zero or one, i.e. what is special about 0x01?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My test for copying an input pin to a boolean variable is: Do I use it more than once? Lets say the variable is 'Power switch in ON position'. That might be used several times in a system model. You dont want any indicator lamps on the instrument panel unless the power switch is on.

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
unsigned char packedbools = 0b11001101;
      unsigned char unpackedbools[8];
      unsigned char n;
      unsigned char msk;
      msk=0x80;
      for(n=0; n<8; n++){
      unpackedbools[n]=(packedbools & msk)==msk;
      msk >>= 1;
      }

what is ==msk used for?

The code looks efficient to me, what would you improve?

theusch wrote:
Quote:

Define "better".

And also answer
Quote:

what is the purpose of this unpacking? Why can't the set of flags be used in-place?

I want to sequentially output the bits from most significant to least significant.
Not sure what you mean by the set of flags
could you elaborate a bit please.
theusch wrote:
How can I unpack thee? Let me count the ways...

-- One can loop as shown in the "benchmark" code
-- The loop can be unrolled
-- One can see how the compiler does it, and determine if that is "best".
(bitfield structure)
-- Put the 8 bits to a port, wire each bit to 8 other ports, read the port value (requires a 100-pin AVR model)


not sure if serious about that last part :shock:

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I can make a case for sending a bunch o packed booleans over a wire from an io system to a pc or something. Its 8 times faster than sending them unpacked.

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
what is ==msk used for?
You wanted the result to be either 0 or 1. If the result of the AND is equal to the mask, then the bit was 1 and therefore the result of the == is true (which results in 1). If not, then the result is 0.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
I want to sequentially output the bits from most significant to least significant.

Output the bits to where? The SPI hardware can do this.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I want to sequentially output the bits from most significant to least significant.

Like to a shift register? As mentioned, SPI can do that. Or bit-banged. No need to unpack.

Or for e.g. display as ASCII characters, like on a debug panel? I wouldn't think a few cycles one way or the other would matter.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

. Or bit-banged.

In fact your bitbang loop is going to look almost identical to the above anyway - you shift a bit across a mask byte from 0x80 to 0x01 or from 0x01 to 0x80 (depending on msb or lsb) and when the bit tests high you set the output data pin high and clock it while when the bit tests low you set the output data pin low and clock that. Something like:

#define DATA (1<<PB3)
#define CLK (1<<PB4)
unsigned char packeddata = 0b11001101; 
unsigned char n;
unsigned char msk;
DDRB |= DATA | CLK; // outputs 
msk=0x80;
for(n=0; n<8; n++){
   if (packeddata & msk) {
     PORTB |= DATA;
   }
   else {
     PORTB &= ~DATA;
   }
   PORTB |= CLK; // clock high
   PORTB &= ~CLK; // clock low
   msk >>= 1;
} 

As others have noted there was no need to unpack the bits into an array of 0/1's first - you just set the output data pin each time round the loop dependent on the 0/1 bit state at that msk position.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yeah But... what if he wasnt trying to send a byte bit by bit? What if he really wanted 8 booleans to use in logic expressions? You cant just say 'Thats stupid. No one has ever wanted to do that'.

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No am not trying to send the bits, In theory I would receive a byte and then break it down into bits one by one.

If there is a single line of code that does it then fine.

input = 0b10001000
mask = 0x80
output = (0b10001000 & mask)==mask
x = output
use x to turn led on or off
repeat for next bit and so on, storing values in an array is not at all a requirement for me.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Koshchi wrote:
Quote:
what is ==msk used for?
You wanted the result to be either 0 or 1. If the result of the AND is equal to the mask, then the bit was 1 and therefore the result of the == is true (which results in 1). If not, then the result is 0.

For the OP's benefit, an alternate approach is

unpackedbools[n]=(packedbools & msk) ? 1 : 0; 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What's wrong with ROR and ROL? :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is a dumb question but why use 'unsigned char' instead of 'uint8_t' or 'byte'.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

This is a dumb question but why use 'unsigned char' instead of 'uint8_t' or 'byte'.


'uint8_t' is a conspiracy to rid the world of old hunt-and-peck programmers by introducing an extra shifted character when coding, thus disturbing the muscle memory of veteran coders that can type 'unsinged char' without thinking. [typo intentional]

I'll bite, though--is there a standardized 'byte' type? If not, I'd propose calling 8-bits-used-as-flag a 'frog' type.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

This is a dumb question but why use 'unsigned char' instead of 'uint8_t' or 'byte'.

Some people may prefer to use "unsigned char" simply as it makes no reliance on a #include - it's natively supported by anything that calls itself a C compiler.

Also while stdint.h are great for determining the width of 16, 32 and 64 bit variables it is a very unusual C compiler for which unsigned char is not 8 bits so you aren't as reliant on the uint8_t guarantee.

As for typing. I personally prefer "uint8_t" to "unsigned char" as it's considerably less characters to type and I've kind of got used to operating the [Shift] key at this stage in my life ;-)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

...my typing finger muscle memory invariably types unit8_t :(
...thinking about setting a #define for it ;)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

yes but I have read that when making an array with Char it places a null in the last index. Not sure why that is but wouldn't that make unint8_t or byte a better data type, I suppose these don't place a null in the array.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

that can type 'unsinged char' without thinking. [typo intentional]

Yup. That should be 'unsung char', right? :wink:

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

That should be 'unsung char', right?

Two different uses. The unsinged char hasn't been burnt, while an unsung char gets no respect.

Don't get me started on the androgynous/hermaphroditic nature of a naked 'char'.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JollyMolly wrote:
yes but I have read that when making an array with Char it places a null in the last index. Not sure why that is but wouldn't that make unint8_t or byte a better data type, I suppose these don't place a null in the array.

No, this is not true. What is true is that standard C strings have a null (0 byte) at the end, but that would happen no matter how you defined the array.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

yes but I have read that when making an array with Char it places a null in the last index. Not sure why that is but wouldn't that make unint8_t or byte a better data type, I suppose these don't place a null in the array.

char foo1[] = "Hello"; // has NUL at end
unsigned char foo2[] = "world"; // has NUL at end
signed char foo3[] = "now is the"; // has NUL at end
uint8_t foo4[] = "time for all"; // has NUL at end
int8_t foo5[] = "good men"; // has NUL at end
char foo6[8] = "to come"; // has a NUL at end
char foo7[6] = "to the"; // no NUL at end

So whether you use char/usigned char/signed char (that is THREE different types by the way) or uint8_t/int8_t has no bearing on whether a literal string has a NUL on the end. If either no size is specified ([]) or a size is specified that allows room for it ([8]) then you get the NUL added. The only way to avoid it is to give the array a dimension that is the exact number of characters in the string literal so there is no room for the NUL to be added.

The reason C adds the NUL is so you can do things like:

char all[40];
strcpy(all, foo3);
strcat(all, foo4);
strcat(all, foo5);

How else could strcpy and strcat work if C didn't have some way to know where the strings end?

The same is true when you implement something like:

void uart_printstring(char * p) {
  while(*p) {
   uatr_putchar(*p++);
  }
}

Such a routine only works because the while() loop ends when it gets to NUL.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So the null is only added for literal stings or "something in double quotes" ?

Soo...

unsigned char numbers[] = {4,5,6,7,6};

will not have a NULL added?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

will not have a NULL added?

Correct. It's an artefact of using "something". Except in the special circumstance I highlighted the 'g' will be followed by 0x00 so it's easy for C (and you!) to find where "something" ends. Similarly if you use:

char text[] = { 'h', 'e', 'l', 'l', 'o' };

that too will not have NUL added but:

char text[] = { "hello" };

will.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yep I understand now.

But what will happen if you try to get the null value from the array?

Say

array[]= {"hello"};

Null is placed in index 5

so what value will

x = array[5]

return?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Null/0x00? What other value(s) >>would<< you expect?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just making sure, I read that trying to get values from undeclared arrays can return odd results.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I read that trying to get values from undeclared arrays can return odd results.

True enough--more like "undetermined" rather than "odd". You can index that array to 1234 if you care to--but the results are probably not what you intended.

However, that has little or nothing to do with the fragment that you posted, as there are 6 elements in the array and 5 is a legal subscript.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Just making sure, I read that trying to get values from undeclared arrays can return odd results.

They are talking about this:

char foo[8];

int main(void) {
  char bar[8];
}

In this code I can absolutely guarantee that foo[5] holds 0x00 and I absolutely guarantee that you cannot predict what bar[5] holds. Rather interestingly if I'd written:

char foo[8];

int main(void) {
  static char bar[8];
}

then in this case I could guarantee that both foo[5] and bar[5] hold 0x00.

C guarantees that uninitialised array space (and single variables) that are global or static will always hold 0x00 entry to main(). There is no guarantee whatsoever what a local/(aka "automatic") variable might hold when first created because they are created on the stack and something may have used that same space previously.