Shop OBEX P1 Docs P2 Docs Learn Events
integer to ASCII object? — Parallax Forums

integer to ASCII object?

JonathanJonathan Posts: 1,023
edited 2015-01-15 14:33 in Propeller 1
Hi All,

I googled and searched the obex but didn't find an integer to ascii converter. I did see reference to there being something of the sort in PASM in fullduplexserial and similar, but not being a ASM guy I couldn't figure it out.

Before I start trying to write one, does anyone have one handy?

Thanks!

Jonathan

Comments

  • Duane DegnDuane Degn Posts: 10,588
    edited 2015-01-15 10:43
    There are lots of objects floating around to do this. The "Dec" method in most serial drivers give an example of converting numbers to ASCII characters.

    The "Numbers" object in the Propeller Library has methods to format numbers as characters in a string.

    I like to use the object "StrFmt.spin" when converting variable to characters. There's a copy of the object in my GitHub "EddieFirmware" repository.
  • Dave HeinDave Hein Posts: 6,347
    edited 2015-01-15 10:49
    Here's the routine I use in the CLIB object.
    PRI itoa10(number, str) | str0, divisor, temp
    {{
      This private routine is used to convert a signed integer contained in
      "number" to a decimal character string.
    }}
      str0 := str
      if (number < 0)
        byte[str++] := "-"
        if (number == $80000000)
          byte[str++] := "2"
          number += 2_000_000_000
        number := -number
      elseif (number == 0)
        byte[str++] := "0"
        byte[str] := 0
        return 1
      divisor := 1_000_000_000
      repeat while (divisor > number)
        divisor /= 10
      repeat while (divisor > 0)
        temp := number / divisor
        byte[str++] := temp + "0"
        number -= temp * divisor
        divisor /= 10
      byte[str++] := 0
      return str - str0 - 1
    
  • JonathanJonathan Posts: 1,023
    edited 2015-01-15 10:50
    Thanks Duane. I'm looking at a DEC function but can't seem to make sense of what it is doing. I'll keep noodling.

    Jonathan
  • ElectrodudeElectrodude Posts: 1,658
    edited 2015-01-15 11:41
    The integer to ascii converter functions in FullDuplexSerial are written in Spin. Only the actualy UART driver (which doesn't care what its data is) is written in PASM.
  • pik33pik33 Posts: 2,366
    edited 2015-01-15 11:41
    These are ttwo functions from my P1V retromachine vga driver. The first outputs decimal string; the second outputs hex string.
    ' add this in var section
    byte n_string[12]  ' string buffer for inttostr and hextostr   
    
    
    pub inttostr(i) |q,pos,k,j
    
    '********************************************************************************
    '
    '             Convert integer to dec string
    '             Return a pointer
    '
    '********************************************************************************
    
    j:=i
    pos:=10
    k:=0
    
    if (j==0)
      return string ("0")
    
    if (j<0)
      j:=0-j
      k:=45
    
    n_string[11]:=0
    repeat while (pos>-1)
      q:=j//10
      q:=48+q
      n_string[pos]:=q
      j:=j/10
      pos-=1
    repeat while n_string[0]==48
      bytemove(@n_string,@n_string+1,12)
    
    if k==45
       bytemove(@n_string+1,@n_string,12)
       n_string[0]:=k
    
    result:=@n_string
    
    
    pub hextostr(i) |q,pos,k,j
    
    
    '********************************************************************************
    '
    '             Convert integer to hex string
    '             Return a pointer
    '
    '********************************************************************************
    
    j:=i
    pos:=10
    k:=0
    
    if (j==0)
      return string ("0")
    
    if (j<0)
      j:=0-j
      k:=45
    
    n_string[11]:=0
    repeat while (pos>-1)
      q:=j//16
      if (q>9)
        q:=q+7
      q:=48+q
      n_string[pos]:=q
      j:=j/16
      pos-=1
    repeat while n_string[0]==48
      bytemove(@n_string,@n_string+1,12)
    
    if k==45
       bytemove(@n_string+1,@n_string,12)
       n_string[0]:=k
    result:=@n_string
    
    
  • Duane DegnDuane Degn Posts: 10,588
    edited 2015-01-15 11:51
    Not that's likely to be an issue very often but I think your method will incorrectly display the max negative value. If you take a look at Dave's code, you can see he has an exception for $80000000.

    Also, FYI, "j"=0-j" can be written as "-j". When the variable is by itself the minus sign negates the variable's value. Dave's "number := -number" could also be reduced to "-number".
  • lonesocklonesock Posts: 917
    edited 2015-01-15 13:39
    This one is decently small Spin code:
    PUB Dec( value ) | denom
    {{
      * Sends a decimal number over the serial link.
      > value : the number to send.
    
      e.g. Dec( 10 ) ' sends "10"
    }}
      ' if negative, note that
      if value < 0
        ||value
        tx( "-" )
      ' start with the largest possible power of 10 to fit in 32 signed bits
      denom := 1_000_000_000
      repeat 9
        ' I have a non-0 digit, or we already had one
        if result |= (value => denom)
          tx( value / denom + "0" )
        value //= denom
        denom /= 10
      ' always show the last character (and denom == 1)
      tx( value + "0" )
    
    Jonathan
  • JonathanJonathan Posts: 1,023
    edited 2015-01-15 14:03
    First, many thanks for the responses.

    I have spent the last while reading and boy, my ignorance is amazing. For starters, I wasn't really asking the right question. I think I'll start a more appropriately titled thread.

    @Jonathan - that is a useful snip. I'll need that. Thanks.
  • tonyp12tonyp12 Posts: 1,951
    edited 2015-01-15 14:27
    Here is a PASM version I made.
    It does not take in to account that Spin variables are signed and can be negative, maybe I update that.
    { Sends a 10 character DEC of a HUB Address value, at a fixed interval }
    
    PUB start(address)
        cognew (@entry,address)
    
    DAT           org 0
    entry         mov       DIRA,_bit30
                  mov       cnt,#7                  '7 cycle overhead
                  add       cnt,cnt                 'add current cnt
    loop1         waitcnt   cnt,#200                'wait and then add 200 for below overhead
                  rdlong    temp,PAR
                  movs      decimal,#table     
                  mov       charcnt,#11            '10 dec chars in a long + space
    loop2         mov       uartTx,#48             'start at ASCII for "0"
    decimal       cmpsub    temp,0-0 wc            'try 1 Billion first
            if_c  add       uartTx,#1
            if_c  jmp       #decimal      
                  cmp       charcnt,#1 wz           'last charter one?
            if_z  mov       uartTX,#32              'replace with space
                  or        uartTx,#$100            'set stopbit
                  shl       uartTx,#1               'merge in startbit               
                  mov       bitcnt,#10              '10bit uart
    loop3         waitcnt   cnt,_baud
                  shr       UartTx,#1 wc
                  muxc      OUTA,_bit30
                  djnz      bitcnt,#loop3
                  add       decimal,#1              'try 100mill next        
                  djnz      charcnt,#loop2
                  add       cnt,_second             'restart main loop with 1sec delay
                  jmp       #loop1
                  
    _second long 80_000_000                         '/2 or /4 if you want shorter delay (insert -76540 if you want absolute sec-to-sec timing)
    _baud   long 80_000_000/115200
    _bit30  long |<30
    table   long 1_000_000_000, 100_000_000, 10_000_000, 1_000_000, 100_000, 10_000, 1_000, 100, 10, 1,1 
    temp    res 1
    charcnt res 1
    bitcnt  res 1
    uartTx  res 1
    
  • Duane DegnDuane Degn Posts: 10,588
    edited 2015-01-15 14:33
    tonyp12 wrote: »
    Here is a PASM version I made.

    Very cool.

    I've wondered about reading messages directly in PASM. I'm pretty sure manipulating characters in Spin is a bottleneck in many of my programs.

    Thanks for posting your code Tony.
Sign In or Register to comment.