unions in C

This is a question for any embedded C experts. If you declare a union, is that handled completely by the compiler? One thing that I like about PBASIC is the way you can access bits and nibbles of a byte directly. If you declare a union in c like this:


union pbyte {
	struct {
		unsigned b0:1;
		unsigned b1:1;
		unsigned b2:1;
		unsigned b3:1;
		unsigned b4:1;
		unsigned b5:1;
		unsigned b6:1;
		unsigned b7:1;
	};
	struct {
		unsigned nib0:4;
		unsigned nib1:4;
	};
	unsigned char byte;
};

will there be a performance hit? According the the C specs it will allocate enough room for the biggest item, so the total size should only be a byte. Is it better practice in the long run to just write macros to get/set/clear the bits instead?

Unions should be handled entirely by the compiler so there really shouldn’t be too large of a performance hit. However, I’d recommend using macro’s to manipulate bits using binary math (and, or, xor, not, etc.). After all, that’s all the compiler is doing and you may be able to optomize it better than the compiler does.

Matt

One of the things I HOPED Innovation First woud do with the C controller was to use signed charaters types for joystick and PWM data.

Basically, this would allow for easy scaling, etc.

0 = off
-127 = full reverse
127 = full forward

It is beautiful and elegant for many reasons.

BUT…

I would rather not just waste the variable space to have 16 inputs from the OI and 16 PWM outputs more or less wasted just because I want to use an elegant solution.

I would like to use unions to allow these modified PWM outputs and Joystick values to be stored in the same location as the unsigned character variables that Innovation First defines.

To use this I would just do something like this just after the getdata statement:
p1_y.DrJoe = p1_y.InnovationFirst - (signed char) 127

The (signed char) is a cast that is required allow the math on the right side of the equation to be performed using signed math.

Also, just before the PWM output statements, I would have to do something like this:
pwm01.InnovationFirst = pwm01.DrJoe + (unsigned char) 127

Again, the cast is needed to get the math work out right (actually, now that I think about it, I may need to put in an (unsigned int)… …I have to go look it up or try it out)

Anyway, I have 2 questions for Union Geeks…

In order to do this, I will have to dig into the structure that Innovation First defines for the recieve data as well as the #define statement where they define p1_y. I will also have to redefine the transmit data structure and its associated macros.

#1 Will this screw up the library functions (which we don’t have access to) which access the same structure?

#2 Is there a better way to do this?

Do tell.

Joe J.

Here is how you actually can do it: (Yes I’ve tried this)

In ifi_default.h change the rc_pwm** variables to signed chars

then, right before PutData(),

pwm01 += 127;
pwm02 += 127;

A similar thing should work for the inputs (don’t have a rc unit hany to try)

I am going to try it tonight.

I am a little disturbed by this but I think I will settle down after I break out my Kernighan & Ritchie.

Here is the nub of my concern:

Are we creating processor/compiler specific code (i.e. not portable code)? The library functions for getting and putting data are expecting unsigned character types. The fact that we are sending signed character types to them seems not right somehow (yes I know that we are actually storing an unsigned character in them when we send the data – the += 127 bit, but it still creeps me out a bit).

Anyway, I will have to try it out.

Thanks for the help.

Joe J.

It will matter in some cases what you use and not matter in other cases.

Let me try and explain why. A signed byte and an unsigned byte represent the numbers from 0 to 127 in exactly the same manner. The values from 128 to 255 in an unsigned byte are represented as the numbers from -128 to -1 in a signed byte. Basically, 255 is represented in the same manner that -1 is represented. Now, for 0 to 255 output values, you don’t want this to occur.

Now, as long as you correctly subtract 127 and then add 127, there should be no difference in the ending output as long as simple arithmetic is used (addition, subtraction, multiplication, and division). That’s a function of binary arithmetic and not dependent on a certain processor. Basically, the code should be portable in that case. If you’re using bitwise operations, I’d be a bit more careful.

My suggestion is to use a a word variable for calculations and then cast it to an unsigned char for output. It will waste a bit of RAM space but it will make sure there’s enough room for all variable calculations.

Matt