I need to write a function that uses interface functions from other components to get individual values for year, month, day, hour, minute, second, and then pack those values into a 5-byte message payload and provide it to another component by using an unsigned char pointer as function parameter. The payload structure is strictly defined and must look like this:
| | bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 |
| -------------- | -------------- | -------------- | --------------| --------------| --------------| --------------|-------------- |-------------- |
| byte 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | year |
| byte 1 | year | year | year | year | year | year | month | month |
| byte 2 | month | month | day | day | day | day | day | hour |
| byte 3 | hour | hour | hour | hour | minute | minute | minute | minute |
| byte 4 | minute | minute | second | second | second | second | second | second |
My current approach is:
void prepareDateAndTimePayload(unsigned char * message)
{
unsigned char payload[5] = {0};
unsigned char year = getYear();
unsigned char month = getMonth();
unsigned char day = getDay();
unsigned char hour = getHour();
unsigned char minute = getMinute();
unsigned char second = getSecond();
payload[0] = (year & 0x40) >> 6u; //get 7th bit of year and shift it
payload[1] = ((year & 0x3F) << 2u) | ((month & 0xC) >> 2u); //remaining 6 bits of year and starting with month
payload[2] = ((month & 0x3) << 6u) | ((day & 0x1F) << 1u) | ((hour & 0x10) >> 4u); //...
payload[3] = ((hour & 0xF) << 4u) | ((minute & 0x3C) >> 2u);
payload[4] = ((minute & 0x3) << 6u) | (second & 0x3F); //...
memcpy(message, payload, sizeof(payload));
}
I'm wondering how I should approach extracting the particular bits and packing them into a payload, so they match the required message structure. I find my version with bit masks and bit shifting to be messy and not elegant. Is there any better way to do it?
Look at your code with its various magic numbers. Now look at this code below. The compiler will optimise to use registers, so the extra clarity is for the human readers able to see and check that all makes sense.
void prepareDateAndTimePayload(unsigned char msg[5])
{
unsigned char yr = 0x7F & getYear() - bias; // 7 bits
unsigned char mn = 0x0F & getMonth(); // 4 bits
unsigned char dy = 0x1F & getDay(); // 5 bits
unsigned char hr = 0x1F & getHour(); // 5 bits
unsigned char mi = 0x3F & getMinute(); // 6 bits
unsigned char sc = 0x3F & getSecond(); // 6 bits
// [4] mmss ssss
msg[4] = sc; // 6/6 bit sc (0-59)
msg[4] |= mi << 6; // lo 2/6 bit mi (0-59)
// [3] hhhh mmmm
msg[3] = mi >> 2; // hi 4/6 bit mi (0-59)
msg[3] |= hr << 4; // lo 4/5 bit hr (0-23)
// [2] MMDD DDDh
msg[2] = hr >> 4; // hi 1/5 bit hr (0-23)
msg[2] |= dy << 1; // 5/5 bit dy (0-31)
msg[2] |= mn << 6; // lo 2/4 bit mn (1-12)
// [1] YYYY YYMM
msg[1] = mn >> 2; // hi 2/4 bit mn (1-12)
msg[1] |= yr << 2; // lo 6/7 bit yr (0-127)
// [0] 0000 000Y
msg[0] = yr >> 6; // hi 1/7 bit yr (0-127)
}
The OP refers to one side of a send/receive operation.
This proposal is based on the idea that both sides of that translation are amenable to revision.
It does not address the OP directly, but provides an alternative if both sides are still under development.
This requires only single byte data (suitable for narrow processors.)
Observation:
Oddly packing 6 values into 5 bytes with error prone jiggery-pokery.
Hallmark of a badly thought-out design.
Here is a reasonable (and cleaner) alternative.
| | b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0 |
| ------ | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | yr max 127 from bias
| byte 0 | yr3 | yr2 | yr1 | yr0 | mo | mo | mo | mo | max 12
| byte 1 | yr6 | yr5 | yr4 | dy | dy | dy | dy | dy | max 31
| byte 2 | | | | hr | hr | hr | hr | hr | max 23
| byte 3 | | | mi | mi | mi | mi | mi | mi | max 59
| byte 4 | | | sc | sc | sc | sc | sc | sc | max 59
And, in code:
typedef union {
uint8_t yr; // 7 bits valid. bias + [0-127]
uint8_t mo; // 1-12. 4 bits
uint8_t dy; // 1-31. 5 bits
uint8_t hr; // 0-23. 5 bits
uint8_t mn; // 0-59. 6 bits
uint8_t sc; // 0-59. 6 bits
} ymdhms_t;
void pack(unsigned char pyld[5], ymdhms_t *dt)
{
// year biased into range 0-127 (eg 2022 - 1980 = 42 )
dt.yr -= bias;
pyld[0] = dt->mo | (dt->yr & 0x0F) << 4; // mask unnecessary
pyld[1] = dt->dy | (dt->yr & 0x70) << 1;
pyld[2] = dt->hr;
pyld[3] = dt->mn;
pyld[4] = dt->sc;
}
void unpack(unsigned char pyld[5], ymdhms_t *dt)
{
dt->mo = pyld[0] & 0x0F;
dt->dy = pyld[1] & 0x1F;
dt->hr = pyld[2];
dt->mn = pyld[3];
dt->sc = pyld[4];
dt->yr = bias + pyld[0] >> 4 + pyld[1] >> 1;
}
One might even ask if "shrinking 6 bytes to 5" is worth the effort when the useful bit density only rises from 69% to 82%.
If you want to write a portable program, then your current implementation is pretty much the way you have to do it. You can make it a bit easier on the eyes by defining some macros to do handle the shifting and masking for you, but that's about it.
Using bitfields, you can offload most of that work to the compiler. Beware though that the compiler is free to implement bitfields in pretty much any way it wants. The resulting memory layout is not always portable between compilers - or even between ISAs using the same compiler.
As an example from the Linux kernel, here you can see how care must be taken to make sure that the CPU's endianness is taken into consideration, for example:
struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 ihl:4,
version:4;
#elif defined (__BIG_ENDIAN_BITFIELD)
__u8 version:4,
ihl:4;
#else
#error "Please fix <asm/byteorder.h>"
#endif
__u8 tos;
__be16 tot_len;
__be16 id;
__be16 frag_off;
__u8 ttl;
__u8 protocol;
__sum16 check;
__be32 saddr;
__be32 daddr;
/*The options start here. */
};
Whatever is chosen, code for 1) portable correctness, 2) clarity and 3) ease of maintenance.
Avoid premature optimization.
OP's code looks like a reasonable way to solve the issue - especially for narrow processors, yet it is challenging to review.
Perhaps use a wider type for the in-between part and let the compiler emit efficient code:
uint64_t datetime =
((uint64_t) getYear() << 26) |
((uint32_t) getMonth() << 22) |
((uint32_t) getDay() << 17) |
((uint32_t) getHour() << 12) |
( getMinute() << 6) |
( getSecond() << 0);
payload[0] = datetime >> 32;
payload[1] = datetime >> 24;
payload[2] = datetime >> 16;
payload[3] = datetime >> 8;
payload[4] = datetime >> 0;
or maybe end with
datetime = htob64(datetime);
memcpy(message, &datetime, 5);
Could add mask in like getMonth() --> (getMonth() && 0x0Flu) if concerned about out of range get function values.
Related
Sorry for the non descriptive title - I wasn't sure how to pose this in one line.
I have a data structure, where I have two values: one 14-bit, one 10-bit. I want to be able to access them as bytes in a union. I have the following:
struct test
{
union
{
struct
{
unsigned int a : 14;
unsigned int b : 10;
} fields;
struct
{
unsigned char i0;
unsigned char i1;
unsigned char i2;
} bytes;
} id;
};
Now, when I assign 1 to the value at bytes.i2, I would expect the value at values.b to also assume the value 1. But the value in values.b is actually bytes.i2 shifted left by 2 bits.
int main()
{
struct test x;
x.id.bytes.i2 = 1;
printf("%d", x.id.fields.b); // OUTPUTS 4
return 0;
}
I must be missing some basic principle here, any insight would be helpful!
In little endian, packed structs:
fields a |b
bytes i0 |i1 : |i2
BITS 00000000|000000|00|10000000 i2 = 1; b = 4
BITS 00000000|000000|10|10000000 i1 = 64; b = 1
INDEX 01234567|890123|45|67890123
0 1 2
As you can see b = 0b00000100 (4)
The exact layout and ordering of bitfields in a struct is entirely up to the implementation.
On a little endian machine, the layout of the union most likely looks like this:
|a |b a |b |
|7 6 5 4 3 2 1 0|1 0 d c b a 9 8|a 9 8 7 6 5 4 3|
| i0 | i1 | i2 |
-------------------------------------------------
| | | | | | | | | | | | | | | | | | | | | | | | |
-------------------------------------------------
In this layout, we can see that the 8 low order bits of a are in the first byte, then the 6 high order bits of a and the 2 low order bits of b in the second byte, followed by the high order 8 bits of b in the third byte. This explains the result you're seeing.
Little endian machine will typically also have the bits in little endian format, so if you reverse the order of the bits in each byte above, reflecting the physical representation instead of the logical representation, you can see that the bits of each bitfield are contiguous.
I am trying to understand how Bitwise operators work in C, but I have an misunderstanding about the << operator.
I have the following code:
#include <stdio.h>
int Add(int x, int y);
int Add(int x, int y)
{
while ( y != 0 ) /// Iterate till there is no carry
{
int carry = x & y; /// carry now contains common set bits of x and y
x = x ^ y; /// Sum of bits of x and y where at least one of the bits is not set
y = carry << 1; /// Carry is shifted by one so that adding it to x gives the required sum
}
return x;
}
int main( void )
{
printf( "%d", Add( 13, 17 ) );
return 0;
}
If I understand correctly works like this:
First Iteration:
|=======================================|
| |
| while ( y != 0 ) |
| while ( 17 != 0 ) |
| while ( 10001 != 00000 ) |
| |
| c = x & y; |
| 1 = 13 & 17 |
| 00001 = 01101 & 10001 |
| |
| x = x ^ y |
| 28 = 13 ^ 17 |
| 11100 = 01101 ^ 10001 |
| |
| y = c << 1 |
| 17 = 1 << 1 |
| 10001 = 00001 << 00001 |
| 00010 = 00001 << 00001 |
| |
|=======================================|
Second Iteration:
|=======================================|
| |
| while ( y != 0 ) |
| while ( 2 != 0 ) |
| while ( 00010 != 00000 ) |
| |
| c = x & y; |
| 0 = 28 & 2 |
| 00000 = 11100 & 00010 |
| |
| x = x ^ y |
| 30 = 28 ^ 2 |
| 11110 = 11100 ^ 00010 |
| |
| y = c << 1 |
| 2 = 0 << 1 |
| 00010 = 00000 << 00001 |
| 00000 = 00000 << 00001 |
| |
|=======================================|
Then Y becomes 0 and X returns 30.
Now in the following code I have an issue:
#include <stdio.h>
int main( void )
{
int x = 13;
int y = x << 1; /// 11010 = 01101 << 00001
x = 0 << 1; /// 00000 = 00000 << 00001
printf("y = %d\n", y ); /// 26 | 11010
printf("x = %d\n", x ); /// 26 | 11010
return 0;
}
Here if I understand right we shift all bits one to the left:
int y = x << 1; /// 11010 = 01101 << 00001
But what exactly happens here:
x = 0 << 1; /// 00000 = 00000 << 00001
Does x get cleared and filled with the rezult of 0 << 1 ?
Does x get cleared and filled with the rezult of 0 << 1 ?
x is just assigned the value of the expression 0 << 1. Zero left or right shifted by any amount remains 0.
So this means that the representation of the First and Second Iteration is correct?
It is correct, except that substitution of the old values of variables (on the lhs) is a bit confusing as in the following cases.
17 = 1 << 1
10001 = 00001 << 00001
and
2 = 0 << 1
00010 = 00000 << 00001
Instead depict it as:
y = 1 << 1
y = 00001 << 00001
and
y = 0 << 1
y = 00000 << 00001
n << k is actually n * (2^k) as long as you have enough bits available to keep all of the resulting bits. So 0 << k is 0 * (2^k) = 0 whatever the (positive integer) value of k is.
Note that for usual 32 bit integers, a number on p = 17 bits or more, like 65537 (0x0001_0001), will stop behaving like the multiplication once k is greater or equal to (32+1)-p = (32+1)-17 = 16, as for example 65537 << 16 is 0x1_0001_0000 which is using 33 bits and is truncated to 0x0001_0000 = 65536.
With 65536 << 15 you may also start having strange results as the result, 0x1000_0000, is changing the left most bit, which is the sign bit if you're not using unsigned values...
U32 BitMap[6] /* 6 words for 96 persons*/
How to make a program having loop to Read 6 words in above bitmap, which we have to read 2 bits per person and store person id and result in tPersonMsg
/* 2 Bits representing 00-> default value, 01->Command Successful, 10->Command Failed
* | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
* |<Pr15>|--------------------------------------------------------------------------------------------------------------------------------------|<Pr2>|<Pr1>|<Pr0>|
* | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
* |<P31>|--------------------------------------------------------------------------------------------------------------------------------------|<P18>|<P17>|<P16>|
--- similarly for 96 persons*/
to get the result of the persons for which command has failed in following structure.
typedef enum eFinalResult {
Succ= 0,
Fail = 1,
noResponse = 2,
} eFinalResult ;
typedef struct {
U32 Person_Id;
tFinalResult Person_Result;
} tResult;
typedef struct {
U32 NumPersons;
tResult Result[32];
} tPersonMsg;
I am not here to annoy anybody , I am a beginner in C programming
Till now I am trying to make program as follows:
for (i=0; i<6; i++) /* Loop for 6 words*/
{
k = 0;
t= 0x3;
for (j=0; j<31; j+2) /* Loop for bits to reach even position like 0th bit,2nd bit,4th ...and so on*/
{
bits = (a[i] & t) >>j;
k++;
if (a[i] == 2)
{
Command Failed
Person Id = j/2;
}
t = t<<2;
}
}
You have observed that six, 32 bit words are required to hold the data for 96 people: 96 people x 2 bits per person = 192 bits of data, and 192 / 32 = 6 words to hold them.
You can also see that one word will contain 32 / 2 bits per result = 16 results.
So, to find the correct word you divide the person's ID by 16 and the remainder is the 'index' of their result bits within the word. Use the index multiplied by 2 (the number of bits in each result) to shift the word containing the result right, so that the correct result bits are in the least significant position and mask out the remaining bits to obtain the result.
static const U32 BITS_PER_RESULT = 2;
static const U32 RESULTS_PER_WORD = 32 / BITS_PER_RESULT;
static const U32 RESULT_MASK = 0x3;
// The following line is commented out because, although implemented in
// several compilers, it is not part of the C standard (at the moment).
/*static const U32 RESULT_MASK = 0b11;*/
tResult FindResultForPerson(U32 personId)
{
// Find the word in the results array that contains the relevant bits.
U32 resultBits = BitMap[personId / RESULTS_PER_WORD];
// Shift the result word right so that the required bits are in the
// least significant bit position.
resultBits >>= ((personId % RESULTS_PER_WORD) * BITS_PER_RESULT);
// Mask out any more significant bits to leave only the required result.
return resultBits & RESULT_MASK;
}
At some point you will want to ensure that the value passed to the function in personId is not out of range and that the BitMap array contains correctly formatted and valid data, but that's further down the line...
For one bit, for the case when char == 8 bits.
int get1bit(unsigned char *array, int bitpos)
{
int res = array[bitpos >> 3];
res >>= (bitpos & 0x07);
return(res & 0x01);
}
if The real question is to get the value of the two bits at any position.
the answer would be to prepare the mask.
n&(n-1) would always check the value of the last bit(depends on the Arch of the processor also).
or the easy step would be to use a mask of max 32 bits or 64 bits (again depends on the ARCH).
Stackoverflow has many questions related to Masking and get the value of the bits.
Here is a program to swap two numbers with out using temporary variable and using shifting operations:
#include <stdio.h>
#include <conio.h>
int main(void)
{
int a,b,i,j;
clrscr();
printf(“Enter two integers: “);
scanf(“%d%d”,&a,&b);
printf(“a=%d,b=%d\n”,a,b);
for(i = 0; i < 16; i++)
{
if((a & (1 << i)) ^ (b & (1 << i)))
{
a = a ^ (1 << i);
b = b ^ (1 << i);
}
}
printf(“a=%d,b=%d”,a,b);
getch();
return 0;
}
My question is what is significance of 1 in this program?
I know the method of xoring that works as follows
a = a^b;
b = a^b;
a = a^b;
but I don't know how above program works?
It toggles each bit if only one is set.
c = a & (1 << i) = true if the ith bit of a is set
d = b & (1 << i) = true if the ith bit of b is set
| c | d | Action | c' | d' |
-------------------------------------
| 0 | 0 | Do nothing | 0 | 0 |
| 0 | 1 | Toggle the bits | 1 | 0 |
| 1 | 0 | Toggle the bits | 0 | 1 |
| 1 | 1 | Do nothing | 1 | 1 |
1 has one bit on the rightmost position set. 1<<i has one bit on place i set. This program loops through each bit, and swaps them if they are different.
a&(1<<i) tests if a has bit i set.
((a&(1<<i))^(b&(1<<i))) tests if bit i in a and b are different.
a=a^(1<<i) toggles bit i.
It's similar to the XOR trick, but swaps only a single bit at a time and only if this bit actually differs in a and b.
1<<i has bit i set to 1 and all other bits 0.
Also, this does not swap two numbers without using a temporary variable. It uses the temporary i.
I am attempting to do the following in c:
unsigned int mask;
unsigned int previous;
unsigned int new;
unsigned int out;
for( int i = 0; i < 8; ++i )
{
bool bit_set = GET_BIT( mask, i );
// If the mask bit is true, use the new bit, otherwise use the previous bit
SET_BIT( out, i, GET_BIT( bit_set ? new : previous, i ) );
}
However I think there may be an easier and quicker way using bitwise operations. I have the truth table but I don't know how to get the expression I need.
Truth table is:
m | p | n | o
0 | 0 | 0 | 0
1 | 0 | 0 | 0
0 | 1 | 0 | 1
1 | 1 | 0 | 0
0 | 0 | 1 | 0
1 | 0 | 1 | 1
0 | 1 | 1 | 1
1 | 1 | 1 | 1
How would I go about working this out?
Use Karnaugh Map - there is a solver available online. Pick "three values", enter the expected results for all eight combinations, and use the expression the solver produces:
F(m, p, n) = (p & !n) | (m & n)
EDIT : You can expand this solution to do the whole byte at once, rather than doing it one bit at a time, by using the ~ bitwise NOT operator:
result = (mask & new) | (~mask & previous);
If the mask bit is true, use the new bit, otherwise use the previous
bit
The natural way to express this (to me) is (mask & new) | (~mask & previous). That is to say, mask corresponding bits from new and previous, and add them together using OR.