1

I'm trying to convert a BCD to ascii and vice versa and saw a solution similar to this while browsing, but don't fully understand it. Could someone explain it?

void BCD_Ascii(unsigned char src, char *dest) {
         outputs = "0123456789"
        *dest++ = outputs[src>>4];
        *dest++ = outputs[src&0xf];
        *dest = '\0';
    }
John
  • 1,808
  • 7
  • 28
  • 57

3 Answers3

1

The function converts a character in binary-coded decimal into a string.

First the upper 4 bits of src are obtained:

src>>4

The function then assumes the values those bits represent are in the range 0-9. Then that value is used to get an index in the string literal outputs:

outputs[src>>4]; 

The value is written into address which is pointed to by dest. This pointer is then incremented.

*dest++ = outputs[src>>4];

Then the lower 4 bits of src are used:

 src&0xf

Again assuming the values of those bits, are representing a value in range 0-9. And the rest is the same as before:

*dest++ = outputs[src&0xf];

Finally a 0 is written into dest, to terminate it.

2501
  • 25,460
  • 4
  • 47
  • 87
1

The opposite function can be:

BYTE ASC_BCD( char * asc )
{
  return (BYTE)( ( asc[0] & 15 ) << 4 ) | ( asc[1] & 15 );
}

Char codes '0'..'9' can be converted to hex with & 15 or & 0x0F. Then make shift and | to combine.

i486
  • 6,491
  • 4
  • 24
  • 41
1

Regarding your first question: Explaining the method:

  • You are right about src>>4, this shifts the character value 4 bits to the right which means it is returning the value of the higher hexdecimal digit. e.g. if src is '\30' then src>>3 will evaluate to 3 or '\3'.

  • src&0xf is getting the lower hexdecimal digit by ANDing the src value with 0xF with is the binary value 1111 (not 11111111). e.g. if src is '\46' then src&0xf will evaluate to 6.

There are two important notes here while trying to understand the method:

  • First: The method cannot handle input when src has either the two digits above 9. i.e. if src was equal to '\3F' for instance, the method will overrun buffer.

  • Second: beware that this method adds the two digit characters at a certain location in a string and then terminates the string. The caller logic should be responsible for where the location is, incrementing the pointer, and making sure the output buffer allows three characters (at least) after the input pointer location.

Regarding your second question: A reverse method could be as following:

unsigned char Ascii_BCD(const char* src) {
    return (unsigned char)((src[0] - 0x30) * 0x10 + src[1] - 0x30);
}

[Edit: adding explanation to the reverse method]

The two ASCII digits at location 0 and 1 are subtracted of by 0x30 or '0' to convert from ascii to binary. E.g. the digit '4' is represented by the ascii code 0x34 so subtracting 0x30 will evaluate to 4.

Then the first digit which is the higher is multiplied by 0x10 to shift the value by 4 bits to the left.

The two values are added to compose the BCD value.

Bishoy
  • 705
  • 9
  • 24
  • What does 0x10 do? Thats representing the (dle) character correct? Is that the same as using <<4? – John Jan 18 '16 at 21:13
  • 1
    Multiplication by 0x10 or 16 is the same as shifting right by 4 bits. I think I should have explained in my answer :) – Bishoy Jan 18 '16 at 21:15
  • Just wanted to double check... I gave your answer the check mark, thank you – John Jan 18 '16 at 21:18
  • U r most welcome. I've added some explanation to the reverse method in case needed. – Bishoy Jan 18 '16 at 21:26