DSPRelated.com
Forums

convert hex to dec four digits on 320F24x DSP

Started by Lotfi May 24, 2004
Hi

I need to convert a hex value (0 to 270Fh) or with negatv 2s complement
D8F1h to 270Fh to the its four decimal digits
exple
1234 (which is 4D2h)  to 1, 2 , 3 and 4
this is for generating ASCII or so characters...

in C++
it gives someting like :

#include <stdio.h>
#include <stdlib.h>

int m,c,d,u;
double Val;
char string[20];

int main(int argc, char* argv[])
{
do{
    printf("\nValeur ? ");
    gets(string);
    Val= atof( string);
    m=(int)(Val/1000);
    c=(int)((Val-1000*m)/100);
    d=(int)((Val-1000*m-100*c)/10);
    u=Val-1000*m-100*c-10*d;
    printf("Conversion : m=%d c=%d  d=%d  u=%d", m,c,d,u);
  } while (Val !=-1);

return 0;
}


BUT I NEED to write it for fixed point DSP (TMS320F24x), as short as
possible
it has 32 bit accu, multiplication... and no division !
any ideas ?

thanks in advance
Lotfi


Hi Lofti,
I just did this with multiplies. Check out this usenet post for some ideas.
I did a similar thing, but used 6553/65536 =~ 0.1 instead of 41/4096 = 0.01.
Cheers, Syms.

http://tinyurl.com/2wty3


"Lotfi" <llbaghli(nospam)@ifrance.com> wrote in message
news:c8sfph$mdg$1@arcturus.ciril.fr...
> > > BUT I NEED to write it for fixed point DSP (TMS320F24x), as short as > possible > it has 32 bit accu, multiplication... and no division ! > any ideas ? > > thanks in advance > Lotfi > >
hi


// Get leading digit:
  n *= 103; // n = (((((n << 1) + n) << 2) + n) << 3) - n;
  d1 = n >> 10;

// Mask away the first digit
  n &= 1023;

// Multiply the remainder by 10/2, and shift down:
  n += n << 2; // n = n * 5;
  d2 = n >> 9;
  printf("Conversion rapide: d=%d  u=%d\n", d1, d2);


but it works for 0-99 only

I found on
http://www.cs.uiowa.edu/~jones/bcd/decimal.html


 if (n < 0) {
     putchar( '-' );
     n = -n;
 }

 d1 = (n>>4)  & 0xF;
 d2 = (n>>8)  & 0xF;
 d3 = (n>>12) & 0xF;

 d0 = 6*(d3 + d2 + d1) + (n & 0xF);
 q = (d0 * 0x19A) >> 12;
 d0 = d0 - 10*q;

 d1 = q + 9*d3 + 5*d2 + d1;
 q = (d1 * 0x19A) >> 12;
 d1 = d1 - 10*q;

 d2 = q + 2*d2;
 q = (d2 * 0x1A) >> 8;
 d2 = d2 % 10;

 d3 = q + 4*d3;
 d4 = (d3 * 0x1A) >> 8;
 d3 = d3 - 10*d4;
  printf("Conversion rapide: dm=%d  m=%d  c=%d  d=%d  u=%d\n", d4, d3, d2,
d1, d0);


