No announcement yet.

four bytes to BCD String?

  • Filter
  • Time
  • Show
Clear All
new posts

  • four bytes to BCD String?

    I have four bytes coming into the serial port (MSB first) that represent a signed integer number. I would like to generate an array of numbers that hold the unpacked BCD values.
    For example, 0x7FFFFFFF = 2147483647 in decimal, so I would like the array to hold 2,1,4,7,4,8,6,4,7.
    I imagine that for negative numbers I would perform a two-compliment before the conversion, and just set a flag to add a "-" in front of the number.....
    I'm not sure if some of the built-in 4DGL functions could help with this?
    Best Regards,

  • #2

    When I first read that I thought you were saying the four bytes were coming in in BCD format (in BCD format 0x12345678 would be decimal 12345678) so the solution would be easy.

    Alas it is not so, so it becomes difficult as Picaso only has 16 bit math and converting a 32 bit binary number to decimal needs 32 bit math.

    Specifically you will need divide, modulous and a way of checking for -ve and ABS to make it positive

    You should be able to find some 'easy' 32 bit math for 16 bit processors algorithms out there that you could use, unfortunately I couldn't esily Google up an answer, but gee it should be out there, somewhere.


    • #3
      I've coded up the "Double Dabble" method of converting binary to bcd digits......It will convert 32 bits to 10 BCD digits in about 12-13 ms......
      #platform "uVGA-II_GFX2"#inherit "4DGL_16bitColours.fnc"// Based on DOUBLE DABBLE algorithm for converting// binary number to BCD digits. As is, this will convert 32 bits to// UNSIGNED BCD representation........// This routine could be optimized by skipping code until first carry is detected, etc
      func main() var bytes43 := 0xFFFF; //Most significant Hex digits var bytes21 := 0xFFFF; //Least Significant Hex digits var packedBCD[3] := [0,0,0]; var unpackedBCD[10] := [0,0,0,0,0,0,0,0,0,0]; var bitnum; var temp,y; var t_start,t_end; var carrybit; //----------------------------------------------- gfx_Cls(); print("starting..............\n"); t_start := sys_T(); //This is just for profiling conversion speed
      for (bitnum:=31;bitnum>=0;bitnum--) //Perform "dabble"..... 1st dabble does nothing as bcds are all zero. for (y:=0;y<3;y++) if ((packedBCD[y] &amp; 0x000F)>0x0004) packedBCD[y] += 0x0003; if ((packedBCD[y] &amp; 0x00F0)>0x0040) packedBCD[y] += 0x0030; if ((packedBCD[y] &amp; 0x0F00)>0x0400) packedBCD[y] += 0x0300; temp := (packedBCD[y] >> 12) &amp; 0x000F; //Get the upper 4 bits of packedBCD var if (temp > 0x0004) packedBCD[y] += 0x3000; next
      //Perform "Double".....bitshift source bits into packed BCD vars bytes21 := bytes21 << 1; //shift the msb of lower two bytes into the overflow register carrybit := (OVF() &amp; 0x0001); //Save the shifted out bit bytes43 := (bytes43 << 1) | carrybit; //Shift the msb of upper two bytes to overflow, carrying in the carry bit carrybit := (OVF() &amp; 0x0001); //Save the shifted out bit
      for(y:=0;y<3;y++) //Loop the number of packed vars we have packedBCD[y] := (packedBCD[y]<<1) | carrybit; //Double packed BCD var and add carry carrybit := (OVF() &amp; 0x0001); //Save the msb of last doubled var next next// print("\n");// print("Packed BCD[2] = " , [HEX] packedBCD[2],"\n");// print("Packed BCD[1] = " , [HEX] packedBCD[1],"\n");// print("Packed BCD[0] = " , [HEX] packedBCD[0],"\n");
      //Now let's unpack the packed BCD Digits (4 unpacked bcds per packed bcd) unpackedBCD[0] := (packedBCD[0] &amp; 0x000F); unpackedBCD[1] := (packedBCD[0] &amp; 0x00F0) >> 4; unpackedBCD[2] := (packedBCD[0] &amp; 0x0F00) >> 8; unpackedBCD[3] := (packedBCD[0] >> 12) &amp; 0x000F; //Correct for errors due to sign extension
      unpackedBCD[4] := (packedBCD[1] &amp; 0x000F); unpackedBCD[5] := (packedBCD[1] &amp; 0x00F0) >> 4; unpackedBCD[6] := (packedBCD[1] &amp; 0x0F00) >> 8; unpackedBCD[7] := (packedBCD[1] >> 12) &amp; 0x000F; //Correct for errors due to sign extension
      unpackedBCD[8] := (packedBCD[2] &amp; 0x000F); unpackedBCD[9] := (packedBCD[2] &amp; 0x00F0) >> 4; t_end := sys_T();
      print("Unpacked BCD array:"); for(y:=9;y>=0;y--) print(unpackedBCD[y]); next print("\n"); // t_end := sys_T(); print("Timer Start: ",t_start,"\n"); print("Timer End: ",t_end,"\n"); print("Total Time: ",t_end - t_start,"\n");repeatforever
      Best Regards,


      • #4
        Here is another conversion routine, this one is much faster as it takes advantage of the built-in str_printf() function. This one performs the conversion in about 1 ms.....
        func Convert2Bcd2(var MSW, var LSW) var private BCD_Array[12]; //Array to hold the unpacked BCD values. LSB in [0] var private isnegative; //Flag to tell us if the result should be interpreted as negative var buff[2]; //Array to hold the 4 bytes in memory var prt_buf[6]; //Array to hold the packed ASCII bytes, each word holds 2 Ascii Chars var ptr; //Generic Pointer var pb_len; //Length of the packed ASCII string var i;// var tmr_start,tmr_end;// tmr_start := sys_T();
        if (MSW<0) //Is the number negative? isnegative := TRUE; //Yes, so...... MSW := (MSW ^ 0xFFFF); //Invert MSB LSW := (LSW ^ 0xFFFF); //Invert LSB LSW := LSW+1; //Add 1 if(LSW==0) MSW+=1; //If LSB rolled over, increment MSB else isnegative := FALSE; //Number is not negative endif
        buff[0]:=LSW; //Correctly orders the bytes in mem buff[1]:=MSW;
        ptr:=str_Ptr(buff); //Get a byte pointer to 4 byte array to(prt_buf); str_Printf(&amp;ptr,"%lu");//Convert 4 bytes to unsigned long decimal ASCII Chars and stuff into buffer// to(prt_buf); str_Printf(&amp;ptr,"%ld");//Convert 4 bytes to signed long decimal ASCII Chars and stuff into buffer
        pb_len:=strlen(prt_buf)-1; //Get the number of ASCII chars, -1 to convert to array byte offset ptr := str_Ptr(prt_buf) + pb_len; //Point to the one's digit in the array
        mem_Set(BCD_Array,0x00,sizeof(BCD_Array)*2); //Zero out the BCD_Array
        for(i:=0;i<=pb_len;i++) //Read the ASCII bytes from the array BCD_Array[i] := str_GetByte(ptr--) - '0'; //Store bytes so ones digit is in lowest array index next //This way we always know where the LSB is and what its value is
        // for(i:=0;i<sizeof(BCD_Array);i++)// print(" 0x",[HEX2]BCD_Array[i]);// next// tmr_end := sys_T();// print("\nElapsed time: ",tmr_end-tmr_start," mS...");endfunc
        Best Regards,