|
|
View previous topic :: View next topic |
Author |
Message |
Ttelmah
Joined: 11 Mar 2010 Posts: 19255
|
|
Posted: Sun Apr 14, 2013 4:18 am |
|
|
Yes, Apologies, it is mishandling values with trailing zeros.
Though it uses an extra bit if storage, this solves this problem, and makes the code a little quicker as well:
Code: |
void toBCD(int16 val,int8 * buff) {
//converts 16bit value, to five BCD digits. Tries to do it fairly
//efficiently, both in size, and speed.
int1 temp_bit;
int8 size=15;
int1 top_bit=TRUE;
buff[0]=buff[1]=buff[2]=0;
do {
if (!top_bit)
{
if ((buff[0] & 0xF)>=5) buff[0]+=3;
if ((buff[0] & 0xF0)>=0x50) buff[0]+=0X30;
if ((buff[1] & 0xF)>=5) buff[1]+=3;
if ((buff[1] & 0xF0)>=0x50) buff[1]+=0X30;
if ((buff[2] & 0xF)>=5) buff[2]+=3;
}
temp_bit=shift_left(&val,2,0);
shift_left(buff,3,temp_bit);
if (top_bit && temp_bit)
{
//Here have the top bit
top_bit=FALSE;
}
} while (size--);
}
|
Best Wishes |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sun Apr 14, 2013 8:23 am |
|
|
The original code failed for all values with least significant bits being zero, i.e. multiples of 2,4,8, etc.
Here is another fixed version. It has been optimized by using a local buffer array. The PIC processor is not efficient at handling pointer variables, but the CCS compiler will use hard coded addresses for data on the stack and as such becomes a lot more efficient.
Code: | void toBCD(int16 val,int8 * outBuf) {
//converts 16bit value, to five BCD digits. Tries to do it fairly
//efficiently, both in size, and speed.
int1 temp_bit;
int8 size = 16;
int8 buff[3] = {0,0,0}; // For optimization. The PIC processor can address a local array much more efficient than a parameterized address.
do {
if ((buff[0] & 0xF)>=5) buff[0]+=3;
if ((buff[0] & 0xF0)>=0x50) buff[0]+=0X30;
if ((buff[1] & 0xF)>=5) buff[1]+=3;
if ((buff[1] & 0xF0)>=0x50) buff[1]+=0X30;
if ((buff[2] & 0xF)>=5) buff[2]+=3;
temp_bit=shift_left(&val,2,0);
shift_left(buff,3,temp_bit);
} while (--size);
memcpy(outBuf, buff, sizeof(buff));
} |
In a short test program I compared the output of the variant posted by Ttelmah today at 11:18 and my version. For all values 0 to 65535 the output was identical. Ttelmah's version clocked at about 85 million instruction counts and the version posted here about twice as fast at 47.5 million.
I tried combining the top_bit optimization but that made things slightly worse. It turns out the top_bit is only skipped for about 12% of the values but adds more total overhead. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19255
|
|
Posted: Sun Apr 14, 2013 9:26 am |
|
|
Interesting. I hadn't realised a local array would be so much quicker.
Should have done. With the local array and fixed indices, the compiler pre-solves and doesn't have to do a table lookup. Know this all too well....
Doing the exit test 'mid loop', and moving the tests after the shift, though more elegant, and avoiding doing the tests on the first pass, costs a couple of instructions....
Looks as if provided you use a local buffer, the simplest is best on this one.
Best Wishes |
|
|
|
|
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
|