How to? Read an SD card a line at a time and parsing the data
SteveWoodrough
Posts: 190
Im in over my head again. Here is what I have done so far. Ive done a few exercises writing to an SD card, and reading it all back to the PST. Here is what I would like to do:
For my Magellan Bot, I want to prepare a list of way points on my lap top and write them to an SD card, in a simple txt file format. The format would be something simple like:
Waypoint, Lat, Lon
1, 123456, 123456
2, 234567, 765432
Simple, comma delimited data.
What I am having trouble with is how to read back the data from the SD a line at a time, and parse the data. Ive looked at GPS_IO as parsing example but Im not sure exactly how that works and how it stiches together a bunch of characters into a string. Once I have a string, I know how to convert that to a number, yada yada. Currently I am doing my waypoints as DAT fields in RAM but I would like to migrate to an SD card.
Any examples you all can share on this are appreciated.
Regards,
Steve
https://www.youtube.com/watch?v=M8u0VsNM0II
https://www.youtube.com/watch?v=-SFVx0i-tGE
For my Magellan Bot, I want to prepare a list of way points on my lap top and write them to an SD card, in a simple txt file format. The format would be something simple like:
Waypoint, Lat, Lon
1, 123456, 123456
2, 234567, 765432
Simple, comma delimited data.
What I am having trouble with is how to read back the data from the SD a line at a time, and parse the data. Ive looked at GPS_IO as parsing example but Im not sure exactly how that works and how it stiches together a bunch of characters into a string. Once I have a string, I know how to convert that to a number, yada yada. Currently I am doing my waypoints as DAT fields in RAM but I would like to migrate to an SD card.
Any examples you all can share on this are appreciated.
Regards,
Steve
https://www.youtube.com/watch?v=M8u0VsNM0II
https://www.youtube.com/watch?v=-SFVx0i-tGE
Comments
1: write a function to read a character at a time from the SD card, and store it into buffer, until a terminating character is found (such as '\r' or '\n').
2: write a function to parse a buffer, and split it on the first occurrence of a specified "split character (such as ',').
--- I'd make this function put the first half of the string in one buffer, and the second half in a second buffer.
3: Now, write the glue logic:
--- a) use function 1 to read in a line from the SD card
--- b) use function 2 to split the line for the first time. One buffer has the waypoint number, the second buffer has the remainder (lat, long, comma, and possibly '\r' and '\n').
--- c) use function 2 again to split the lat and long.
--- d) use a string to decimal function to convert all your character representations of numbers, to numbers.
This is a somewhat simplified outline
When the parsing is over you'll have an indexed table of values. I use this concept to parse HTTP headers.
Reading the stuff sector-wise is better, as it is only one call to get 512 bytes at once. Then you simply loop over the content to find parameters and lineend.
You could have a look at the ConfigReader in the object exchange:
http://obex.parallax.com/objects/598/
It only needs some little changes to make it read a file like you have it:
1. The ConfigReader currently only needs a space as separator (it was originally designed to read command lines from keyboard), so if you insist on your comma + space separation, you have to modify that a little bit. As Mike also suggests, each space is replaced by $00 which makes the part in front of the space a valid string which can be used with any function that works with strings.
2. The ConfigReader treats the first string found special in a way that it generates a hash value out of it. This is also due to the nature of being developed as a command line reader. It's easier/faster and needs less RAM for a command-table if you compare hashes instead of doing a strin-compare. As your first part is just a waypoint-number you could keep it as it is - or replace the hash-function in a way that the first parameter is also parsed like all following parameters.
The rest is magic. It simply parses through the file, line by line and in case a line is done you'll find all the content in a parameter array.
Parameters starting with % are parsed like a binary, parameters starting with $ are parsed like a hex-number, parameters starting with a number are parsed decimal, parameters starting with anything else are treated as strings and you'll find it's string address in the array.
If the buffer has been parsed and the line is not finished yet, the next bunch of data is loaded from SD card.
Regards,
Steve
here is a little programm (PropC3)
it works:
-1) gps-datas as vars
-2) mount sdcard
-3) look for file "gps1.txt"
-4) if file on the sd-card delete it
-5) open a new file "gps1.txt
-6) write gps-datas into file as:
$nnn.nn:nnn.nn:....
-6) close file
-7 open it for read
-8) read the string to pst.terminal
-9) close file
-10) unmount sdcard
attachment: c3-quadV2-SD-02.spin
regards
nomad
Let me see if I have one concept down correctly. I asked how strings are "stiched" together. As I played with Jon McPhalen's jm_sd_text_read.spin it occured to me that a byte aligned array forms a string merly through the act of calling the array root. I've probably butchered that, here is an example.
VAR BYTE Newbie[10] is an array of 10 bytes (0-9)
assuming that I bytefill Newbie to put zeros in the array
and if then I make:
Newbie[0] = "S"
Newbie[1] = "t"
Newbie[2] = "e"
Newbie[3] = "v"
Newbie[4] = "e"
then to get the "stiched" together string I need to only refer to the variable Newbie.
Am I getting it or still missing something?
Thanks
Steve
String functions need the address of (@) a z-string (zero-terminated string).
in the attachmant there is a OpenOffice-sheet (like an Excel-sheet) explaining how strings work
and with some basic democode how to parse a string for a certain character.
I made this maybe two years ago for another propeller-user
best regards
Stefan
That's why I like reading these forums, I learn all kinds of things, and get answers to questions I didn't even know I needed to ask.
Thanks everyone for your help .
Anyway, I’m a bit more dangerous thanks to everyone’s input. Hope these notes will help the next person along.
Regards,
Steve
char := sbuf[index]
should be replaced with
char := byte[pntr][index]
otherwise pntr is of no use at all. (similar replacement needed for sbuf[index] := 0 )
char itself is a waste of stack-space because you could come along without.
And finally I'd not call this a parser, as it does not parse anything, it's only replacing comma with stringend.
write next method. This way you will avoid a lot of bugs. This seems to be slower in progress but in the end it is much faster
because you don't waste any time on bug-searching across many lines of code.
Now replacing the comma with a zero terminates the string. Every string-out-put method stops if it cames across a zero.
If you want to access the characters behind the zero you have to go on parsing it and copying to some other string-variable.
best regards
Stefan