CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Possible to use partial 16it Ints in a struct ?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
James B
Guest







Possible to use partial 16it Ints in a struct ?
PostPosted: Mon Mar 06, 2006 1:27 pm     Reply with quote

I have a message coming from I2C from another PIC that has 8 bytes in it, split into 4 16bit signals, the first 5 bits are unused, the next is the sign bit, then 10 bits for the actual signal.

The binary looks like this:
00000 1 0000111100 == +60

I want to use structs to easily use these.


struct MySignal {

int16 signal:10;
int1 signbit:1;
int void_rest:5;
};

I get the compiler error "Number of bits out of range".

If this doesn't work, is it possible for me to split up an int16 ???
treitmey



Joined: 23 Jan 2004
Posts: 1094
Location: Appleton,WI USA

View user's profile Send private message Visit poster's website

PostPosted: Mon Mar 06, 2006 1:53 pm     Reply with quote

The error is because you can only use the " : " to break down a int8 value.

Soooo.. If I were you I would use shifts and masks to make the value.
Code:
void main(void)
{
int32 temp;
int16 signal;
int1 sign;
sign=(temp&0b0000010000000000)>>11;//mask off all but sign and shift it
signal=temp&0b0000001111111111;//mask off all but signal
  fprintf(DEBUG,"%u   %lu!\n\r",sign,signal);
  while(1)
  {
  }
}

or you could make a signed int16.. make signal and sign as above and do a

if (sign) signal*=-1;
James B
Guest







Oh,
PostPosted: Mon Mar 06, 2006 2:00 pm     Reply with quote

Well, that solves that.

I was hoping to avoid int32 and shifts, it seemed a struct would faster. Esp. since this is going to be a very repetitive move. And my micro is running pretty slow to save power.

Too bad the : doesn't work for int16.
James B
Guest







PostPosted: Mon Mar 06, 2006 4:19 pm     Reply with quote

Ok, I settled on the fact I'de have to shift the data around, but now I'm having a similar problem with my pointer / struct. This is a little of topic with my last post but.....

The one I posted before just had 2 bytes in it, but my real one setup has two different stucts of 8.

My idea was to use the values returned by my getd(int *data, &type) function and apply whatever struct was appropriate. For example

This are my two structs :

Code:

struct Signal_Type1 {
int16 data1;
int16 data2;
int16 data3;
int16 data4;
};

and
Code:

struct Signal_Type2 {
int8 data1;
int8 data2;
int8 data3;
int8 data4;
int8 data5;
int8 data6;
int8 data7;
int8 data8;
};

//and then the pointers....
struct Sinal_Type1 *ptr1;
struct Sinal_Type2 *ptr2;


When I read in data of type2 I wanted to set a pointer to the data and then I could access the values in data with something like "ptr2.data5=x" which modifies some of data. This all really so I can addess data elememts by meaningful names.

But for the live of me I can not figure out the syntax for this.... If I can't figure it out in a bit I'll make a post about it.

Thanks
Guest








PostPosted: Mon Mar 06, 2006 4:24 pm     Reply with quote

It is worth perhaps looking at some other ways of doing this. For instance:
Code:

#define SIG_MASK (0x3FF)
#define SIGN_MASK (0x400)
int16 value;
int1 sign;
int16 signal;

//To save signal
value = (value & SIGN_MASK)|signal;

//To retrieve signal
signal=value & SIG_MASK;

//To set sign
value = value | SIGN_MASK;

//To clear sign
value = value & SIG_MASK;

//To get sign
sign = value && SIGN_MASK;

These involve no rotations, and will be pretty much what the compiler would have to code to handle an int16 bit access mode. They should be only a handful of instructions each.

Best Wishes
Ttelmah
Guest







PostPosted: Mon Mar 06, 2006 4:37 pm     Reply with quote

Beware, that array operations (and pointers), take a relatively large number of operations...
Your declaration syntax should be OK, except the declaration you have posted, has the structure name misdeclared. To access an element in a pointer to a structure, use the '->' declaration, instead of the '.' declaration. You also need to actually declare the structure somewhere, and set the pointer to address it. So:
Code:

struct Signal_Type2 {
int8 data1;
int8 data2;
int8 data3;
int8 data4;
int8 data5;
int8 data6;
int8 data7;
int8 data8;
};

//You need to actually _declare_ the structure. So far you have only created a name.

struct Signal_Type2 second_struct;

//Alternatively make a space the size required, using the memory
//access functions.

//Now make your pointer.

struct Signal_Type2 *ptr2;

//Now in the main code, make the pointer access the physical structure

ptr2=second_struct;

//Then you can access an element as:

second_struct.data8

//or as

ptr2->data8


Best Wishes
James B
Guest







PostPosted: Mon Mar 06, 2006 5:24 pm     Reply with quote

I see now, except for one thing. I'm doing this so that I can always use my getd(*data) which returns my *data with 8 new elements and also link structs to it so that I can access the vars by name.

I kind of want to link multiple structs to the same changing data. If that makes any sense.

For example:

getd(data,type);

if (type ==2)
second_struct.data1 = 250;
else
first_struct.data1 = 65000;


