0

I've written a function in c that converts a byte (unsigned char) BCD string into ASCII. Please have look at the code and advice some improvements.

Is there any other efficient way that can convert BYTE BCD to ASCII.

BYTE_BCD_to_ASC(BYTE *SrcString, char *DesString)
{

        switch (((BCD *)SrcString)->l)
        {
            case 10:/*A*/
            case 11:/*B*/
            case 12:/*C*/
            case 13:/*D*/
            case 14:/*E*/
            case 15:/*F*/
                *DesString = (char)(((BCD *)SrcString)->l + '0' + 7);
                break;
            default:
                *DesString = (char)(((BCD *)SrcString)->l + '0');
                break;
        }

        switch (((BCD *)SrcString)->h)
        {
            case 10:
            case 11:
            case 12:
            case 13:
            case 14:
            case 15:
                *(DesString + 1) = (char)(((BCD *)SrcString)->h + '0' + 7);
                break;
            default:
                *(DesString + 1) = (char)(((BCD *)SrcString)->h + '0');
                break;
        }
    *(DesString + 2) = '\0';
}

thanks

Fakhar

codaddict
  • 445,704
  • 82
  • 492
  • 529
Fakhar Imran
  • 11
  • 1
  • 1
  • 2

3 Answers3

5

I think I'd do something like this:

void BCD2ASC(unsigned char src, char *dest) { 
    static const char outputs[] = "0123456789ABCDEF";
    *dest++ = outputs[src>>4];
    *dest++ = outputs[src&0xf];
    *dest = '\0';
}
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • 1
    In my understanding, BCD only contains digits from 0 to 9. So no need for A - F. – Thomas Matthews Aug 26 '10 at 20:16
  • 1
    @Thomas: there shouldn't be, but his code took that possibility into account, so I did too. In reality, I seem to recall some types of BCD using those codes for decimal points and rough equivalents of NaN and Infinity, but I don't recall any details. In any case, using a table lookup makes it trivial to treat those any way you prefer. – Jerry Coffin Aug 26 '10 at 20:33
  • You could also make the `outputs` array `const`... or even just use `#define outputs "0123456789ABCDEF"` ;) – caf Aug 27 '10 at 02:37
2

Try this:

void BCD_To_ASCII(unsigned char bcd_value, char * p_ascii_text)
{
  //--------------------------------------------------
  // BCD contains digits 0 .. 9 in the binary nibbles
  //--------------------------------------------------
  *p_ascii_text++ = (bcd_value >> 4)  + '0';
  *p_ascii_text++ = (bcd_value & 0x0f) + '0';
  *p_ascii_text = '\0';
  return;
}
Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
  • @Jerry @Thomas, Thank you for your response, I believe now I'll be able to improve my code.... – Fakhar Imran Aug 30 '10 at 00:49
  • please also help me how can I incorporate the conversion of Reverse-BCD in the routine. – Fakhar Imran Aug 30 '10 at 08:19
  • @Fakhar: Please define "Reverse-BCD". – Thomas Matthews Aug 30 '10 at 20:14
  • @Thomas, actually there are two structures defined in the header file as follows #ifdef __IBM__ #pragma option align=packed typedef struct { unsigned l : 4; unsigned h : 4; } BCD; typedef struct { unsigned h : 4; unsigned l : 4; } BCD_REVERSE; #pragma option align=reset now I think that any BCD number can be represented in two formats, BCD and REVERSE-BCD, may be the Reverse shall be with swapped nibbles, however there are systems sending time in this format. Now, I need to know how your code shall be modified to take care of this REVERSE option. – Fakhar Imran Aug 31 '10 at 01:08
  • @Thomas, another define is as follows #elif defined(__COMPAQ__) typedef struct { unsigned char h : 4; unsigned char l : 4; } BCD; typedef struct { unsigned char l : 4; unsigned char h : 4; } BCD_REVERSE; #endif – Fakhar Imran Aug 31 '10 at 01:23
  • @Fakhar: The ASCII digits are calculated as: `high = (bcd_value >> 4) + '0';` and `low = (bcd_value & 0x0f) + '0';`. To convert your `BCD` and `BCD_REVERSE`, just add '0' to ".l" for the low value and to ".h" for the high value. – Thomas Matthews Aug 31 '10 at 23:43
  • @Thomas, @R.. If you know the output is ASCII, then `+ '0'` may be the *wrong* thing to use, an implementation is not required to map `'0'` to the ASCII value representing the zero character, but if you *need* ASCII then you should use `+ 0x30` directly. – dreamlax Aug 31 '10 at 23:49
1

finally I have implemented the routine as follows

static const char s_szHexAscNo[] = "0123456789ABCDEF";

void BYTE_BCD_to_ASC(BYTE *SrcString, char DesString[3], int BCDflag)
{
    assert(SrcString != NULL);
    assert(DesString != NULL);

    if ( BCDFlag_Normal == BCDflag)
    {
        *DesString++ = (char) s_szHexAscNo[((BCD *)SrcString)->l];
        *DesString++ = (char) s_szHexAscNo[((BCD *)SrcString)->h];
    }

    if (BCDFlag_Reverse == BCDflag)
    {
        *DesString++ = (char) s_szHexAscNo[((BCD_REVERSE *)SrcString)->l];
        *DesString++ = (char) s_szHexAscNo[((BCD_REVERSE *)SrcString)->h];
    }
    *DesString = '\0';
}

/* BCD and BCD_REVERSE  are defined as */

typedef struct
{
unsigned char    l : 4;
unsigned char    h : 4;
} BCD;

typedef struct
{
unsigned char    h : 4;
unsigned char    l : 4;
} BCD_REVERSE;

comments would be appreciated....

Fakhar Imran
  • 11
  • 1
  • 1
  • 2