Electronics > Projects, Designs, and Technical Stuff

Making A Cylon Eye

(1/3) > >>

Lance:
I'm trying to make 8 leds run like a cylon eye. Because the leds cover two different port ranges, I decided to try and make a little bitfield which I could then set the ports with. It failed horribly.

The idea is to have 8 unsigned integers, one representing each light. Then just use some bitwise shifts to move the light around.

--- Code: ---void Cylon(void)
{
unsigned int counter=0;
unsigned long i=0;

struct light
{
unsigned int light0:1;
unsigned int light1:1;
unsigned int light2:1;
unsigned int light3:1;
unsigned int light4:1;
unsigned int light5:1;
unsigned int light6:1;
unsigned int light7:1;
}

union light_union
{
struct light x;
} Lights;

Lights.x=(0b00000000u);
}

--- End code ---

Actually trying to set the bits is being problematic, I get this error message:


--- Code: ---illegal conversion between types unsigned int -> struct light
--- End code ---
I'm not sure what to do here.

RayJones:
You are close, but not quite right! (as you've probably figured!)

You need to add an int to your union, and keep your struct as you have already.

Ala


--- Code: ---union light_union {
  int x;
  struct light bits;
} Lights;

--- End code ---

You can then access x as you desire, and the magic of the union will set the bits broadside as you desire, likewise read them back.

If you want change a bit, use


--- Code: ---Lights.bits.light0 = 1; (or 0)

--- End code ---

Lance:

--- Quote from: RayJones on February 20, 2011, 06:29:07 am ---You are close, but not quite right! (as you've probably figured!)

You need to add an int to your union, and keep your struct as you have already.

Ala


--- Code: ---union light_union {
  int x;
  struct light bits;
} Lights;

--- End code ---

You can then access x as you desire, and the magic of the union will set the bits broadside as you desire, likewise read them back.

If you want change a bit, use


--- Code: ---Lights.bits.light0 = 1; (or 0)

--- End code ---


--- End quote ---
I see. Could you please explain to me why this is necessary?

RayJones:
BTW, I've been coding for far too long, and still the union caught me with my pants down the other day.

I knew what I wanted to achieve, but still made minced meat of it.  :'(

The secret is each line in the union specifies a element, the largest element determines the end size of the union (space used in memory).
Other elements will occupy the same memory space, but be interpreted according to their type, ie a bit field in your application.

Other tricks could be


--- Code: ---union {
  int AsInt;
  float AsFloat;
}

--- End code ---

This allows you to write a float value, then grab the byte form equivalent for transfer/storage.

When digging down to byte level though you need to be careful of the endian order of your processor as to where the LSB lives in memory for a 16 or 32 bit value.

My personal fave is


--- Code: ---union {
  int Word;
  struct {
     char LSB;
     char MSB;
  } bytes;
}

--- End code ---

This is used to rip a 16 bit value into the HIWORD/LOWORD far more efficiently than the typical mask and shift operations used.
Once again, take care with the endianess of your processor.

RayJones:
I should also add, using int is processor specific as to how many bits it is.

The native register size of the processor is usually adopted.

ie for a 16 bit processor, ints will be 16 bits, likewise 32 bits for a 32 bit processor.
to control the sizes better, you should use shorts or longs (16 or 32)
char is invariably 8 bits, but not always!

Having said this, you should realise my examples above are flawed, instead of int I should use long in the float example, and short in the HIWORD/LOWORD example.

Navigation

[0] Message Index

[#] Next page

There was an error while thanking
Thanking...
Go to full version