|
|
View previous topic :: View next topic |
Author |
Message |
Marttyn
Joined: 06 Mar 2015 Posts: 28 Location: Spain
|
typedef, working with 12bits ints? |
Posted: Fri Mar 06, 2015 10:05 am |
|
|
Hi!
This is my first post in this forum, hope to learn and contribute to it!
I'm working on a RF decoder library I've made, and now I'm trying to give some structure to the buffer, so it can be accessed easily.
The RF data its always a 24 bits stream. Every group of 2 bits represent a "1", "0" or "floating" (11/00/10).
It comes in 2 (more in the future) arrangements:
If the remote control has 4CH, the 24 bits are like this: 16bits for address, 8 bits for data.
If the remote control has 6CH, the 24 bits are like this: 12bits for address, 12 bits for data.
Ive made a typedef called rfBuff for this, and i use a complex fashion of structs and unions to arrange the data. I use 32bits wide, although 8bits are waste.
So, if i create:
rfBuff data;
Then if I'm working with 4CH remote, i can access address like this:
data.Ch4.Addr -> int16 with address of the remote
Also i can access data like this:
data.Ch4.Dat -> int8 with data of the remote
If i work with 6CH remote, i can do the "same" with some problems:
data.Ch6.AddrLo -> int8 with low address of the remote
data.Ch6.AddrHi -> 4bits with address of the remote
data.Ch6.DatLo -> 4bits with low address of the remote
data.Ch6.DatHi -> int8 with address of the remote
and i need to do some "math" to recompose the address and data:
long Addr6CH = make16(data.Ch6.AddrHi, data.Ch6.AddrLo);
long Dat6Ch = (long)data.Ch6.DatHi<<4 | data.Ch6.DatLo;
Here is the typedef, which i simplified, and removed some unions and structs for better understanding:
Code: |
typedef union{
//A0 A1 A2 A3 A4 A5 A6 A7 D3 D2 D1 D0 (order of received data, each one is 2 bits)
struct{
//address
long Addr; //bits 0-15
//data
int Dat; //bits 16-23
int Nul; //bits 24-32
}Ch4; //4 ch remote
//A0 A1 A2 A3 A4 A5 D5 D4 D3 D2 D1 D0 (order of received data, each one is 2 bits)
struct{
//address
int AddrLo; //bits 0-7
//half address high and half data low
struct{
int AddrHi:4; //bits 8-11
int DatLo:4; //bits 12-15
};
//data high
int DatHi; //bits 16-23
int Nul; //bits 24-31
}Ch6; //6 ch remote
short Bits[32]; //32 bits
int32 Full;
}rfBuff;
|
As you can see, you can even access full value with "data.Full", or single bits with "data.Bits[x]"
There is some possible way to get the full values of data and address for 6CH remote directly from the typedef? Without additional processing?
I've tried something like:
int Addr:12;
int Dat:12;
But doesn't work
And of course the icing on the cake would be to find a way to remove the 8bit waste, so the typedef would become an int24...
Any suggestion for any of the problems?
Thanks a lot, and we will see more often in the future |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19499
|
|
Posted: Fri Mar 06, 2015 12:15 pm |
|
|
Help if you told us the processor.
However I'd guess has to be a PIC16/18?.
The bitfield is the way to go, if you switch to a PIC24, then it'll work with :12 as a width....
It's one of those things that CCS ought to support in ANSI mode, for the other processors and I'd suggest you point this out to them.
Unfortunately on the lower processors they still seem to insist on sticking with 8bit max, even if you use #type to force int to be int16.. :(
I'm sure this was mentioned in the compiler updates a while ago, but I couldn't spot it in the update list. |
|
|
Marttyn
Joined: 06 Mar 2015 Posts: 28 Location: Spain
|
|
Posted: Sat Mar 07, 2015 3:16 am |
|
|
Thanks for your reply!
Yes, I mainly develop in PIC12 and PIC16.
Im not sure what you mean when you say bitfield is the way to go.
An interesting directive, i didnt knew i could change the size of the variables. But why its there if it doesnt work?
Regards! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19499
|
|
Posted: Sat Mar 07, 2015 4:11 am |
|
|
It does work for most things. The one thing it doesn't handle is the bitfield. :(
Bitfield (or bit-field), is the 'name' for what you are showing.
:x is a bitfield in a variable. Allows you as you show to fit things occupying various numbers of bits into a variable. On the PIC 12/16/18 though CCS limit the size of the 'container' to be the default integer size....
ANSI C, requires the default integer to be 16bit, and so CCS should accept a 16bit value for the bitfield when this option is enabled - but doesn't.
However I'm sure I remember them saying something about this in one of the compiler update 'readmes' not that long ago, but just can't find it.
It's never going to be terribly efficient using 12bit or similar values, since the core processor always works in bytes (or words for the larger PIC's). |
|
|
Marttyn
Joined: 06 Mar 2015 Posts: 28 Location: Spain
|
|
Posted: Sat Mar 07, 2015 5:14 am |
|
|
Ttelmah wrote: | It does work for most things. The one thing it doesn't
It's never going to be terribly efficient using 12bit or similar values, since the core processor always works in bytes (or words for the larger PIC's). |
But it should be more efficient than doing extra math...
making a struct of 2 ints, and an union with a long its more efficient than using make16 of two ints, or using << >>.
Well... the point is its not possible :(
Thanks for sharing your thoughts! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19499
|
|
Posted: Sat Mar 07, 2015 9:06 am |
|
|
Not really. It just hides the maths.
The compiler is still going to have to do the maths, to move the values around.
Now there are cases where 'doing the maths' yourself, will be more efficient.
If (for instance), you only want the high nibble of the high byte, you could elect to use make8, and the swap instruction. However since the compiler couldn't 'know' that this was OK, it'd have to use the individual rotations to get this part. |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Mon Mar 09, 2015 3:11 am |
|
|
Certainly in the past, but I believe not now, CCS S did not support bit fields that straddled byte boundaries. That means recent compiler versions might be able to cope with 12 bit wide fields, but older ones (?most if not all version V4s?) couldn't.
There is no built-in support for 12 bit variables (int12), both in the hardware, nor the compiler. There's no 24 bit support either (int24), which is in my experience more useful, and is provided by some PIC compilers, but not CCS C.
As tempting as it is, personally I gave up long ago trying to force the compiler to map data structures on to bit streams. There's too much that can, and often does go wrong: word length, data alignment, bit and byte order, unexpected padding, page alignment on earlier PICs and so on. Even if it works on one architecture, its often not all that portable (i.e. I can't use precisely the bit-field based same structure definition on PIC 16, PIC18, PIC 24, PC and, say, ARM). Instead I explicitly decode and map such streams on to variables with code, rather than trying to coax the compiler and PIC to do it for me in its somewhat unpredictable way. I simply have no confidence in it any more: I've been burnt too often.
12 bit variables can, with care with things like overflow, be treated as 16 bit. I do a fair bit of work with CAN, and the eight byte message limit means I often have to pack odd length variables into short messages. For scaling reasons, I seem to end up using a lot of fourteen and ten bit variables, and these cause, if anything, even more problems than 12 bit values. I'd love to be able to use bit fields - and I have tried many times - but there's always been something messing them up. So, now I don't bother trying. |
|
|
|
|
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
|