Structure exercise implementation
In this article, let’s code the below exercise packet field extraction program.
Exercise:
Write a program to decode a given 32bit packet information and print the values of different fields. Create a structure with member elements as packet fields as shown below.
First I created a variable of uint32_t packetValue. And then I am getting that value from the user using scanf. We are inputting the number in hex format, so for the scanf I use %X.
#include<stdint.h> #include<stdio.h> struct Packet { uint8_t crc; uint8_t status; uint16_t payload; uint8_t bat; uint8_t sensor; uint8_t longAddr; uint8_t shortAddr; uint8_t addrMode; }; int main(void) { uint32_t packetValue ; printf("Enter the 32bit packet value:"); scanf("%X",&packetValue);
After that, I created the packet structure.
CRC is 2 bits, but I have to use the uint8 variable type. That is sufficient to store two bits.
And here the status is stored in uint8. Payload is 12 bits, so I have selected uint16 for that, like that I have used the data types.
Later we can see how we can optimize the bits using the bit fields.
After that, I created a structure variable packet. Let’s start decoding.
struct Packet packet; packet.crc = (uint8_t) (packetValue & 0x3); packet.status = (uint8_t) ( (packetValue >> 2) & 0x1 ); packet.payload = (uint16_t) ( (packetValue >> 3) & 0xFFF ); packet.bat = (uint8_t) ( (packetValue >> 15) & 0x7 ); packet.sensor = (uint8_t) ( (packetValue >> 18) & 0x7 ); packet.longAddr = (uint8_t) ( (packetValue >> 21) & 0xFF ); packet.shortAddr = (uint8_t) ( (packetValue >> 29) & 0x3 ); packet.addrMode = (uint8_t) ( (packetValue >> 31) & 0x1 ); printf("crc :%#x\n",packet.crc); printf("status :%#x\n",packet.status); printf("payload :%#x\n",packet.payload); printf("bat :%#x\n",packet.bat); printf("sensor :%#x\n",packet.sensor); printf("longAddr :%#x\n",packet.longAddr); printf("shortAddr :%#x\n",packet.shortAddr); printf("addrMode :%#x\n",packet.addrMode);
First, calculate CRC. The CRC is the first 2 bits.
packet.crc = (uint8_t)(packetValue & 0x3); Here, I am interested in only the last two bits, that’s why I’m zeroing out all the other bits.
And after that, status. Status is 1 bit, but it comes in the second position.
How do you extract that? For that what you have to do is, let’s take the packet value and right shift by 2. Now that bit comes to the least significant bit position, and after that & 0x1. That’s it.
packet.status = (uint8_t)((packetValue >> 2) & 0x1);
And next is the packet payload. Payload starts from 3, so you have to shift by three. Now, you have to extract the first 12 bits. So, to extract 12 bits, what should be the mask value? F is 4 once, another F 8 once, and another F 12 once. So, FFF. Here the payload is of type uint16. So, I have to use uint16.
packet.payload = (uint16_t)((packetValue >> 3) & 0xFFF);
The next one is BAT value. Now you have to shift at the right-hand side and the shift amount. You can calculate by adding previous bit widths. So, 12 plus 1 plus 2, 15. Here it is 15.
And you have to extract the first 3 bits. So, 7.
packet.bat = (uint8_t)((packetValue >> 15) & 0x7);
Next is the sensor. You have to shift this value by 18.
packet.sensor = (uint8_t)((packetValue >> 18) & 0x7);
After that, to extract the long address, you have to shift this value by 21 and the width is 8 bits. That’s why, I’m using FF as a mask value, so this is the long address.
packet.longAddr = (uint8_t)((packetValue >> 21) & 0xFF);
And to extract the short address you have to shift by 29 and the short address is 2 bits.
packet.shortAddr = (uint8_t)((packetValue >> 29) & 0x3);
And to address the address mode you have to shift by 31. That’s why I would use three here. After that to get the address mode packet values should be shifted by 31.
packet.addrMode = (uint8_t)((packetValue >> 31) & 0x1);
To print a 0x, you can give the # symbol in between %X. That would add to the zero cross symbol for the hex value, as shown above.
The Output is shown in Figure 2. Here it is printed in hex.
Let’s print the size of this structure, the code is shown below. I think the sizeof this structure may be 9 or 10.
printf("Size of struct is %I64u\n",sizeof(packet)); while(getchar() != '\n'); getchar(); return 0; }
Size of the packet code
The output shows 10 bytes, as shown in Figure 3. So, it consumes 10 bytes in memory.
Basically, the packet value that you entered was a 4-byte value (32 bits). And to store that in a structure format using various member elements you lost 6 bytes, isn’t it? It is taking 10 bytes for this structure.
So, now we have to find out if is there any technique by which we can minimize this memory consumption. The answer for that is using bit fields with the structure, and that is our next discussion.
In the next discussion, we’ll use the same structure, the same member element, but we will reduce the size of the struct. And I will show you how to do that in the following article.
FastBit Embedded Brain Academy Courses
Click here: https://fastbitlab.com/course1