but it is too long with lot of *....
:-(



Lofti,
Did you read this bit?
>>>>>
I'm really partial to using the 1/100 approximation 41 / 4096. With inputs of more than 3 digits, this can result in a wrong answer, but since it will be too large, the subsequent back-multiplication and subtraction will detect it easily, and allow a fixup based on the carry flag. The intermediate radix-100 numbers can then be split into 2 digits using 103 / 1024 as an 'exact approximation' to 1/10 over the 0..99 range. <<<<< cheers, Syms.
>>>>> "Symon" == Symon <symon_brewer@hotmail.com> writes:
Symon> Lofti, Symon> Did you read this bit? >>>>>> Symon> I'm really partial to using the 1/100 approximation 41 / 4096. Symon> With inputs of more than 3 digits, this can result in a wrong answer, Symon> but since it will be too large, the subsequent back-multiplication and Symon> subtraction will detect it easily, and allow a fixup based on the carry Symon> flag. It is possible to compute floor(n/d) exactly by using one multiplication and maybe some shifts. So if you want floor(n/100) using a 16-bit word-width, you can do something like floor(n/d) = floor(m*n/2^p) = floor((m*n/2^W)/2^s) where W is the word width, m is the magic number and s is a shift. For a 16-bit word (W = 16), m = 5243 and s = 3. For a division by 10, m = 26215 and s = 2. If d = 100 and W = 12, m = 1311, s = 5. See Hacker's Delight for the proof and algorithm. Ray
Thank you for your answer

ok to find the right couple (M and s), I have to minimise the function :
f(M,s)= M/2^s/2^16 - 1/d

for 16 bit data
where d=10, 100 or 1000 in my case.

I 'll use mathematica or so, but I don't know if the optimizer works with
integer values ??? will try and see.

Afterwards, I 'll write the routine to extract the decimal digits
exple for 1234
it will extract 1, 2, 3 and 4. then display it on my LCD...

I am thinking of divising the work in two similar, n (check its 2 digits
[thank to your 10 formula])   and     n/100 [thank to your 100 formula]
(check its 2 digits [thank to your 10 formula])


yours sincerely
Lotfi

"Raymond Toy" <toy@rtp.ericsson.se> a &#4294967295;crit dans le message news:
sxd1xl8gvwn.fsf@edgedsp4.rtp.ericsson.se...
> >>>>> "Symon" == Symon <symon_brewer@hotmail.com> writes: > > Symon> Lofti, > Symon> Did you read this bit? > >>>>>> > Symon> I'm really partial to using the 1/100 approximation 41 / 4096. > > Symon> With inputs of more than 3 digits, this can result in a wrong
answer,
> Symon> but since it will be too large, the subsequent
back-multiplication and
> Symon> subtraction will detect it easily, and allow a fixup based on
the carry
> Symon> flag. > > It is possible to compute floor(n/d) exactly by using one > multiplication and maybe some shifts. So if you want floor(n/100) > using a 16-bit word-width, you can do something like > > floor(n/d) = floor(m*n/2^p) > > = floor((m*n/2^W)/2^s) > > where W is the word width, m is the magic number and s is a shift. > > For a 16-bit word (W = 16), m = 5243 and s = 3. > > For a division by 10, m = 26215 and s = 2. > > If d = 100 and W = 12, m = 1311, s = 5. > > See Hacker's Delight for the proof and algorithm. > > Ray

Hi

just with excel

I computed the best Magic numbers (round up to have positive error)

here are my results for d=10, 100 and 1000

s 2^s           m0 m    1/10            reste
3 8 52428.8 52429.00 0.10000038 3.8146973E-07

                        1/100
5242.88 5243.00 0.01000023 2.2888184E-07

                        1/1000
8388.608 8389.00 0.00100005 4.6730042E-08


here is the excel file :-)


Lotfi wrote:

   ...

> f(M,s)= M/2^s/2^16 - 1/d
M/2^s/2^16 = (M/2^s)/2^16 = M/2^(s+16). Is that what you mean? ... Jerry -- Engineering is the art of making what you want from things you can get. &#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;&#4294967295;
the best routine :-)) to extract the numbers

int m,c,d,u;
int Magic, s;
double Val;


 // floor 16 bits
    unsigned short ns=Val; // here the entry point
    int W=16;
    m=0; c=0; d=0; u=0;
    if (ns>32767)  {printf("Attention n&#4294967295;gatif ");
                    ns=-ns; }
    Magic=8389; s=7;            // d=1000
    m=floor((Magic*ns>>W)>>s);
//    if (m>10)  alors d&#4294967295;passement affichage
    ns-=1000*m;
    Magic=5243; s=3;            // d=100
    c=floor((Magic*ns>>W)>>s);
    ns-=100*c;
    Magic=52429; s=3;           // d=10
    d=floor((Magic*ns>>W)>>s);
    u=ns-10*d;

    printf("Conversion magic number : m=%d c=%d  d=%d  u=%d\n", m,c,d,u);




"Jerry Avins" <jya@ieee.org> a &#4294967295;crit dans le message news:
40b4bcd5$0$3124$61fed72c@news.rcn.com...
> Lotfi wrote: > > ... > > > f(M,s)= M/2^s/2^16 - 1/d > > M/2^s/2^16 = (M/2^s)/2^16 = M/2^(s+16). Is that what you mean? >
forget it, I made an excel file that simply calculates the magic numbers... www.baghli.com/dl/magic.xls bye