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

Conversion and manipulation between 8 and 16 bit variables
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
kypec



Joined: 20 Sep 2003
Posts: 54

View user's profile Send private message

Conversion and manipulation between 8 and 16 bit variables
PostPosted: Tue Nov 11, 2003 4:26 am     Reply with quote

Hello,

I was looking for an easy way how to load int8 to either low or high
byte of int16 variable WITHOUT affecting the other byte of that int16.

The opposite conversion is quite simple:
int16 word;
int8 lowbyte, highbyte;

lowbyte=make8(word,0);
highbyte=make8(word,1);

My solution is like this (only for PIC18 family -> tested with PCH 3.180 compiler)
Code:

////////////////////////////////////////////////////////////////////////////////
//MACRO for straight move of 8-bit variable to low byte of 16-bit variable
////////////////////////////////////////////////////////////////////////////////
#define move8to16low(SOURCE8,DESTINATION16) \
#asm \
movff SOURCE8,&DESTINATION16 \
#endasm

////////////////////////////////////////////////////////////////////////////////
//MACRO for straight move of 8-bit variable to high byte of 16-bit variable
////////////////////////////////////////////////////////////////////////////////
#define move8to16high(SOURCE8,DESTINATION16) \
#asm \
movff SOURCE8,&DESTINATION16+1 \
#endasm


and then whenever in your code you just use

move8to16low(lowbyte,word)

or

move8to16high(highbyte,word)

Please post your comments and suggestions if you know
about some pure C solution for this, thanks.
Ttelmah
Guest







Re: Conversion and manipulation between 8 and 16 bit variabl
PostPosted: Tue Nov 11, 2003 5:46 am     Reply with quote

kypec wrote:
Hello,

I was looking for an easy way how to load int8 to either low or high
byte of int16 variable WITHOUT affecting the other byte of that int16.

The opposite conversion is quite simple:
int16 word;
int8 lowbyte, highbyte;

lowbyte=make8(word,0);
highbyte=make8(word,1);

My solution is like this (only for PIC18 family -> tested with PCH 3.180 compiler)
Code:

////////////////////////////////////////////////////////////////////////////////
//MACRO for straight move of 8-bit variable to low byte of 16-bit variable
////////////////////////////////////////////////////////////////////////////////
#define move8to16low(SOURCE8,DESTINATION16) \
#asm \
movff SOURCE8,&DESTINATION16 \
#endasm

////////////////////////////////////////////////////////////////////////////////
//MACRO for straight move of 8-bit variable to high byte of 16-bit variable
////////////////////////////////////////////////////////////////////////////////
#define move8to16high(SOURCE8,DESTINATION16) \
#asm \
movff SOURCE8,&DESTINATION16+1 \
#endasm


and then whenever in your code you just use

move8to16low(lowbyte,word)

or

move8to16high(highbyte,word)

Please post your comments and suggestions if you know
about some pure C solution for this, thanks.


Just use a union...
Universal C, and makes small code.

union CONVERT {
int8 b[2];
int16 word;
} value;

Then to write to/retrieve the bytes, just use value.b[0], and value.b[1]. To talk to the whole 'word', use value.word.

So:

int8 onebyte;
value.word=0x3FF;
onebyte=value.b[1]; //onebyte=03
value.b[1]=0x7;
printf("%lx",value.word); //will print 7FF

Works on all the PICs, and (with a caveat about the byte order), on other processors to. The code produced is single byte accesses for the byte operations, which is as good as the assembler solution.

Best Wishes
Neutone



Joined: 08 Sep 2003
Posts: 839
Location: Houston

View user's profile Send private message

PostPosted: Tue Nov 11, 2003 8:28 am     Reply with quote

Their are built in functions to handel this and keep your code easy to read.
Make8
Make16
Make32
Refer the the manual for their use.
kypec



Joined: 20 Sep 2003
Posts: 54

View user's profile Send private message

