What is the most economical way of extracting parts of a ul such as 11011011010001000011110111011010 , into variables
First 8bits
9th bit
Bits 10-14
Bits 15-24
Last 8bits
"most economical" is not a well-defined term. What do YOU mean by it?
Normally, you would present your method for accomplishing this, and then we would point out how to do it better.
So, how do YOU propose to proceed with this? I haven't seen any code yet.
The first and last 8 bits can be extracted efficiently with a union. The rest you can get with bit shifting and masking.
However, I think bit 24 is part of the top 8 bits. So check your numbers.
I'm not positive I did this right, but it's a starting point for discussion:
void setup() {
// put your setup code here, to run once:
unsigned long val = 0b11011011010001000011110111011010;
unsigned char first8;
bool ninth;
unsigned long tenTo14;
unsigned long fifteenTo24;
unsigned long last8;
Serial.begin(9600);
// 0b11011011010001000011110111011010;
first8 = val & 0b00000000000000000000000011111111;
ninth = (bool) (val & 0b00000000000000000000000100000000);
tenTo14 = (unsigned long) (val & 0b00000000000000000011111000000000) >> 9;
fifteenTo24 = (unsigned long) (val & 0b00000000111111111100000000000000) >> 14;
last8 = (unsigned long) (val & 0b11111111000000000000000000000000) >> 24;
Serial.println((unsigned char) first8);
Serial.println(ninth, BIN);
Serial.println((unsigned long) tenTo14);
Serial.println((unsigned long) fifteenTo24);
Serial.println((unsigned long) last8);
}
void loop() {
// put your main code here, to run repeatedly:
}
Hi, I would think of these:
first n bits would be (var)&((((typeof(var))1)<<n)-1)
9th (bit number 8) bit would be ((var)>>8)&1) or { if ((var)&(((typeof(var))1)<<9)) ... }
10 to 14: (((var)>>10)&0b11111)
...
The OP is numbering from 1 from the most significant end I think.
The commonest and thus least confusing numbering is 0 from the least significant end,
thus sign bit is 31, LSB is 0.
The union method of conversion is sensitive to the host endianess, and thus is not
portable (without conditional compilation at least). However on an 8-bit
microcontroller without a barrel-shifter its a lot faster than the alternative.
The most readable conversion, assuming the bit numbering is as I suspect would be:
unsigned long in = 0b11011011010001000011110111011010 ;
byte a = (in >> 24) & 0xFF ;
byte b = (in >> 23) & 1 ;
byte c = (in >> 18) & 0x1F ;
unsigned int d = (in >> 8) & 0x3FF ;
byte e = in & 0xFF ;
Such code makes it very clear which bits are going where, but would be slow on
an ATmega processor (all the operations are on longs which means a minimum of
4 instructions per operation).
econjack & MarkT , both are good answers, easily understood.
I'm transmitting NEC 2km downstream on a TTL Laser, i will use those 32bits to relay data now & not just turn objects on/off.
Node_TypeIO_Pin_Value_Master (REQUEST) Master to Node
Master_TypeIO_11111_Value_Node (ACK) Node to Master
Master_TypeIO_Pin_Value_Node (DATA) Node to Master
Node_TypeIO_11111_Value_Master(ACK) Master to Node
So, Thanks!
You could also use bit fields:
typedef struct
{
uint32_t
a : 8,
b : 1,
c : 5,
d : 10,
e : 8;
} myStruct_t;
...
uint32_t myVal = 0b11011011010001000011110111011010;
myStruct_t myStruct = *(myStruct_t*)&myVal;
Serial.println( myStruct.a, BIN );
Serial.println( myStruct.b, BIN );
Serial.println( myStruct.c, BIN );
Serial.println( myStruct.d, BIN );
Serial.println( myStruct.e, BIN );
Possibly use an union:
typedef struct
{
uint32_t
a : 8,
b : 1,
c : 5,
d : 10,
e : 8;
} myStruct_t;
union
{
uint32_t myVal;
myStruct_t myStruct;
} myUnion;
...
myUnion.myVal = 0b11011011010001000011110111011010;
Serial.println( myUnion.myStruct.a, BIN );
Serial.println( myUnion.myStruct.b, BIN );
Serial.println( myUnion.myStruct.c, BIN );
Serial.println( myUnion.myStruct.d, BIN );
Serial.println( myUnion.myStruct.e, BIN );
Another good answer Thanks. Answer was awesome!
Yes and the best part is, it's much faster (and also a bit more memory efficient) than bit shifting and masking..
That typedef should be:
typedef struct
{
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
unsigned int
a : 8,
b : 1,
c : 5,
d : 10,
e : 8;
#else
unsigned int
e : 8,
d : 10,
c : 5,
b : 1,
a : 8;
#endif
If you want it to work universally.
:o Cool Beans