-1

EEPROM Data:

0000: 88 77 66 55 44 33 22 11 00 00 00 00 00 00 00 00

0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

I am saving the result after reading 0th row of EEPROM in array

Ex - Uint8 EEPROM_res[8];

 EEPROM_res = {88, 77, 66, 55, 44, 33, 22, 11};

I want to convert HexaDecimal(0x8877665544332211) into decimal (9833440827789222417) and save the decimal value into integer data type for further comparison. What is the easiest way of conversion of 8-Byte Hexadecimal?

Richard Matsen
  • 20,671
  • 3
  • 43
  • 77
  • 1
    same as a 7 byte and as a 6 byte and ... as a 1 byte and as 2 bits. – old_timer Jul 07 '20 at 02:00
  • Can you share the algorithm? – Shivangi Kishore Jul 07 '20 at 02:06
  • maybe work with a `union` – Mike Jul 07 '20 at 05:20
  • 1
    You realize that all data in your memory and C program is _binary_, yeah? Hex, decimal etc are only different convenient presentations to the user or programmer. Thus "converting from hex to decimal" doesn't make any sense, because you neither have hex nor decimal, but raw binary. Converting to _strings_ containing one representation or the other is another story though. – Lundin Jul 07 '20 at 06:49
  • The next question is why you store data in big endian format when you want to use little endian format? Assuming this Cypress MCU is little endian. – Lundin Jul 07 '20 at 06:52
  • If comparison is the motive , then compare byte by byte. That is enough. – Babajan Jul 07 '20 at 07:26
  • I want to compare the whole Decimal value at a time so Byte by Byte comparison is not good enough in my case. – Shivangi Kishore Jul 07 '20 at 07:56
  • Take a byte pointer and point to EEPROM_res.Take a integer variable, assign it's value using the byte pointer and type casting to integer. Code snippet as below uint8* byteptr = EEPROM_res; uint64 int_var = (uint64)(*byteptr) ; Take care about Endiannes. This should work. – Babajan Jul 07 '20 at 08:27
  • 1
    @Babajan I take it that you meant `uint64 int_var = *(uint64*)byteptr ;`. That's still a strict aliasing violation however. Make sure to have it disabled when doing hardware-related programming. In general, stay clear of fishy casts unless you have in-depth knowledge of C. – Lundin Jul 07 '20 at 10:42
  • @Lundin You got it correctly and thanks for code correction. What else can be done ?Shivangi Kishore is looking for easiest way. – Babajan Jul 07 '20 at 11:14
  • and @Shivangi Kishore Why do you think byte by byte comparison is not good enough ? – Babajan Jul 07 '20 at 11:14
  • @Shivangi Kishore In general reading from EEPROM function should have 3 arguments as shown below. ReadEEPROM( EEPROM address, Ram address, No of bytes) why cant you read to uint64 variable directly ? code snippet as below uint64 int_var; ReadEEPROM( EEPROM address, &int_var , 8 ); – Babajan Jul 07 '20 at 11:20

1 Answers1

-1

Can you share the algorithm? – Shivangi Kishore

Converting base 10 (seconds) to base 60 (hours:minutes:seconds)

4321 seconds (in base 10) to base 60.

60^0 = 1
60^1 = 60
60^2 = 3600
60^3 = 216000

(just like 10^0 = 1, 10^1 = 10 and 10^2 = 100 ... base 10, 2^0 = 1, 2^1 = 2, 2^2 = 4 and so on base 2)

So 4321 is less than 216000 but greater than 3600 so we can shortcut and start there

4321 / 3600 = 1 remainder 721
721 / 60 = 12 remainder 1

So 4321 base 10 converted to base 60 (using base 10 to do the math) is 01:12:01

base 2 to base 10 using a base 2 computer is no different.

10 factors into 2 and 5, 2 factors into 2, so you cannot do base 8 (octal) to base 2 shortcuts nor can you do base 16 (hex) to base 2 shortcuts. Have to do it the long way.

EDIT

Another approach that may be more useful to you is to work from the other end. Same math just done using remainders instead of results. Makes for an easier algorithm to program.

4321 / 60 = 72 remainder 1 72 / 60 = 1 remainder 12 1 / 60 = 0 remainder 1 conversion to base 60: 01:12:01

1234 / 10 = 123 remainder 4 123 / 10 = 12 remainder 3 12 / 10 = 1 remainder 2 1 / 10 = 0 remainder 1 conversion to base 10: 1234

Long division in binary is the same but simpler than in a base greater than 2 because the divisor on each step through the denominator can either go into the test value 0 times or 1 time. binary...base 2...

Also if you think through long division (254 / 5 or 0xFE / 0x5)

    ------------
101 ) 11111110

this is the first test cases that is non-zero

      001
    ------------
101 ) 11111110
      101

and you keep going

      001
    ------------
101 ) 11111110
      101
      ---
       10

and

      0011
    ------------
101 ) 11111110
      101
      ---
       101
       101
       ---
         0

and

      00110010
    ------------
101 ) 11111110
      101
      ---
       101
       101
       ---
         0111
          101
          ---
           100

