boolean programming code help?

40 posts / 0 new
Author
Message

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?

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

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.

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.

```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?

```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.

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.

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

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.

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.

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

Regards,
Steve A.

The Board helps those that help themselves.

Quote:

Define "better".

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.

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?

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

```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".

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:

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

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.

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.

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.

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.

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

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
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.

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; `

What's wrong with ROR and ROL? :)

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

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.

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 ;-)

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

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.

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]

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.

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.

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.

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?

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.

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?

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.

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

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.

Quote:

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

```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.