Pololu Robotics & Electronics
Menu
My account Comments or questions? About Pololu Contact Ordering information Distributors

Pointing to a struct


#1

Hello,
maybe this could be a topic more general than Wixel, but since I’m using that board, I post here. I apologise if administrators will have to move my post in a more appropriate section of the forum.

I want to optimize a radio packet for transmission; in order to store in it the largest amout of data, I defined a new type and a struct like this:

typedef struct {
		unsigned int value10bits :10;
} uint10;

typedef union typeConverter {
	uint16 intValue;
	struct {
		//little-endian bit order
		uint10 element;
		unsigned int padding :6;
	} bits;
} typeConverter;

typeConverter container;

the uint10 type allows me to store an adc reading (@ 10-bit resolution) and the union typeConverter allows me to manage it in a smart way.

The problem arises when I try to store those readings into a buffer obtained by txBuf = radioNetworkTxCurrentPacket() (radio_network is an advanced radio protocol that allows Wixels to create a mesh network; it work like radio_queue library).

This is the code which populates my buffer:

		uint10 temp10;

		uint32 XDATA * ptrTimeStamp = (uint32 XDATA *) &txBuf[4];
		uint10 XDATA * ptrData = (uint10 XDATA *) &txBuf[9];

		*(txBuf + 2) = param_dest_address;	//destination wixel address
		radioNetworkFillAddress(); 	        //allows radio_network to specify other routing info

		//timestamp
		*(ptrTimeStamp) = getMs();
		//T4CNT
		temp = T4CNT;
		*(txBuf + 8) = temp;

		//sampled data, obtained by ADC @ 10-bit resolution. They are stored in a queue
		i = 0;
		while (!isEmpty(&myQueue) && i < 12) {
			getItem(&myQueue, &container.intValue);
			temp10.value10bits=container.bits.element.value10bits;
			*(ptrData + i)->value10bits = temp10.value10bits;
			i++;
		}

When I try to compile the code, the line

*(ptrData + i)->value10bits = temp10.value10bits;

generates: error 27: Pointer required.

I made some attempts but I do not solved anything.

Can you suggest me something?

Thank you!


#2

[quote=“tapisge”]*(ptrData + i)->value10bits = temp10.value10bits;

generates: error 27: Pointer required.
[/quote]

Hello. The -> operator takes care of dereferencing the pointer, so the expression (ptrData + i)->value10bits is not a pointer and it is inappropriate to try to dereference it again using the asterisk. I think you can fix this by just removing the asterisk.

–David


#3

Thank you, David.
I’ve another question that is related with 10-bit structs as above, but also with the way the bits are transmitted by radio module of CC2511.

I prepare the radio buffer with this code (it’s only a chunk):

		i = 0;
		while (!isEmpty(&myQueue) && i < 12) { //TODO: Remove numerical constant
			uint10 temp10;
			temp10.value10bits=0;
			container.intValue=0;
			getItem(&myQueue, &container.intValue);
			temp10.value10bits=container.bits.element.value10bits;
			(ptrData + i)->value10bits = temp10.value10bits;
			i++;
		}

and in the receiver I extract transmitted data with this code:


typedef struct {
		unsigned int value10bits :10;
} uint10;

typedef union typeConverter {
	uint16 intValue;
	struct {
		//little-endian bit order
		uint10 element;
		unsigned int padding :6;
	} bits;
} typeConverter;

/* *** RADIO PDU STRUCT ***/
typedef struct {
	uint8 	length;
	uint8 	node;
	uint8 	destination;
	uint8 	source;
	uint32 	timestamp;
	uint8 	msFract;
	uint10 	sample[12]; //TODO: remove numerical constant
} radioPacket;
		for (i = 0; i < rxPacket->length - 8; i++) {
			typeConverter container;
			container.intValue=0;
			container.bits.element.value10bits = rxPacket->sample[i].value10bits;
			printf(" %5u", container.intValue);
		}

When print my data, it seems bits are in a different order with respect to the transmitted ones.


#4

Example: at every radio packet I send a queue of 12 10-bit values. I modified the code in order to send a constant arbitrary value (823, 0b1100110111) instead of sending samples from adc.

Instead of reading

In my console I read those values

   823   823   823   823   823   823   776     0     0   257   258   324
   823   823   823   823   823   823     8     0     0   257     2   324
   823   823   823   823   823   823   263     0     0   514   513     0
   823   823   823   823   823   823   263     0     0   257   514   324
   823   823   823   823   823   823   264     0     0   257     2   324
   823   823   823   823   823   823   776     0     0   514   513     0
   823   823   823   823   823   823   776     0     0   257   770   324
   823   823   823   823   823   823   264     0     0   257   514   324
   823   823   823   823   823   823   520     0     0   514   513     0
   823   823   823   823   823   823   776     0     0   257   514   324
   823   823   823   823   823   823   520     0     0   257   514   324
   823   823   823   823   823   823     8     0     0   514   513     0
   823   823   823   823   823   823   264     0     0   257   514   324
   823   823   823   823   823   823     8     0     0   257   514   324
   823   823   823   823   823   823   264     0     0   514   513     0
   823   823   823   823   823   823   520     0     0   257   514   324
   823   823   823   823   823   823     7     0     0   257   770   324

I cannot explain myself why constant zeros and why decreasing values for every received packet, and why I obtain also variable values… :imp:


#5

I do not see anything in the code you posted that would cause that behavior.

I did notice that your loop that prints the values doesn’t look quite right:

for (i = 0; i < rxPacket->length - 8; i++) {

If the rxPacket->length is a number of bytes, then a packet holding 12 samples would actually have a length of 32, which means your loop would print out 24 different values. The example output you showed only had 12 values though, and I am not sure why.

I suspect that sizeof(typeConverter) will actually be 3, but it looks like you were trying to make it be 2 because of the way you added 6 bits of padding.

Since the data at the beginning of the packet is fine and the data at the end of the packet is corrupted, I would look for issues where you might specify the length of the packet incorrectly when sending it, or maybe the length you are specifying is too long for the underlying radio library to handle. You should make sure you know what sizeof(radioPacket) is; I think it is 33 because each uint10 struct will take 2 bytes.

I suggest that you simplify your code as much as possible, and post the full source code of both apps here if you are still having issues. Also, you might try just using uint16 integers to hold your data instead of trying to use bit fields.

–David


#6

The reason why I use 10-bit values is to optimize transmission: In an area of 120 bit I would like to store 12 10-bit samples instead of 7 uint16 samples.

Maybe I will try different ways to solve my problem. I might enlarge the buffer size in my radio library; otherwise I might try to populate the buffer with a shifting procedure that allows me to optimize space usage without using structs. The second way is more difficult to implement but smarter, since I would not modify the radio library.


#7

You should be able to pack your 120 bits of data into 15 bytes, but you will have to do it a different way. Every struct (including a uint10) must occupy a whole number of bytes, and cannot start in the middle of a byte. One reason for that is that the C compiler needs to be able to produce pointers to such structs, and pointers are not designed to point at individual bits inside a byte. So when you write uint10 sample[12], that array actually takes 24 bytes.

I am not sure if it would work to just have 12 bit fields with 12 different names inside your radioPacket struct.

–David


#8

For the same reason, is it correct to imagine that if I built BIT myData[120] it would take 120 bytes?


#9

That is probably true. If you want to be sure, you can make a simple program that defines a struct like that and then prints sizeof(mystruct) to the USB virtual COM port.

–David