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 support@ccsinfo.com

typedef, working with 12bits ints?

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



Joined: 06 Mar 2015
Posts: 28
Location: Spain

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

typedef, working with 12bits ints?
PostPosted: Fri Mar 06, 2015 10:05 am     Reply with quote

Hi!
This is my first post in this forum, hope to learn and contribute to it! Very Happy

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 Sad

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 Smile
Ttelmah



Joined: 11 Mar 2010
Posts: 19358

View user's profile Send private message

PostPosted: Fri Mar 06, 2015 12:15 pm     Reply with quote

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

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

PostPosted: Sat Mar 07, 2015 3:16 am     Reply with quote

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: 19358

View user's profile Send private message

PostPosted: Sat Mar 07, 2015 4:11 am     Reply with quote

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

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

PostPosted: Sat Mar 07, 2015 5:14 am     Reply with quote

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: 19358

View user's profile Send private message

PostPosted: Sat Mar 07, 2015 9:06 am     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Mar 09, 2015 3:11 am     Reply with quote

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.
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