Shop OBEX P1 Docs P2 Docs Learn Events
Displaying WORD variable as DEC? — Parallax Forums

Displaying WORD variable as DEC?

John CoutureJohn Couture Posts: 370
edited 2007-03-20 17:45 in General Discussion
Guys and Gals,

I admit it, I need help.· You all have been very helpful and have sent me to sites with the answers but I can't seem to make it work.·

I need a simple routine that will enable me to display the contents of a 16bit variable as a DEC·value (ASCII).· Something like the following where you hand it a WORD variable and it sets up something like a DATA string (zero terminated).· That way you can use Jon Williams TX_·OUT routine to display the value on an LCD or Terminal.· With the new WORD variables, has anyone developed one yet?

'
TX_Dec16:
' Use: TX_Dec16 word
' -- Send a word variable and set six contiguous bytes to
'··· the ASCII Decimal.·
'··· Example:· C351h would return "50001",0 in an array?




▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
John J. Couture

San Diego Miramar College

Comments

  • Michael ChadwickMichael Chadwick Posts: 80
    edited 2006-08-01 17:56
    Hi John,

    Check this post:

    http://forums.parallax.com/showthread.php?p=579269

    There are two routines listed, the first in assembly, the second as an SXB subroutine.· The second is faster and of course is usable from SXB.· It doesn't add a zero to the end of the output array, but that would be trivial to add.· At the very end before the return, add the following:

    inc FSR
    mov ind,#00

    It isn't exactly what you want, but should be adaptable to the word variables.· It might be usable as is by calling it with the address of the word variable as the first argument, by prefixing it with @.· As soon as I get time, I'll try it and if required modify it to work properly, unless you get it done first and post the new code.

    I'm not sure what order TX_ out wants the output array, but it is currently created most significant digit first at output_array[noparse][[/noparse]0], which is how I would expect it would want it to be sent to a serial output.

    Hmm, it also occurs to me that it would be trivial to add leading zero blanking if you want that too.· But maybe that should be done as a separate output routine.· Currently the output is just 5 digits, leading zeros included.







    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    MRC

    Post Edited (Michael Chadwick) : 8/1/2006 6:17:20 PM GMT
  • BeanBean Posts: 8,129
    edited 2006-08-01 18:00
    John,
    Here is how I do it with the HC4LED modules. I know it looks clunky, but the code is smaller than using "/ 1000", "/ 100", ect.
    http://forums.parallax.com/attachment.php?attachmentid=42396

    Bean.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Cheap 4-digit LED display with driver IC·www.hc4led.com

    Low power SD Data Logger www.sddatalogger.com

    "You're braver than you believe, stronger than you seem, and smarter than you think" Christopher Robin to Pooh
    ·
  • John CoutureJohn Couture Posts: 370
    edited 2006-08-02 00:44
    Thank you Michael and Bean, that helped a lot.

    Bean with your new Word variables it seems we can do a lot more.· Based on the examples both you and Michael provided here is a derivative work that should handle values up to $FFFF (65,000).· I took out the negative sign stuff:


    '
    Bin16DEC:
    ' Use: Bin16DEC word
    ' -- Convert a 16bit binary variable into a decimal value.
    '··· Note add 30h to each ascDigit to directly output
    '··· to a terminal or LCD.
    '··· Original versions by Bean (Hitt Consulting) & Michael Chadwick
    '
    ' Setup
    '··· wrdTemp··· var WORD
    '··· wrcDivisor var WORD
    '··· ascDigit·· var Byte(5)

    ·· IF __PARAMCNT = 1 THEN·· ' if parameter is a Byte or Word variable
    ···· wrdTemp = __PARAM1
    ·· ELSE
    ···· wrdTemp = __WPARAM12
    ·· ENDIF

    ·· ' fill all locations with blanks
    ·· PUT ascDigit, BLANK, BLANK, BLANK, BLANK, BLANK· 'updated line

    Bin16DEC1:
    ·· x1 = 4··································· ' position in array
    ·· wrdDivisor = 10000······················· ' set initial power of 10

    Bin16DEC2:
    ·· IF wrdTemp < wrdDivisor THEN Bin16DEC3··· ' continue to loop?
    ····· inc ascDigit(x1)······················ ' increment digit in appropriate position
    ····· wrdTemp = wrdTemp - wrdDivisor·········' subtract 10 power from word variable
    ····· goto Bin16DEC2

    Bin16DEC3:
    ·· dec x1··································· ' decrement·position counter
    ·· wrdDivisor = wrdDivisor / 10············· ' divide power of 10
    ·· if x1 > 0 THEN Bin16DEC2················· ' more digits to process?
    ·· ascDigit(x1) = wrdTemp_LSB··············· ' take care of last (right most) digit
    · RETURN·

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    John J. Couture

    San Diego Miramar College

    Post Edited (John Couture) : 8/2/2006 2:07:11 AM GMT
  • BeanBean Posts: 8,129
    edited 2006-08-02 01:53
    John,
    That's pretty cool. Yeah, those WORD variables really come in handy don't they...

    Since the HC4LED only has 4 digits it didn't make sense to support values > 9999, so I made it support negative numbers.

    Now that I see your code, I might change mine to use your "divisor = divisor / 10". But I know that divide is going to generate a good bit of code, of course it's only used once. Hmmm...

    Bean.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Cheap 4-digit LED display with driver IC·www.hc4led.com

    Low power SD Data Logger www.sddatalogger.com

    "You're braver than you believe, stronger than you seem, and smarter than you think" Christopher Robin to Pooh
    ·
  • John CoutureJohn Couture Posts: 370
    edited 2006-08-02 02:08
    Yea, a while back I was trying to come up with an easy and cheap divide by 10 routine using SHIFT commands .... divide by 2 is easy ... it was the divide by 5 that was tough. If I can think of an easy way to do it with Shift commands, I'll post it.

    Hmmmm.

    What if we replaced the divisor = divisor / 10 with a tight loop that subtracted 10 each time?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    John J. Couture

    San Diego Miramar College

    Post Edited (John Couture) : 8/2/2006 2:15:03 AM GMT
  • Michael ChadwickMichael Chadwick Posts: 80
    edited 2006-08-02 03:14
    After the 10000s are subtracted, you need to subtract 1000s, 100s then 10s. I think using the READ command to get the next wrdDivisor might be the fastest way to do it. Use the digit index as the offset for the READ command.

    In the process of trying this idea, I discovered that SXB isn't generating the correct code for the READ command with WDATA values. It needs to add twice the index value to the base of the WDATA table in order to index to the correct value in. It is only adding it once.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    MRC
  • Michael ChadwickMichael Chadwick Posts: 80
    edited 2006-08-02 04:30
    Hi John,

    Here is a revised version that uses WDATA to look up the divisor.· I also changed the test order to speed that up a little.· Converting 12345d the original with the wrdDivisor= wrdDivisor / 10 took 505.5 us at a 4Mhz clock, using the data statements it takes 130.5 uS.· This compares to 45.25 for the assembly version using Golovchenko's code.· I'm going to do an SXB version of Golovchenko's code using the data lookup to see how that compares.· In the mean time, here is the revised subtract by powers of 10 code using WDATA with work around for the READ bug when using word values.

    I also made a tiny change that allows you to set BLANK as a constant to either 0, if you want BCD nibbles, or $30 if you want ASCII digits.
    '---------------------------------------------------------------------------
    Bin16DEC:
    ' Use: Bin16DEC word
    ' -- Convert a 16bit binary variable into a decimal value.
    '    define BLANK as 00h for BCD nibbles
    '    define BLANK as 30h to directly output ASCII
    '    to a terminal or LCD.
    '    Original versions by Bean (Hitt Consulting) & Michael Chadwick
    '
    ' Setup
    '    wrdTemp    var WORD
    '    wrcDivisor var WORD
    '    ascDigit   var Byte(5)
     
       IF __PARAMCNT = 1 THEN   ' if parameter is a Byte or Word variable
         wrdTemp = __PARAM1
       ELSE
         wrdTemp = __WPARAM12
       ENDIF
     
       ' fill all locations with blanks
       PUT ascDigit(0), BLANK, BLANK, BLANK, BLANK, BLANK  'updated line
     
       x1 = 4                                    ' position in array
       wrdDivisor = -10000                        ' set initial power of 10
     
    Bin16DEC1:
       inc ascDigit(x1)        ' assume we will succeed in subtraction
       wrdTemp = wrdTemp + wrdDivisor      ' try the subtraction
       if C = 1 then Bin16DEC1       ' OK, try again
       dec ascDigit(x1)
       wrdTemp = wrdTemp - wrdDivisor
       dec x1                                    ' decrement position counter
       if x1 = 0 THEN Bin16DEC2                  ' more digits to process?
       x1= x1 SHL 1         ' * 2 as a work around for the read bug
       READ divisors + x1,  wrdDivisor
       wrdDivisor= 0-wrdDivisor
       x1= x1 SHR 1         ' / 2 as work around for the read bug
       goto Bin16DEC1
     
    Bin16DEC2:
       ascDigit(x1) = ascDigit (x1) + wrdTemp_LSB   ' take care of last (right most) digit
      RETURN  
     
    divisors:
     WDATA 1,10,100,1000
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    MRC
  • BeanBean Posts: 8,129
    edited 2006-08-02 14:09
    Okay, Here is my routine. I kind of combined everything that has been posted in this thread.
    I think it's pretty neat and clean...
    '---------------------------------------------------------------------------
    Bin16DEC:
    ' Use: Bin16DEC word
    ' -- Convert a 16bit binary variable into a decimal value.
    '    define BLANK as 00h for BCD nibbles
    '    define BLANK as 30h to directly output ASCII
    '    to a terminal or LCD.
    '    Original versions by Bean (Hitt Consulting) & Michael Chadwick & John Couture
    '
    ' Setup
    '    temp       VAR Byte
    '    wTemp      VAR Word
    '    wDivisor   VAR Word
    '    ascDigit   VAR Byte (5)
     
      IF __PARAMCNT = 1 THEN   ' if parameter is a Byte or Word variable
        wTemp = __PARAM1
      ELSE
        wTemp = __WPARAM12
      ENDIF
     
      ' fill all locations with zeros
      PUT ascDigit(0), BLANK, BLANK, BLANK, BLANK, BLANK
     
      ' Loop for first 4 digits
      FOR temp = 0 TO 3
        ' Get divisior for this digit
        LOOKUP temp, 10000, 1000, 100, 10, wDivisor
        ' Increase digit until value < divisor
        DO UNTIL wTemp < wDivisor
          INC ascDigit(temp)
          wTemp = wTemp - wDivisor
        LOOP
      NEXT
    
      ' Last digit is just units, so just add it
      ascDigit(4) = ascDigit(4) + wTemp_LSB
      RETURN  
     
    

    P.S.·· This is 131 uSec @ 4MHz measured from SXSim

    Bean.
    ·

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Cheap 4-digit LED display with driver IC·www.hc4led.com

    Low power SD Data Logger www.sddatalogger.com

    "You're braver than you believe, stronger than you seem, and smarter than you think" Christopher Robin to Pooh


    Post Edited (Bean (Hitt Consulting)) : 8/2/2006 2:19:56 PM GMT
  • Michael ChadwickMichael Chadwick Posts: 80
    edited 2006-08-02 14:40
    Nice and concise!·

    And fixes a bug in my version, related to the final carry of a multibyte subtraction or addition not reflecting the proper result, because of the way intermediate carries have to be handled on the SX.

    100 bytes for SXB vs 99 for the assembly version, not a bad trade off for understandability.· The assembler version·does run about 3x faster though. [noparse]:)[/noparse]



    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    MRC
  • John CoutureJohn Couture Posts: 370
    edited 2006-08-02 17:22
    A sort of lookup was what I was thinking about this morning too before I logged on (great minds think alike smile.gif. Anyway, Bean my original design did not have the traditional DO WHILE inside a FOR NEXT because I thought I had trouble with that in the past. I guess that is the nature of research, never leave a rock unturned. Wow, great work all!

    Michael, (grin) the assembler does work faster .... You know, maybe we should convince Bean to allow the development of "objects" for SX/B that can be loaded at will (that thump was the sound of Bean hitting the floor after passing out with the realization of how much work THAT would be!) smile.gif

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    John J. Couture

    San Diego Miramar College
  • Capt. QuirkCapt. Quirk Posts: 872
    edited 2007-03-14 22:00
    Old thread question,

    What applications are these binary to decimal converters used for?, Serial Data?, why?
  • BeanBean Posts: 8,129
    edited 2007-03-14 22:05
    Yes, to send a value as ASCII to a serial LCD or whatever.
    Why ? How else would you display a variable on a serial device ?

    Bean.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    "A problem well defined is a problem half solved"

    "Just because you're approved, doesn't mean you can afford it."
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Cheap used 4-digit LED display with driver IC·www.hc4led.com
    Low power SD Data Logger www.sddatalogger.com
    SX-Video Display Modules www.sxvm.com
    Coming soon! Propeller based OSD module www.hittconsulting.com
    ·
  • John CoutureJohn Couture Posts: 370
    edited 2007-03-14 22:25
    Capt,

    At the time I was trying to read a sensor that had a 16 bit variable and wanted to be able to display that value on the LCD .... I was hoping for a simple solution like the BS2 has (grin). Bean has done an outstanding job putting in some kool statements.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    John J. Couture

    San Diego Miramar College
  • Capt. QuirkCapt. Quirk Posts: 872
    edited 2007-03-15 06:35
    I thought you could send Binary, Hex and Decimal equivilants for ascii charaters. It's because ascii is 7 or 8 bit, so you have to convert it to 2, 8 bit values in order to pass it through the SX?

    This thread's routines were also similar to one that Bean helped me out with that replaced the BS2 version of R_J_Value for a parallel LCD ( a similar portion of his HC4LED program). I have been doing a lot of work with it the last few days, I can get it to work perfectly with DEBUG, but it just prints out blanks on the lcd. I thought that one of these other programs may be helpful, But I did not understand them.



    Post Edited (Capt. Quirk) : 3/15/2007 6:53:36 AM GMT
  • PJMontyPJMonty Posts: 983
    edited 2007-03-20 17:45
    Capt. Quirk,

    Computers store numbers internally in binary. LCDs, serial terminals, etc, all use ASCII to display anything. It's like the difference between "3" and "three". The first is a number you can add using math, the second is the English word version of the same number. You have to convert binary numbers to ASCII strings in order to display them.

    Thanks,
    PeterM
Sign In or Register to comment.