and so 0xFE / 5 = 0x32 remainder 4, but the key here is that I could do that in hardware with a hardware divide instruction if I have say an 8 bit divide instruction and want to divide an infinitely long number. If my next (let's say) four digits were 1010:

     0001110
101  1001010
      101
      ===
      1000
       101
       ===
        111
        101 
        ===
         100

0xFEA / 5 = 0x32E remainder 4

So now I have divided a 12 bit number using an 8 bit divider instruction and I can do this all day long until I run out of ram. 8 bits, 88 bits, 888 bits, 8888 bits, a million bits divided by a small number like 5 or 10.

Or if you keep working on this you find that compilers often use multiply we also know from grade school (since all of this problem is solved with grade school math).

x / 10 = x * (1/10)

More likely to find a hardware multiply than a divide and the multiply is often fewer clocks, etc.

unsigned int fun ( unsigned int x )
{
    return(x/10);
}
00000000 <fun>:
   0:   e59f3008    ldr r3, [pc, #8]    ; 10 <fun+0x10>
   4:   e0802093    umull   r2, r0, r3, r0
   8:   e1a001a0    lsr r0, r0, #3
   c:   e12fff1e    bx  lr
  10:   cccccccd    stclgt  12, cr12, [r12], {205}  ; 0xcd


0000000000000000 <fun>:
   0:   89 f8                   mov    %edi,%eax
   2:   ba cd cc cc cc          mov    $0xcccccccd,%edx
   7:   f7 e2                   mul    %edx
   9:   89 d0                   mov    %edx,%eax
   b:   c1 e8 03                shr    $0x3,%eax
   e:   c3                      retq   

and other instruction sets, the compiler multiplies by 1/5 then compensates (base 10, 10 factors to 2 and 5, base 2, 2 factors to 2 a common factor).

But if your hardware doesn't have a multiply or divide the compiler should still handle the basic C language variable types, long, int, short, char. And you can cascade those all day long.

unsigned int fun ( unsigned int x )
{
    unsigned int ra;
    unsigned int rb;
    unsigned int rc;

    ra=((x>>4)&0xFF)/5;
    rb=((x>>4)&0xFF)%5;
    rb=(rb<<4)|(x&0xF);
    rc=rb/5;
    ra=(ra<<4)|rc;
    return(ra);
}

test it on the development machine

#include <stdio.h>
extern unsigned int fun ( unsigned int );
int main ( void )
{
    printf("%X\n",fun(0xFEA));
    return(0);
}

and the output is 0x32E.

And that really completes it everything you need to know (well you already knew from grade school) to do the conversion with the tools you have available.

If instead you are looking for some big math library for some compiler for some target, having us google things for you is not a Stack Overflow question and should be closed as seeking external or third party libraries.

Now as pointed out

save the decimal value into integer data type for further comparison

makes no sense whatsoever, if you want to take some number and then save it for further comparison on a computer, that function looks like this

void fun ( void )
{
}

It is already in that form you want it to be a integer that means some variable (larger than C supports so that is yet another problem with the wording of the question) so that means binary not decimal, so it is already in a future comparable integer form.

If you want to represent that number visually (as in a human viewable printout) in some base then you need to convert that into something that can be viewed be it base 2 (binary), base 8 (octal), base 16 (hex), base 10 (decimal) and so on.

The bits 11111111 in the computer if I want to see those in binary then "11111111" in octal "377" in hex "FF" in decimal "255" all of which require an algorithm to convert. Octal and hex of course being the simplest, don't need to use a division routine to convert to octal, base 8, factors are 222 base 2 factors are 2 so 2^3 vs 2^1

11111111 / 8 = 11111111 >> 3 = 11111 r 111
11111 / 8 = 11111 >> 3 = 11 r 111
11 / 8 = 11 >> 3 = 0 r 11
377

Base 10 though you have to go the long way and actually do the division and find the remainder until the result of the division in the loop is 0. 10 has factors 2 and 5, 2 has factors 2 you can't shift your way through it. Base 100, 10*10, and base 10 you can shift your way through (just like base 2 to base 4) but base 10 from base 2, can't.

11111111 / 10 = 11001 r 101
11001 / 10 = 10 r 101
10 / 10 = 0 r 10
255

Which of course is why we greatly prefer to view stuff on the computer in hex rather than decimal.

Once in decimal though

"for further comparison"

once you get it to base 10 then the only reasonable comparison you can do with other base 10 numbers is a string compare or an array compare, from the above example the two more common ways you would store that conversion is 0x32, 0x35, 0x35, 0x00 or 0x02, 0x05, 0x05 with some length knowledge. You can't do greater than less than without a whole lot of work. Equal vs not equal you could do in base 10 bit it is not in integer form.

So your question doesn't make any sense.

Also assume this is a multi part typo:

EEPROM_res = {88, 77, 66, 55, 44, 33, 22, 11};

which is the same as

EEPROM_res = {0x58,0x4D,0x42,0x37,0x2C,0x21,0x16,0x0B};

Neither of which are

EEPROM_res = {0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11};

Which is what your first 8 bytes of eeprom dump showed in hexadecimal as you mentioned and is somewhat obvious.

Nor are they

EEPROM_res[19] = {0x39,0x38,0x33,0x33....and so on
or
EEPROM_res[19] = {0x09,0x08,0x03,0x03....and so on

the decimal value you computed somehow: 9833440827789222417

halfer
  • 19,824
  • 17
  • 99
  • 186
old_timer
  • 69,149
  • 8
  • 89
  • 168
  • and as pointed out from the limited information provided your starting data is binary (only visually represented in hex, which uses the shortcut). – old_timer Jul 07 '20 at 14:05