Not what I was looking for
PostPosted: Tue Nov 11, 2003 8:56 am     Reply with quote

Unfortunately,

make8 is only useful when you need to retrieve int8 alias byte
from larger variable like int16 or int32

make16 is for creating int16 alias long variable from two smaller
variables like int8

however, what I needed to do is to modify ONLY ONE byte of
int16 variable without use of any shifting, masking or whatsoever operations on that int16 variable

that hint with UNION declaration is indeed very handy, thanks

now my code looks like this:
Code:

union word {
int8 b[2]; //low[0] and high[1] byte
int16 w; //create together one word
};

union word parameter[32]; //={0x05FF,100,100,1000,1000,500,100};
int8 mode_flags, now_flags;
int16 time_valve;

mode_flags=parameter[0].b[1]; //reading the byte from word
parameter[0].b[0]=now_flags;   //writing the byte to word
time_valve=parameter[1].w      //reading the word from word


the only disadvantage I can see now is that I lost the possibility
to declare and initialize my array of parameters in simple step
(therefore those brackets with hexa values)
Ttelmah
Guest







Re: Not what I was looking for
PostPosted: Tue Nov 11, 2003 9:29 am     Reply with quote

kypec wrote:
Unfortunately,

make8 is only useful when you need to retrieve int8 alias byte
from larger variable like int16 or int32

make16 is for creating int16 alias long variable from two smaller
variables like int8

however, what I needed to do is to modify ONLY ONE byte of
int16 variable without use of any shifting, masking or whatsoever operations on that int16 variable

that hint with UNION declaration is indeed very handy, thanks

now my code looks like this:
Code:

union word {
int8 b[2]; //low[0] and high[1] byte
int16 w; //create together one word
};

union word parameter[32]; //={0x05FF,100,100,1000,1000,500,100};
int8 mode_flags, now_flags;
int16 time_valve;

mode_flags=parameter[0].b[1]; //reading the byte from word
parameter[0].b[0]=now_flags;   //writing the byte to word
time_valve=parameter[1].w      //reading the word from word


the only disadvantage I can see now is that I lost the possibility
to declare and initialize my array of parameters in simple step
(therefore those brackets with hexa values)


There is a way (more 'CCS specific'), to give both abilities, provided you are happy to manually 'set' the variables at a particular address. You can use the #locate ability to place two variables into the same area of memory (rather like a union). So:

struct {
int8 b[2];
} bytearray[];

int16 wordarray[32]={0x05FF,100,100,1000,1000,500,100};

#locate bytearray=0x400
#locate wordarray=0x400

Places an initialised int16 array (called 'wordarray'), at address 0x400 in RAM, and also an array of 'bytearray' structures at the same point.
Then just as with the union, you can access:

wordarray[0] - the first 16bit 'word', while:
bytearray[0].b[0] - is the low byte of the first word.

Again like the union system, it generates quite tidy code.
It is also worth realising, that you can cast between types into a function. So, if you declare the array as int16, and initialise it, and have the union type declared, you can create a function like:

put_byte(union word location, int val, int place) {
location.b[place]=val;
}

and call this with an int16 value, like:

int16 array[32]={0x05FF,100,100,1000,1000,500,100};

put_byte(array[2],5,0);

which will write the byte '5' to the low byte of 'array[2]', effectively giving the other 'half' of the make8/make16 functions. :-)

Best Wishes
dragonpic
Guest







how I do it
PostPosted: Tue Nov 11, 2003 3:02 pm     Reply with quote

int highbyte, lowbyte;
long word;
#BYTE word0 = word
#BYTE word1 = word + 1

highbyte = word1
lowbyte = word0
Ttelmah
Guest







Re: how I do it
PostPosted: Tue Nov 11, 2003 3:33 pm     Reply with quote

dragonpic wrote:
int highbyte, lowbyte;
long word;
#BYTE word0 = word
#BYTE word1 = word + 1

highbyte = word1
lowbyte = word0

