Shop OBEX P1 Docs P2 Docs Learn Events
Serial Terminals and String Manipulation — Parallax Forums

Serial Terminals and String Manipulation

CumQuaTCumQuaT Posts: 156
edited 2011-03-06 19:11 in Propeller 1
Hi all,

Looking around the OBEX, I can see a number of fun looking data manipulation objects, but nothing PRECISELY like what I'm after (but please prove me wrong if I am, since it will help)

I have 4 long variables that I am transmitting back to my PC from my propellor, and I can submit each one back to the PC individually with no problems. However, what I would like to do is send them all back at once in a single long string, separated by colons.

So, instead of sending back data that looks like this:

532
634
12
1022

I would send back a single string that looks like this:

532:634:12:1022

Also, for a bonus question... I would like to add a mask to my numbers so that they always get returned back as 4 digit numbers, filling in the gaps with extra zeros, like so:

0532:0634:0012:1022

But I can't for the life of me work out a way of doing this... Does anyone have any ideas?

Comments

  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-03-06 03:33
    Kyedos has some bonus string handling routines that I added to do this sort of thing. They replicate Basic string handling. In Basic syntax. Bear with me with the Basic code because it is pretty easy to then convert to Spin. I'll write this the long way rather than trying to do everything on one line. You can make this a lot shorter if you want, eg by putting things in subroutines
    Dim Variable1 as Long
    Dim Variable2 as Long
    Dim Variable3 as Long
    Dim Variable4 as Long
    Dim LineOfText as String
    Dim TempString as String
    
    Variable1 = 532
    Variable2 = 634
    Variable3 = 12
    Variable4 = 1022
    LineofText = ""
    TempString = strings.str(Variable1)
    TempString = "0000" + TempString
    TempString = strings.right(Tempstring,4)
    LineofText = LineOfText + Tempstring + ":"
    TempString = string.str(Variable2)
    TempString = "0000" + TempString
    TempString = strings.right(Tempstring,4)
    LineofText = LineOfText + Tempstring + ":"
    TempString = string.str(Variable3)
    TempString = "0000" + TempString
    TempString = strings.right(Tempstring,4)
    LineofText = LineOfText + Tempstring + ":"
    TempString = string.str(Variable4)
    TempString = "0000" + TempString
    TempString = strings.right(Tempstring,4)
    LineofText = LineOfText + Tempstring
    ' and now send out 
    
    

    Attached is Kyedos, and the bit you want is the string handler ASCII0_STREngine.spin Down the bottom are some of the Basic type string methods.

    To use these, create some string space in the main program. Kyedos itself has this in its main program, but to summarise the important bits
    OBJ
      str: "ASCII0_STREngine.spin"
    

    and
    VAR
       byte TempString[80] ' temporary string buffer
       byte LineOfText1[80] ' general purpose string buffer
    

    String handling is still not quite as simple as in Basic, eg joining two strings is a function in the string handler rather than just using +

    This is a summary of some of the routines I used to test out these strings
    ' ***************************************************************************************
          'printstring(@lineoftext1)                         ' testing string functions
          'str.left(@lineoftext1,@lineoftext2,3)  ' find leftmost characters in a string
          'printstring(@lineoftext2)
          'str.trimstring(@lineoftext1)
          'printstring(@lineoftext1)
          'str.trimstring(@lineoftext1)
          'str.mid(@lineoftext1,@lineoftext2,4,2) ' find middle characters in a string
          'printstring(@lineoftext2)
          'printstring(str.integertodecimal(str.len(@lineoftext2),5))
          'str.copy(string("hello"),@lineoftext1) ' copy fixed value into a string
          'printstring(@lineoftext1)
          'str.str(@lineoftext1,55) ' decimal to string with no leading zeros
          'printstring(@lineoftext1)
          'str.stringfill(@lineoftext1,10,65)
          'printstring(@lineoftext1)
          'str.str(@lineoftext1,1234)' convert to string
          'str.str(@lineoftext1,str.decimaltointeger(@lineoftext1)) ' convert back
          'printstring(@lineoftext1)
          ' str.left(@lineoftext1,@lineoftext2,str.len(@lineoftext1)-4) ' remove extension
          ' printstring(@lineoftext2) ' print it out
    

    Most of the bits you need are in there, eg str.str (which is the same as strings.str).

    The catch is that strings.right has not been written (yet). But you can replicate this in other ways that might be neater anyway. Instead of adding 4 zeros, then taking the right most 4 characters, first, convert your number to a string, then get the length of the string. (str.len) Subtract this number from 4, and add that many zeros using a loop and str.StringConcatenate

    Full zip of Kyedos is attached but you will only be needing the strings object.

    If you want to add characters between the numbers, eg a comma or a colon, add those with str.StringConcatenate

    You might need to add a str.trim after converting the number to a string as there is a leading (hidden) space for positive numbers.
  • CumQuaTCumQuaT Posts: 156
    edited 2011-03-06 04:14
    You, sir, are a gentleman. I couldn't have asked for a more thorough an informative reply. Thank you very much!
  • Dave HeinDave Hein Posts: 6,347
    edited 2011-03-06 06:21
    Or you could use CLIB and just do c.printf4(string("%04d:%04d:04d:%04d"), num1, num2, num3, num4). :)
  • CumQuaTCumQuaT Posts: 156
    edited 2011-03-06 07:43
    Good golly, Miss Molly. That's a lot more to the point! Thanks!
  • JonnyMacJonnyMac Posts: 9,208
    edited 2011-03-06 09:10
    Here's another tool for the box -- I use this method in a custom serial driver
    pub rjdec(value, width, pad) | divisor, zflag, c
    
    '' Print decimal value in field "width" characters wide
    '' -- only works with positive #s
    '' -- pad is character for left-side padding
    
      ||value                                               ' remove sign
      width := 1 #> width <# 9                              ' limit field width
      divisor := 1                                          ' prep initial divisor
      repeat width
        divisor *= 10 
      value //= divisor                                     ' truncate value to fit in field
      zflag := 0                                            ' clear print zero flag
    
      repeat width
        divisor := (divisor / 10) #> 1                      ' prep divisor  
        c := (value / divisor) + "0"                        ' digit to ASCII
        zflag |= ((c <> "0") | (divisor == 1))              ' update zero flag
        if zflag                                            ' if flag tripped
          tx(c)                                             '   print char
        else                                                ' else
          tx(pad)                                           '   print pad character
        value //= divisor                                   ' prep for next digit
    
  • CumQuaTCumQuaT Posts: 156
    edited 2011-03-06 19:11
    Very cool, Jonny! Thanks for the contribution!
Sign In or Register to comment.