I'm not sure but I don't 'think' this would be very memory or cpu intensive.
James B
Guest







PostPosted: Mon Mar 06, 2006 6:52 pm     Reply with quote

I guess so imagine I have two structs and 1 source of data coming in. I want to link both so that I can do this:

struct animals {
int pig;
int cow;
int horse;
int duck;
}

struct equipment {
int tractor;
int truck;
int16 pipes;
}


int *data[8];
...
getd(data,type);
...
if (type == animals)
d = animals.duck;
else
p = equipment.pipes
...

So basically my data is always stored in the data[] but I can symbolicly access it by its type.

I dumbed down the example (obviously) to explain myself better. I'de rather not change the way I collect data in the getd().

This seems like a job for unions but I'm not sure how to aligh to an array multible times.

Thank You,
Ttelmah
Guest







PostPosted: Tue Mar 07, 2006 3:25 am     Reply with quote

Linking different names, is definately a name for unions.
Basically, if you declare two structure 'names':
Code:

struct struct1 {
   //stuff here
}

struct struct2 {
   //other stuff here
}

//Then if you declare a union:

union union_name {
   struct struct1;
   struct struct2;
}

You can now use a union declared as 'union_name', to access the data through the two different structure names. Space will only be allocated to the union (just as with the structure), when you have a 'variable name', after the declaration. The actual amount of space allocated will be that of the larger structure.
Remember that you could allocate the 'space' somewhere else, either usng the memory management functions (include 'stdlibm.h', and using malloc), or by just allocating a byte array of the required size. If the memory is static, then you only need to pass the pointer, and declare the value passed as a pointer to a union of this type (don't actually 'move' the values). Now you can 'depointer' with the * declaration.

So if you have a function 'fred', returning a variable of type *union union_name, and you put this into 'mem_ptr', you can access the structures as:

(*mem_ptr).struct1.structure_element

Note the brackets. These are required, because of the way operator precedence works in C. 'mem_ptr', is a pointer to union of type 'union_name, and (*mem_ptr), is the union itself.

Best Wishes
James B
Guest







PostPosted: Tue Mar 07, 2006 3:50 am     Reply with quote

Thank You Ttelmah

I get it, but it seems I am making the program more complex then it needs to be. I was just looking for an easy way to call data by symbolic names but for as much as I'm doing that I may as well just hardcode it in (x = data[5])

It won't be as easy to read and I'm sure to forget thing here or there but it does keep it simple.

Thanks Again!
treitmey



Joined: 23 Jan 2004
Posts: 1094
Location: Appleton,WI USA

View user's profile Send private message Visit poster's website

PostPosted: Tue Mar 07, 2006 9:16 am     Reply with quote

Quote:
It won't be as easy to read and I'm sure to forget thing here or there but it does keep it simple.


Put in LOTS of comments.

And Yes allways think of KISS.
Ttelmah
Guest







PostPosted: Tue Mar 07, 2006 9:56 am     Reply with quote

For some types of operation, the union/structure approach, may be the 'best', but for many (most?) likely embedded applications, careful use of your own direct accesses, and good comments will be better/simpler.
One thing it might be worth considering, is use of the #define.
So:
Code:

#define pig 0
#define cow 1
#define horse 2
#define duck 3

#define tractor 0
#define truck 1
#define pipes16 1

#union {
   b8[4];
   w16[2];
} data;


Then you can access 'cow', as data.b8[cow], and 'pipes', as
data.w16[pipes16].

I use the '16', and '8', to remind you which data sizes are being used.
This has the advantage of being a lot less likely to cause compiler problems than the union of structures, but still give some 'sense' to the names.

Best Wishes
Ttelmah
Guest







PostPosted: Tue Mar 07, 2006 10:20 am     Reply with quote

It would help if I had an int8, and int16 declarations in the union. Brain elsewhere...

Best Wishes
James B
Guest







PostPosted: Tue Mar 07, 2006 11:42 am     Reply with quote

I thought about define and didn't really cling to that since I'de be calling from an array, and like you said that adds a few instructions. I was looking at your post and was like "Huh.... apparently you don't need to give it a data type there", but then came to my senses with your last post Embarassed


I did have an idea that isn't exactly what I wanted to do but.. How about declaring a *data[8], then assigning certain bytes inside it, based on thier memory

Sort of like the #byte command, but is it then required for me to locate *data?

ie:

int *data[8]; //lets say it starts at 0x100;

int &pig = 0x103;

int16 pipes = 0x101;

I figure when I update data it will only be meaningfull depending on the address/name I use, which is kind of what I wanted in the first place, but not really, I'm dumb so I'm comprimising.

Can I do that ? Also, can it be done without having ME locate *data? Or is this a waste of resources ?
Ttelmah
Guest







PostPosted: Tue Mar 07, 2006 3:28 pm     Reply with quote

If you access a _constant_ element in an array, the compiler sorts it all out at compile time, and directly accesses the element (only a couple of instructions). If you use a pointer, or a variable, the maths has to occur at runtime. Hence the define gives quick accesses, but using a pointer doesn't.
Sorry...

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group