Decoding serial input
DiverBob
Posts: 1,125
It's getting late and my mind has decided it doesn't want to play anymore! A search through the forum didn't help so I'll ask here.
I want to output a series of numbers using the Parallax Serial Terminal object. The series will consist of a "T" for a start indication, a comma, a number, comma, and another number ("T",n,nnn). I can type the series into the serial terminal but my attempts at decoding it in the prop are falling flat. Any similar examples available out there?
Thanks
I want to output a series of numbers using the Parallax Serial Terminal object. The series will consist of a "T" for a start indication, a comma, a number, comma, and another number ("T",n,nnn). I can type the series into the serial terminal but my attempts at decoding it in the prop are falling flat. Any similar examples available out there?
Thanks

Comments
Well that's straightforward in Forth but you can do something similar in Spin by simply sitting in a loop which tests for digits and shifts them into an accumulator ( acc := (acc*10) + (char-$30). So when you encounter a non-digit you simply terminate with the result as the number. So this will work with commas or end-of-line but the T should be passed in a variable so that the app knows to disregard the result and synch or whatever. Not quite sure why you need to say "T" with the quotes though, it seems very redundant. Personally I would just use a symbol like a colon immediately followed by the first number :n,nnn
I'm a bit confused by your post. You say you want to output (from the Prop) data in the given format, but the title and subsequent comments seem to indicate an input (to the Prop) operation. Which is it?
-Phil
Last night I couldn't figure out how to parse the input string into its different components. This morning I'm doing better and have a couple of ideas to test tonight but as long as I've asked the question it would be nice to see how others have solved this type of issue. Oh yes, the T is just a transmit character to indicate the start of the command sequence, I just typed quotes around it, seemed like a good idea at the time...
That would be my starting point..
Massimo
#include <stdio.h> char buffer[100]; int main(void) { int int1, int2; while (gets(buffer)) { if (sscanf(buffer, "T,%d,%d", &int1, &int2) == 2) printf("int1 = %d, int2 = %d\n", int1, int2); } return 0; }I've tested this with GCC under Cygwin, and it correctly decodes a string with the format "T,#,#". It rejects any string that does not follow that exact format. I haven't tested this under PropGCC so I don't know if it works exactly the same.EDIT: I tested it with PropGCC, and it works correctly on the Prop also.
Maybe someone else can see where I went wrong:The program as it stands works until I add in the commented out lines and then comment out the line teststr := string("$T,1,2,345")
con _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 CLK_FREQ = ((_clkmode - xtal1) >> 6) * _xinfreq MS_001 = CLK_FREQ / 1_000 con RX1 = 31 TX1 = 30 SDA = 29 SCL = 28 CS = 27 CLK = 26 DIO = 9 obj io : "FullDuplexSerialPlus" re : "regex" pub main Serialtest pub SerialTest | teststr, pattern, resaddr, rslt, i 'test inputing data from PST and echoing it back to the PST ' input string format: "$T,1,2,345" io.start(31, 30, 0, 9600) io.tx(16) ' repeat ' pauseMSec(1000) ' io.Str(String(pst#NL, "Enter command: ")) ' io.getstr(teststr) teststr := string("$T,1,2,345") pattern := string("\$T\s*,($1[\d])\s*,($2[\d])\s*,($3[\d]+)\s*") io.str(string("String:", 13, 13)) io.str(teststr) io.str(string(13, 13, "Pattern:", 13, 13)) io.str(pattern) rslt := -cnt resaddr := re.match(teststr, pattern, re#NOALT) rslt += cnt io.str(string(13, 13, "Time: ")) io.dec(rslt / 80_000) io.str(string(" ms.")) io.str(string(13, 13, "Results:", 13)) if (resaddr < 0) io.tx(13) io.str(string("Error #")) io.dec(-resaddr) elseif (resaddr == 0) io.tx(13) io.str(string("No match.")) else repeat i from 0 to 9 if (rslt := long[resaddr][i]) io.tx(13) io.dec(i) io.str(string(": ")) io.str(re.field(i)) io.str(string(13, 13, "Remainder of string:", 13, 13)) io.str(re.remainder) PUB pauseMSec(Duration) '' Pause execution in milliseconds. '' Duration = number of milliseconds to delay waitcnt(((clkfreq / 1_000 * Duration - 3932) #> 381) + cnt)SerialParsingTest - Archive [Date 2014.06.11 Time 21.34].zip
VAR [COLOR="#FF0000"]byte buffer[128][/COLOR] PUB SerialTest | teststr, pattern, resaddr, rslt, i 'test inputing data from PST and echoing it back to the PST ' input string format: "$T,1,2,345" io.start(31, 30, 0, 9600) io.tx(16) repeat pauseMSec(1000) io.Str(String(pst#NL, "Enter command: ")) io.getstr(teststr[COLOR="#FF0000"] := @buffer{0}[/COLOR]) pattern := string("\$T\s*,($1[\d])\s*,($2[\d])\s*,($3[\d]+)\s*") ...Currently you'd pass a random stack value (uninitialised local variable).Check out this book and the associated code:
http://www.parallax.com/product/32316
ftp://ftp.propeller-chip.com/
There is a terminal project included there that contains some great token parser routine. Even without the book the code should be useful to you as it is well commented.
That worked! I went back and looked at the getstr() command in FullDuplex SerialPlus, don't know why I missed seeing that it needed a string pointer...
Thanks for the help. Now to get back to work on using the information!
con _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 CLK_FREQ = ((_clkmode - xtal1) >> 6) * _xinfreq MS_001 = CLK_FREQ / 1_000 con RX1 = 31 TX1 = 30 SDA = 29 SCL = 28 CS = 27 CLK = 26 DIO = 9 var byte buffer[128] word leg, command, parameter obj io : "FullDuplexSerialPlus" re : "regex" pub main Serialtest pub SerialTest | teststr, pattern, resaddr, rslt, i 'test inputing data from PST and echoing it back to the PST ' input string format: "$T,1,2,345" io.start(31, 30, 0, 9600) io.tx(13) repeat pauseMSec(1000) io.Str(String("Enter command: ")) io.getstr(teststr := @buffer{0}) ' teststr := string("$,1,2,345") pattern := string("\$\s*,($1[\d])\s*,($2[\d])\s*,($3[\d]+)\s*") rslt := -cnt resaddr := re.match(teststr, pattern, re#NOALT) rslt += cnt if (resaddr < 0) io.tx(13) io.str(string("Error #")) io.dec(-resaddr) elseif (resaddr == 0) io.tx(13) io.str(string("No match.")) else repeat i from 0 to 3 if (rslt := long[resaddr][i]) io.tx(13) io.dec(i) io.str(string(": ")) io.str(re.field(i)) case i 1: leg := re.field(i) 2: command := re.field(i) 3: parameter := re.field(i) io.tx(13) io.str(string("Leg: ")) io.dec(leg) io.tx(13) io.str(string("Command: ")) io.dec(command) io.tx(13) io.str(string("Parameter: ")) io.dec(parameter) io.tx(13) io.tx(13) PUB pauseMSec(Duration) '' Pause execution in milliseconds. '' Duration = number of milliseconds to delay waitcnt(((clkfreq / 1_000 * Duration - 3932) #> 381) + cnt)The problem is when I attempt to assign the values to the Leg, command, and parameter variables. Here is the output I'm getting when entering a string of $,1,2,345 in to the program:
Hopefully someone will see what mistake I'm making here.
SerialParsingTest - Archive [Date 2014.06.14 Time 15.01].zip
John Abshier
John Abshier
See http://forums.parallax.com/showthread.php/122295-Converting-string-to-decimal?p=905112&viewfull=1#post905112
That should do it for you
You can find other relevant/useful links with the following google search:
https://www.google.ca/#q=string+to+integer+in+spin+for+propeller
Hope that helps!
Bill
Some Forum glitch. You need to replace attachment.php by the correct filename to save.
It is doing this for a while now. Filename always shows as attachment.php.
Enjoy!
Mike
[SIZE=1][FONT=courier new]CON _clkmode = xtal1 + pll16x ' _xinfreq = 5_000_000 N_VALUES = 3 LAST_INDEX = N_VALUES - 1 VAR long idx, value[N_VALUES] OBJ fds : "fullDuplexSerial" PUB trial | char fds.start(31,30,0,9600) waitcnt(clkfreq/10+cnt) repeat ' for each string entered repeat idx from 0 to LAST_INDEX ' clear data array value[idx]~ idx~ ' zero array index fds.str(string(13,13,"waiting for data... ")) repeat until fds.rx == "$" ' expect a "$" if fds.rx <> "," ' expect "," else restart next repeat ' capture digits of each number repeat while (char := fds.rx) => $30 and char =<$39 value[idx] := value[idx] * 10 + char - $30 until idx++ == LAST_INDEX fds.str(string(13,"the values are: ")) ' show what we got. repeat idx from 0 to LAST_INDEX fds.tx(13) fds.dec(idx) fds.tx(":") fds.dec(value[idx]) [/FONT][/SIZE]That's the best thing about here, all the different ways to go about accomplishing the same goal. I learned a lot through this exercise and that was at least half the fun!