Works fine for a single value, but is not really a solution for an array of values... :-)

Best Wishes
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Tue Nov 11, 2003 5:14 pm     Reply with quote

One word - Pointers
Ttelmah
Guest







PostPosted: Wed Nov 12, 2003 3:30 am     Reply with quote

Mark wrote:
One word - Pointers

Yes, _but_...
It depends what you want to do, and how often. You can as you say, access words as bytes, or bytes as words, using pointers, and casting them between types. Unfortunately, the resulting code is _bulky_, and relatively slow. For instance, accessing the bytes in the union method, generates single instruction accesses, for fixed addresses. Doing the same using pointers, runs to about 30 instructions.
You 'pays your money'... :-)

Best Wishes
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Wed Nov 12, 2003 7:07 am     Reply with quote

Yep, but he is using arrays which will already generate the "bulky" code.
Ttelmah
Guest







PostPosted: Wed Nov 12, 2003 7:26 am     Reply with quote

Mark wrote:
Yep, but he is using arrays which will already generate the "bulky" code.

Not true.
If (as he shows), you generate array accesses to fixed addresses, the code produced is a single access to the actual value. So if you use arrays purely for their 'simplicity', in terms of the code appearance, rather than for allowing a variable to act as an index, then you don't get the time overhead of a table access. There will be one 'table access' routine, written in front of the stored array data, but this won't be used for the simple accesses. Also the routine only appears once. If you write multiple routines accessing data via pointers, the table access code is repeated in each location it is used.

Best Wished
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Wed Nov 12, 2003 7:52 am     Reply with quote

I will bet a nickel that is uses a variable to access the data and that the fixed address is just an example. Furthermore, I would bet that a structure is really what he wants but is unsure of how to initialize one.
neil



Joined: 08 Sep 2003
Posts: 128

View user's profile Send private message

All variations on a theme
PostPosted: Wed Nov 12, 2003 12:44 pm     Reply with quote

I have always used the way CCS did it in their faq about writing a long to EEPROM. (Pointers in other words)

#define lo(x) *&x
#define hi(x) *(&x+1)

...

long variable;

hi(variable) = 0xE0;
lo(variable) = 0xFC;

// variable now = 0xE0FC

or:
variable = 0xAA55;

int low, high;

low = lo(variable); // low = 55
high = high(variable); // high = AA

From what I have seen, there is virtaully no extra code generated, just direct access to the bytes in either direction, as, quite logically the compiler assigns mulitbyte words sequentially. Am I right in thinking this?

Neil.
Ttelmah
Guest







Re: All variations on a theme
PostPosted: Wed Nov 12, 2003 2:25 pm     Reply with quote

neil wrote:
I have always used the way CCS did it in their faq about writing a long to EEPROM. (Pointers in other words)

#define lo(x) *&x
#define hi(x) *(&x+1)

...

long variable;

hi(variable) = 0xE0;
lo(variable) = 0xFC;

// variable now = 0xE0FC

or:
variable = 0xAA55;

int low, high;

low = lo(variable); // low = 55
high = high(variable); // high = AA

From what I have seen, there is virtaully no extra code generated, just direct access to the bytes in either direction, as, quite logically the compiler assigns mulitbyte words sequentially. Am I right in thinking this?

Neil.


No, this is fine, but the poster wants to work with arrays....

Best Wishes
DragonPIC



Joined: 11 Nov 2003
Posts: 118

View user's profile Send private message

arrays?
PostPosted: Wed Nov 12, 2003 3:16 pm     Reply with quote

I was responding to the original post. I seen nothing of arrays. Just a word and 2 byte variables.

Anyways

Code:
int make_8_from_16(long word, short high_low)
{
#BYTE word0 = word
#BYTE word1 = word + 1

   if(high_low == 1)
      return(word1);
   else
      return(word0);
}


Maybe not the best way to approuch it, but it works. You just have to think about it.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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