tags:

views:

95

answers:

3

hello all,

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

+4  A: 

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
In my understanding, BCD only contains digits from 0 to 9. So no need for A - F.
Thomas Matthews
@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
You could also make the `outputs` array `const`... or even just use `#define outputs "0123456789ABCDEF"` ;)
caf
@caf: good point -- fixed.
Jerry Coffin
+1  A: 

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
+1 for correct use of `+ '0'`
R..
@Jerry @Thomas, Thank you for your response, I believe now I'll be able to improve my code....
Fakhar Imran
please also help me how can I incorporate the conversion of Reverse-BCD in the routine.
Fakhar Imran
@Fakhar: Please define "Reverse-BCD".
Thomas Matthews
@Thomas, actually there are two structures defined in the header file as follows <code>#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</code> 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
@Thomas, another define is as follows <code> #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 </code>
Fakhar Imran
@Fakhar: The ASCII digits are calculated as: `high = (bcd_value >> 4) + '0';` and `low = (bcd_value `. 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
@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
A: 

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